11

I have the plot 1

curve(exp(x), from=1, to=5, lwd=5)
curve(150-exp(x), from=1, to=5, lwd=5, col="darkblue",add=T)

and inside it i would like to add the following plot 2

par(mar=c(7,7,1,1))
curve(exp(x), from=1, to=5, lwd=7, xlab="chi", ylab="exp(x)", cex.lab=4,axes=F)
axis(1, labels=NA,at=c(0,5))
axis(2, labels=NA,at=c(0,150))
text(1,120,"Alpha",adj=c(0,0),cex=3)
text(3.5,10,"Beta",adj=c(0,0),cex=3)

In order to obtain the following

Combined

I would also like to make plot 2 transparent so that if there are some elements of plot 1 behind plot 2 they will still show (just like the blue line). Also important are the bigger labels of plot 2 and the absence of labels and ticks in it's axes.

Is this possible? Please only base R solutions (no ggplot2 / no lattice)

ECII
  • 10,297
  • 18
  • 80
  • 121
  • There are functions named 'subplot' in both the Teaching Demos and Hmisc packages. I don't know if they are the same code. I suspect that a background color that was full transparent would succeed but haven't tried it yet. – IRTFM Jan 12 '13 at 01:13
  • I tried to use `subplot` from `TeachingDemos` but unfortunately without success. The size and margins of the axis labels went wrong. Don't know why, could be my fault. – ECII Jan 12 '13 at 10:18

2 Answers2

18

OK, here's an example, which I plotted to a 10 by 10 inch pdf. (Part of what's frustrating about using par(fig = ) et al. is that their effects are very much dependent on the size of the plotting device.)


Edited to add some explanation:

The base graphic plotting parameter par("fig") describes/sets the location of a figure region as a proportion of the "drawing region" (which is usually the entire device, for single figure plots). It takes a length-4 vector of the form c(xmin, xmax, ymin, ymax) consisting of numbers (proportions) between 0 and 1.

Here I use grconvertX() and grconvertY() to convert x-y locations expressed in terms of the larger plot's own (a.k.a. "user") coordinate system into the "ndc" (normalized device coordinates) coordinate system. The "user" coordinate system is more human-user-friendly, while the "ndc" is (with the caveats expressed above) the coordinate system used by par("fig"). The grconvert*() calls are just there to perform the translation between them.

## pdf("fig-in-fig.pdf", width=10, height=10)
curve(exp(x), from=1, to=5, lwd=5)
curve(150-exp(x), from=1, to=5, lwd=5, col="darkblue",add=T)

## Here's the bit I added.
par(fig = c(grconvertX(c(1, 3), from="user", to="ndc"),
            grconvertY(c(50, 125), from="user", to="ndc")),
    mar = c(4,6,1,1),
    new = TRUE)

curve(exp(x), from=1, to=5, lwd=7, xlab="chi", ylab="exp(x)", cex.lab=4,axes=F)
axis(1, labels=NA,at=c(0,5))
axis(2, labels=NA,at=c(0,150))
text(1,120,"Alpha",adj=c(0,0),cex=3)
text(3.5,10,"Beta",adj=c(0,0),cex=3)
## dev.off()

enter image description here

Josh O'Brien
  • 159,210
  • 26
  • 366
  • 455
  • 1
    Great answer. Thank you very much. Would you mind adding a line or two explaining what you did there with `par(plt)` and `grconvertX` ? – ECII Jan 12 '13 at 10:25
  • 1
    @ECII -- Thanks. I just added some explanation, and edited the code to make it easier to *see* how it has the effect that it does. After playing with this yesterday and today, I've concluded that it's just something you have to experiment with quite a bit to really grasp. If you want to master it, I'd suggest making a bunch of plots (including some using `layout()` and `par(mfcol=c(2,3))`, and then examining them with frequent calls to `par("omd")`, `par("fig")`, and `par("plt")`. Also play around with `par("mar")` and then re-examine `par("plt")`, etc, etc. Good luck! – Josh O'Brien Jan 13 '13 at 01:52
  • Nice and elegant. Solved my problem as well. Thank you. – DorinPopescu Dec 01 '15 at 12:46
7

Here is one approach:

curve(exp(x), from=1, to=5, lwd=5)
curve(150-exp(x), from=1, to=5, lwd=5, col="darkblue",add=T)
par(new=TRUE)
par(oma=c(1,4,5,1))
par(mfcol=c(2,2), mfg=c(1,1))
par(mar=c(7,7,1,1))
curve(exp(x), from=1, to=5, lwd=7, xlab="chi", ylab="exp(x)", cex.lab=2,axes=F)
axis(1, labels=NA,at=c(0,5))
axis(2, labels=NA,at=c(0,150))
text(1,120,"Alpha",adj=c(0,0),cex=1.5)
text(4,10,"Beta",adj=c(0,0),cex=1.5)

Gives me this:

enter image description here

Play with the various options (especially oma and mar) to format the result to your like.

Theodore Lytras
  • 3,955
  • 1
  • 18
  • 25
  • So you set the position of plot 2 by `par(mfcol=c(2,2), mfg=c(1,1))` ? – ECII Jan 12 '13 at 00:02
  • Is there any way to fine tune more the position and the size of plot 2 ? – ECII Jan 12 '13 at 00:08
  • @ECII -- Yes, you can use `par(new = TRUE, fig=c(x1, x2, y1, y2))`, and also `plt=`, and others. Here [are](http://stackoverflow.com/questions/9747426/how-can-i-produce-plots-like-this/9748213#9748213) a [couple](http://zoonek.free.fr/blosxom/R/2006-08-10_R_Graphics.html) examples. I've never mastered the commands b/c I find **grid** viewports so much less finicky, but it can be done! – Josh O'Brien Jan 12 '13 at 00:33
  • 1
    @ECII maybe you can try use The layout() function which provides an alternative to the mfrow and mfcol settings(of course after the call to par(new=TRUE) – agstudy Jan 12 '13 at 00:38