9

I'm trying to recreate this base-produced plot with ggplot, but I want to use a workflow more elegant than the the one demonstrated here, which relies directly on grid::viewport().

enter image description here

Using ggsubplot, I tried:

require(ggplot2)
require(ggsubplot)
d = data.frame(x = sort(rlnorm(300)), y = sort(rlnorm(300)), grp = 1)
ggplot(d, aes(x, y)) + geom_point() + theme_bw() +
  scale_x_continuous(limits=c(0, 10)) + scale_y_continuous(limits=c(0, 10)) +
  geom_subplot(data=d, aes(x=5, y=1, group = grp, subplot = geom_point(aes(x, y))), width=4, height=4)

which produced the following disappointing result:

enter image description here

Obviously needs some work, but if axes, labels and grid are added to the subplot its not far off. Any idea how to do these? I can't find any examples of this, and ggsubplot defaults to removing these elements. Thanks in advance.

Josh O'Brien
  • 159,210
  • 26
  • 366
  • 455
geotheory
  • 22,624
  • 29
  • 119
  • 196
  • I used the `viewport` in combination with ggplot, I was not even aware of `ggsubplot` – Ananta Dec 20 '13 at 16:39
  • try the last example in `?annotation_custom` – baptiste Dec 21 '13 at 00:17
  • Possible duplicate of [It is possible to create inset graphs?](http://stackoverflow.com/questions/5219671/it-is-possible-to-create-inset-graphs) – zx8754 Aug 19 '16 at 21:03
  • Related post: http://stackoverflow.com/questions/17041246/how-to-add-an-inset-subplot-to-topright-of-an-r-plot – zx8754 Aug 19 '16 at 21:04

3 Answers3

15

With cartesian coordinates, I would use annotation_custom

require(ggplot2)
d = data.frame(x = sort(rlnorm(300)), y = sort(rlnorm(300)), grp = 1)

main <- ggplot(d, aes(x, y)) + geom_point() + theme_bw() 

sub <- main + geom_rect(data=d[1,],xmin=0, ymin=0, xmax=5, ymax=5, 
                        fill="blue", alpha=0.5)
sub$layers <- rev(sub$layers) # draw rect below

main + annotation_custom(ggplotGrob(sub), xmin=2.5, xmax=5, ymin=0, ymax=2.5) +
  scale_x_continuous(limits=c(0, 5)) + scale_y_continuous(limits=c(0,4))

enter image description here

baptiste
  • 75,767
  • 19
  • 198
  • 294
2

you might have to play with position and color, etc, but it seems like adding reference works

ggplot(d, aes(x, y)) + geom_point() + theme_bw() +
  scale_x_continuous(limits=c(0, 10)) + scale_y_continuous(limits=c(0, 10)) +
  geom_subplot(data=d, aes(x=5, y=1, group = grp, subplot = geom_point(aes(x, y))), width=4, height=4,reference=ref_box(fill = "grey90", color = "black"))

works

Ananta
  • 3,671
  • 3
  • 22
  • 26
  • Thanks Ananta. This is the closest to what I requested so I feel obliged to award the solution. But I think Josh is right that the grid solution seems more elegant if you want a more professional looking subplot of this kind (given ggsubplot's insistence on minimising subplot chart elements). – geotheory Dec 21 '13 at 00:50
  • 1
    Note that as of 2019 geom_subplot and the ggsubplot package are dead and no longer available on CRAN. The working solution is now to use annotation_custom() as described in another answer by baptiste. – user2711915 Jul 16 '19 at 15:01
2

Is this what you had in mind?

Edit: Added @geotheory's edit to draw only 1 geom_rect(...)

You can do this with viewports in the grid package.

require(ggplot2)
set.seed(123)
d   <- data.frame(x = sort(rlnorm(300)), y = sort(rlnorm(300)), grp = 1)
ggp <- ggplot(d, aes(x, y)) + 
  geom_point() + theme_bw() +
  scale_x_continuous(limits=c(0, 5)) + 
  scale_y_continuous(limits=c(0, 5)) 

sub <- ggplot(d)+geom_point(aes(x,y))+
  theme_bw()+
# assign single row data object so only one rectangle is drawn  
  geom_rect(data=d[1,],xmin=0,ymin=0,xmax=5,ymax=5,fill="blue",alpha=0.5)

library(grid)
grid.newpage()
print(ggp)
vp <- viewport(width = .6, height = .6, x=.37, y=.06,just=c("left","bottom"))
pushViewport(vp)
print(sub,vp=vp)
jlhoward
  • 58,004
  • 7
  • 97
  • 140
  • 1
    @Ananta - Yes he did, though it's pretty poor practice to supply critical info like that in the form of a link that readers have to click through to to pick up. Ended up wasting a bit of jlhoward's time. (& FWIW, using **grid**'s mature, expressive toolset to do this seems like the **more** elegant approach to me.) – Josh O'Brien Dec 20 '13 at 21:08
  • @JoshO'Brien, yeah, I also commented in OP's question for viewport and clicked in link before answering, he might have used "rather than viewport" to save our time. – Ananta Dec 20 '13 at 21:13
  • 1
    @Ananta -- It wasted a bit of my time as well. I just edited the question to make the OP's request a bit clearer. – Josh O'Brien Dec 20 '13 at 21:19
  • Apologies for not being more explicit. I think the comments above are right that grid currently remains the more elegant solution. – geotheory Dec 21 '13 at 00:53
  • @josh-obrien can you suggest any SO guidance on the linking to external sites? It seems pretty common in SO to find links to other questions that aren't described, requiring the same effort to follow. I personally fail to see the difference, but would be interested if this has been documented. – geotheory Dec 21 '13 at 14:49
  • @geotheory -- Sorry if that came across sounding too harsh. Links are great, and my edits to your question pretty much show what I'd have preferred to have seen. As for what other SO questions do, I'd suggest keeping your standards *far* above those of the typical questioner here (as you already do ;). Cheers. – Josh O'Brien Dec 21 '13 at 17:26
  • Point taken! Thanks for the feedback. – geotheory Jan 15 '14 at 16:09