[R] Placement of legend in base plot()
Helmut Schütz
he|mut@@chuetz @end|ng |rom beb@c@@t
Tue May 31 15:07:08 CEST 2022
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
--
Ing. Helmut Schütz
BEBAC – Consultancy Services for
Bioequivalence and Bioavailability Studies
Neubaugasse 36/11
1070 Vienna, Austria
E helmut.schuetz using bebac.at <mailto:helmut.schuetz using bebac.at>
W https://bebac.at <https://bebac.at/>
F https://forum.bebac.at <https://forum.bebac.at/>
More information about the R-help
mailing list