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/

______________________________________________
[email protected] mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to