Skip to content

Instantly share code, notes, and snippets.

@GuangchuangYu
Last active August 26, 2015 13:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GuangchuangYu/b7a99692afedb034b7f9 to your computer and use it in GitHub Desktop.
Save GuangchuangYu/b7a99692afedb034b7f9 to your computer and use it in GitHub Desktop.
embed subview in ggplot2
require(grid)
require(ggplot2)
require(magrittr)

theme_transparent <- function(...) {
    theme(panel.background = element_rect(
              fill = "transparent",
              colour = NA),
          plot.background = element_rect(
              fill = "transparent",
              colour = NA), ...)
}

p <- ggplot(data=data.frame(x=c(0, 10), y=c(0, 10)), aes(x, y))+geom_blank()

dd <- data.frame(x=LETTERS[1:3], y=1:3)
pie <- ggplot(dd, aes(x=1, y, fill=x)) + geom_bar(stat="identity", width=1) + coord_polar(theta="y")
pie <- pie + ggtree::theme_tree() + xlab(NULL) + ylab(NULL) + theme_transparent(axis.line=element_blank())


x <- sample(2:9)
y <- sample(2:9)
width <- sample(seq(0.1, 0.2, length.out=length(x)), length(x))
height <- width


grid.newpage()
grid.draw(ggplotGrob(p))

for (i in seq_along(x)) {
    pushViewport(vp=viewport(x=x[i]/10, y=y[i]/10, width=width[i], height=height[i]))
    grid.draw(ggplotGrob(pie))
    upViewport()
}

subview <- function(mainview, subview, x, y, width=.1, height=.1) {
    xrng <- mainview$data$x %>% range %>% diff %>% abs
    yrng <- mainview$data$y %>% range %>% diff %>% abs
   
    xmin = x - width*xrng
    xmax = x + width*xrng
    ymin = y - height*yrng
    ymax = y + height*yrng

    mainview + annotation_custom(
        ggplotGrob(subview),
        xmin=xmin, xmax=xmax,
        ymin=ymin, ymax=ymax)
}



for (i in seq_along(x)) {
    p <- subview(p, pie, x[i], y[i], width[i], height[i])
}


p$layers %>% length

## [1] 9

print(p)

@GuangchuangYu
Copy link
Author

pushViewport didn't support putting the subview by specifying x-y coordinates and it's hard to adjust the position to the exact x-y coordinates we anticipated.

The subview function is easy to use and works on x-y coordinates. But it seems that there is a bug in ggplot2 that it can't draw the figure properly.

@GuangchuangYu
Copy link
Author

referring to tidyverse/ggplot2#1256, adding different name works.

subview <- function(mainview, subview, x, y, width=.1, height=.1, name="subview") {
    xrng <- mainview$data$x %>% range %>% diff %>% abs
    yrng <- mainview$data$y %>% range %>% diff %>% abs

    xmin = x - width*xrng
    xmax = x + width*xrng
    ymin = y - height*yrng
    ymax = y + height*yrng

    mainview + annotation_custom(
        editGrob(ggplotGrob(subview), name=name),
        xmin=xmin, xmax=xmax,
        ymin=ymin, ymax=ymax)
}


p <- ggplot(data=data.frame(x=c(0, 10), y=c(0, 10)), aes(x, y))+geom_blank()
for (i in seq_along(x)) {
    p <- subview(p, pie, x[i], y[i], width[i], height[i], name=i)
}
print(p)

@GuangchuangYu
Copy link
Author

fixed in tidyverse/ggplot2@cc25a9c. No need to specify name manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment