Title: How to add miniature to plot and repeat this for multiple plots side by side?
Tags: r;plot
Question: There's a nice answer around to plot a miniature plot within a plot. I wrapped it in a function which works fine for a single plot.
myPlot <- function(x, y) {
# main plot
plot(x)
# calculate position of inset
pp <- par(&quot;plt&quot;)
x0 <- pp[2] - (pp[2] - pp[1]) * 0.225
x1 <- pp[2] - .01
y0 <- pp[4] - (pp[4] - pp[3]) * 0.225
y1 <- pp[4] - .01
# set position for inset
op <- par(fig=c(x0, x1, y0, y1), mar=c(0, 0, 0, 0), new=TRUE)
# add inset grey background
plot.new()
u <- par(&quot;usr&quot;)
rect(u[1], u[2], u[4], u[3], col=&quot;grey80&quot;)
# add inset
par(new=TRUE)
plot(y, col=2)
par(op)
myPlot(x, y)
However, when I useMap to loop over several data lists, in order to make multiple plots of this type side by side, there seems to be a mess with the pars. The miniature appears as a new plot and not within the main plot. Also a new device is opened after one iteration (i.e. old plot gets overwritten).
op1 <- par(mfrow=c(1, 2))
Map(function(x, y) myPlot(x, y), list(d0, d0), list(d0_inset, d0_inset))
par(op1)
When I use Map(function(x, y) myPlot(x, y), list(d0, d0), list(d0_inset, d0_inset)) alone, though, there are two perfect plots in the plot queue (of RStudio). Thus the plot.new() and par(new=TRUE) might not be the issue here.
What I actually want is this:
myPlot() should throw a number of main plots with miniatures inside corresponding to the length of the data lists when using Map and fit it into the par(mfrow=...).
Does anyone have a clue how to solve this using base R functionalities?
x <- data.frame(x = rnorm(150, sd=5), y = rnorm(150, sd=5))
y <- data.frame(x = rnorm(1500, sd=5), y = rnorm(1500, sd=5))

Here is the accepted answer: There's a couple of points here Jay. The first is that if you want to continue to use mfrow then it's best to stay away from using par(fig = x) to control your plot locations, since fig changes depending on mfrow and also forces a new plot (though you can override that, as per your question). You can use plt instead, which makes all co-ordinates relative to the space within the fig co-ordinates.
The second point is that you can plot the rectangle without calling plot.new()
The third, and maybe most important, is that you only need to write to par twice: once to change plt to the new plotting co-ordinates (including a new = TRUE to plot it in the same window) and once to reset plt (since new will reset itself). This means the function is well behaved and leaves the par as they were.
Note I have added a parameter, at, that allows you to specify the position and size of the little plot within the larger plot. It uses normalized co-ordinates, so for example c(0, 0.5, 0, 0.5) would be the bottom left quarter of the plotting area. I have set it to default at somewhere near your version's location.
myPlot <- function(x, y, at = c(0.7, 0.95, 0.7, 0.95))
# Helper function to simplify co-ordinate conversions
space_convert <- function(vec1, vec2)
vec1[1:2] <- vec1[1:2] * diff(vec2)[1] + vec2[1]
vec1[3:4] <- vec1[3:4] * diff(vec2)[3] + vec2[3]
vec1
# Main plot
plot(x)
# Gray rectangle
u <- space_convert(at, par(&quot;usr&quot;))
rect(u[1], u[3], u[2], u[4], col=&quot;grey80&quot;)
# Only write to par once for drawing insert plot: change back afterwards
plt <- par(&quot;plt&quot;)
plt_space <- space_convert(at, plt)
par(plt = plt_space, new = TRUE)
plot(y, col = 2)
par(plt = plt)
So we can test it with:
x <- data.frame(x = rnorm(150, sd = 5), y = rnorm(150, sd = 5))
y <- data.frame(x = rnorm(1500, sd = 5), y = rnorm(1500, sd = 5))
myPlot(x, y)
par(mfrow = c(1, 2))
myPlot(x, y)
myPlot(x, y)
par(mfrow = c(2, 2))
for(i in 1:4) myPlot(x, y)
Comment for this answer: Works like a charm, thanks for the thorough explanation!
Comment for this answer: Fantastic approach to a problem I have long struggled with. I added this as a function to my package - allowing any plot to be embedded this way via `eval(expression()))` [link](https://github.com/marchtaylor/sinkr/blob/master/R/embedPlot.R)


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2020:00:07/25/20', 'FavoriteCount': 2.0, 'PostTypeId': 1, 'Tags': '<r><plot>', 'Title': 'How to add miniature to plot and repeat this for multiple plots side by side?', 'ViewCount': 88, 'id': 63086207, 'user_AboutMe': '<p>[UTC+01:00]</p>\n<p><em>«I\'d rather speak R than cReole!»</em></p>\n<h1>New to R?</h1>\n<ul>\n<li><a href="https://cran.r-project.org/" rel="nofollow noreferrer"><strong>R</strong></a> comes with packages <code>stats</code>, <code>graphics</code>, <code>grDevices</code>, <code>utils</code>, <code>datasets</code>, <code>methods</code>, and <code>base</code></li>\n<li>official <a href="https://cran.r-project.org/manuals.html" rel="nofollow noreferrer"><strong>Introduction to R</strong></a> provides fundamental vocabulary and grammar</li>\n<li><a href="https://cran.r-project.org/doc/contrib/Short-refcard.pdf" rel="nofollow noreferrer"><strong>Cheat sheet</strong></a>, helpful when programming, even for more experienced users</li>\n<li><a href="https://cran.r-project.org/doc/manuals/r-devel/NEWS.html" rel="nofollow noreferrer"><strong>R News</strong></a>—stay up to date!</li>\n<li><a href="https://jef.works/R-style-guide/" rel="nofollow noreferrer"><strong>I ♥ legible code</strong></a></li>\n</ul>\n<br>\n<p><sup><a href="https://rextester.com/l/r_online_compiler" rel="nofollow noreferrer"><em>Mobile R</em></a></sup></p>\n', 'user_AccountId': 8796229.0, 'user_DisplayName': 'jay.sf', 'user_Reputation': 50099.0, 'user_Views': 3877.0, 'user_id': 6574038.0}}