Skip to content

Instantly share code, notes, and snippets.

@k-barton
Last active February 13, 2021 02:35
Show Gist options
  • Save k-barton/1bd47f788d7c304dcb926a93aff06f63 to your computer and use it in GitHub Desktop.
Save k-barton/1bd47f788d7c304dcb926a93aff06f63 to your computer and use it in GitHub Desktop.
Create a subplot within the current plotting region (using base graphics).
#' @param expr an \R expression to produce the plot content.
#' @param fig numeric of length 1 or 2. The proportion of the plotting region to
#' be taken as the subplot plotting region (horizontal, vertical).
#' @param pos subplot position as a keyword, including "top", "bottom", "left",
#' "right". Empty string for centered plot.
#' @param inset numeric of length 1 or 2, giving inset distance(s) from the
#' margins in inches.
subplot <-
function(expr, fig = .33, pos = "topleft", inset = c(0, 0)) {
fig <- rep(fig, length.out = 2L)
xl <- diff(grconvertX(c(0, 1), from = "npc", to = "lines"))
yl <- diff(grconvertY(c(0, 1), from = "npc", to = "lines"))
if(!missing(inset)) {
inset <- rep(inset, length.out = 2L)
xi <- grconvertX(inset[1L], from = "inches", to = "lines")
yi <- grconvertY(inset[2L], from = "inches", to = "lines")
} else
xi <- yi <- 0
mar <- par("mar")
.haspos <- function(a, p) any(grepl(a, p, fixed = TRUE))
mar[c(2L, 4L)] <- mar[c(2L, 4L)] + xi
mar[c(1L, 3L)] <- mar[c(1L, 3L)] + yi
sx <- xl * (1 - fig[1L])
sy <- yl * (1 - fig[2L])
if(.haspos("left", pos)) {
mar[4L] <- mar[4L] + sx
} else if(.haspos("right", pos)) {
mar[2L] <- mar[2L] + sx
} else
mar[c(2L, 4L)] <- mar[c(2L, 4L)] + (sx / 2)
if(.haspos("bottom", pos)) {
mar[3L] <- mar[3L] + sy
} else if(.haspos("top", pos)) {
mar[1L] <- mar[1L] + sy
} else
mar[c(1L, 3L)] <- mar[c(1L, 3L)] + (sy / 2)
mf <- min(fig)
op <- par(mar = mar, cex = if(mf < .5) .66 else if(mf < 1) .88 else 1,
new = TRUE)
on.exit(par(op))
if(!missing(expr)) eval.parent(substitute(expr))
}
@k-barton
Copy link
Author

Example:

x <- rnorm(100)
y <- rnorm(100, sd = 2)
plot(x, y, axes = FALSE)
# add a histogram of x in the upper right corner:
subplot(fig = .4, inset = c(.05, .05), pos = "topright", {
    hist(x, col = 2:3, main = NA, axes = FALSE, ann = FALSE)
    axis(3)
    axis(4)
    box()
})
# add thin y-density plot along y-axis:
usr <- par("usr")
subplot(fig = c(.2, 1), pos = "left", {
    plot.new()
    plot.window(0:1, usr[3:4], yaxs = "i", xaxs = "i")
    d <- density(y)
    polygon(c(0, d$y, 0), c(usr[1], d$x, usr[2]), col = "black")
})
box()
axis(1)
axis(2)

subplot

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