[R] Placement of legend in base plot()
John Fox
j|ox @end|ng |rom mcm@@ter@c@
Tue May 31 15:35:50 CEST 2022
Dear Helmut,
I'm not sure why you're seeing an error, but replacing the last several
commands in your code with
legend(loc, legend = lgd, x.intersp = 0, title = paste("n =",
n.pts[1]), bg = bg)
works perfectly fine for me. I suspect that the example you posted
differs in some respect from the code that produces the error.
I hope this helps,
John
On 2022-05-31 9:07 a.m., Helmut Schütz wrote:
> Dear all,
>
> I try to figure out where to automatically place the legend in a scatter
> plot.
> If there is large variability, points may cover the legend. Hence, I
> assess in which section the fewest points are.
> Example:
>
> set.seed(27) # for reproducibility
> n <- 25
> slope <- +1
> sd <- 10
> x <- 1:n
> mean.x <- mean(x)
> y <- slope * x + rnorm(n = n, mean = mean.x, sd = sd)
> mean.y <- mean(y)
> top <- which(y >= mean.y)
> bottom <- which(y < mean.y)
> left <- which(x <= mean.x)
> right <- which(x > mean.x)
> n.pts <- data.frame("topleft" = sum(top %in% left),
> "topright" = sum(top %in% right),
> "bottomleft" = sum(bottom %in% left),
> "bottomright" = sum(bottom %in% right))
> loc <- names(n.pts)[n.pts == min(n.pts)]
> if (length(loc) > 1) loc <- loc[1] # arbitrary selection (better
> approaches?)
> bg <- "transparent"
> lgd <- paste("Pretty long legend line number #", 1:3)
> plot(x, y, type ="n", pch = 19, xlab = "", ylab = "", axes = FALSE,
> frame.plot = TRUE)
> abline(h = mean.y, v = mean.x)
> mtext(text = paste0("top left: n = ", n.pts[1], ", right: n = ", n.pts[2]),
> side = 3, line = 1)
> mtext(text = paste0("bottom left: n = ", n.pts[3], ", right: n = ",
> n.pts[4]),
> side = 1, line = 1)
> mtext(text = paste0("bottom: n = ", sum(n.pts[3:4]),
> ", top = ", sum(n.pts[1:2])), side = 2, line = 1)
> points(x, y, pch = 19, col = "red", cex = 1.25)
> print(n.pts); loc
> if (loc == "topleft") legend("topleft", legend = lgd, x.intersp = 0,
> title = paste("n =", n.pts[1]), bg = bg)
> if (loc == "topright") legend("topright", legend = lgd, x.intersp = 0,
> title = paste("n =", n.pts[2]), bg = bg)
> if (loc == "bottomleft") legend("bottomleft", legend = lgd, x.intersp = 0,
> title = paste("n =", n.pts[3]), bg = bg)
> if (loc == "bottomright") legend("bottomright", legend = lgd, x.intersp
> = 0,
> title = paste("n =", n.pts[4]), bg = bg)
>
> Unfortunately, one of the keywords in legend() instead of x, y cannot be
> a variable.
> Hence, legend(loc, ...) throws an error...
> Error in match.arg(x, c("bottomright", "bottom", "bottomleft", "left", :
> 'arg' must be of length 1
> ... and I had to resort to conditionally specify all 4.
> Given.
>
> Problems:
> 1. If there are the same number of points in sections, I select the
> first though another might lead to fewer overlapping points. Is there a
> better approach?
> 2. I know how to get the width/height of the legend box with (..., plot
> = FALSE) but couldn't figure out how to squeeze it between points where
> enough space might exist.
>
> Best,
> Helmut
--
John Fox, Professor Emeritus
McMaster University
Hamilton, Ontario, Canada
web: https://socialsciences.mcmaster.ca/jfox/
More information about the R-help
mailing list