问题描述
在一个上一个问题中,我问如何获得用户坐标中的边界线位置.我以line2user
函数的形式收到了一个很好的答案.但是,当x轴或y轴处于对数刻度时,我无法弄清楚如何修改该功能以使其工作.
In a previous question I asked how to get margin line locations in user coordinates. I received an excellent answer in the form of the line2user
function. However, I cannot figure out how to modify the function to work when either the x or y axis is on a log scale.
我做了一些修改以适应对数刻度轴:
I have made a couple modifications to accommodate a log-scaled axis:
line2user <- function(line, side, log = "") {
lh <- par('cin')[2] * par('cex') * par('lheight')
x_off <- diff(grconvertX(0:1, 'inches', 'user'))
y_off <- diff(grconvertY(0:1, 'inches', 'user'))
usr <- par('usr') ## Added by me
if (grepl("x", log)) usr[1:2] <- 10^usr[1:2] ## Added by me
if (grepl("y", log)) usr[3:4] <- 10^usr[3:4] ## Added by me
switch(side,
`1` = usr[3] - line * y_off * lh,
`2` = usr[1] - line * x_off * lh,
`3` = usr[4] + line * y_off * lh,
`4` = usr[2] + line * x_off * lh,
stop("Side must be 1, 2, 3, or 4", call.=FALSE))
}
但是,我无法弄清楚如何正确调整xoff
和yoff
变量以绘制正确的线条.插图:
However, I cannot figure out how to properly adjust the xoff
and yoff
variables to draw the proper lines. Illustration:
setup_plot <- function(log = "") {
par(mar = c(2, 10, 2, 2), oma = rep(2, 4))
plot.new()
plot.window(xlim = c(1, 10), ylim = c(1, 10), log = log)
box(which = "plot", lwd = 2, col = "gray40")
box(which = "figure", lwd = 2, col = "darkred")
box(which = "outer", lwd = 2, col = "darkgreen")
text(x = 0.5, y = 0.5,
labels = "Plot Region",
col = "gray40", font = 2)
mtext(side = 3, text = "Figure region", line = 0.5, col = "darkred", font = 2)
mtext(side = 3, text = "Device region", line = 2.5, col = "darkgreen", font = 2)
for (i in 0:9) {
mtext(side = 2, col = "darkred", text = paste0("Line", i), line = i)
}
}
setup_plot(log = "x")
abline(v=line2user(line=0:9, side=2, log = "x"), xpd=TRUE, lty=2)
在考虑以下示例后,压缩线才有意义:
The compressed lines make sense after considering the following example:
plot(10)
diff(grconvertX(0:1, 'inches', 'user'))
## [1] 0.08121573 (on my device)
plot(10, log = "x")
diff(grconvertX(0:1, 'inches', 'user'))
## [1] 0.0297354 (on my device)
使用对数刻度轴时如何获得正确的x_off
和y_off
值?
How can I get the correct x_off
and y_off
values when working with a log-scaled axis?
推荐答案
这是可与对数刻度和线性刻度轴配合使用的版本.诀窍是用npc
坐标而不是user
坐标表示线位置,因为当轴在对数刻度上时,后者当然不是线性的.
Here's a version that works with log-scale and linear scale axes. The trick is to express line locations in npc
coordinates rather than user
coordinates, since the latter are of course not linear when axes are on log scales.
line2user <- function(line, side) {
lh <- par('cin')[2] * par('cex') * par('lheight')
x_off <- diff(grconvertX(c(0, lh), 'inches', 'npc'))
y_off <- diff(grconvertY(c(0, lh), 'inches', 'npc'))
switch(side,
`1` = grconvertY(-line * y_off, 'npc', 'user'),
`2` = grconvertX(-line * x_off, 'npc', 'user'),
`3` = grconvertY(1 + line * y_off, 'npc', 'user'),
`4` = grconvertX(1 + line * x_off, 'npc', 'user'),
stop("Side must be 1, 2, 3, or 4", call.=FALSE))
}
以下是一些示例,它们通过mar=c(5, 5, 5, 5)
应用于您的setup_plot
:
And here are a couple of examples, applied to your setup_plot
with mar=c(5, 5, 5, 5)
:
setup_plot()
axis(1, line=5)
axis(2, line=5)
abline(h=line2user(0:4, 1), lty=3, xpd=TRUE)
abline(v=line2user(0:4, 2), lty=3, xpd=TRUE)
abline(h=line2user(0:4, 3), lty=3, xpd=TRUE)
abline(v=line2user(0:4, 4), lty=3, xpd=TRUE)
setup_plot(log='x')
axis(1, line=5)
axis(2, line=5)
abline(h=line2user(0:4, 1), lty=3, xpd=TRUE)
abline(v=line2user(0:4, 2), lty=3, xpd=TRUE)
abline(h=line2user(0:4, 3), lty=3, xpd=TRUE)
abline(v=line2user(0:4, 4), lty=3, xpd=TRUE)
setup_plot(log='y')
axis(1, line=5)
axis(2, line=5)
abline(h=line2user(0:4, 1), lty=3, xpd=TRUE)
abline(v=line2user(0:4, 2), lty=3, xpd=TRUE)
abline(h=line2user(0:4, 3), lty=3, xpd=TRUE)
abline(v=line2user(0:4, 4), lty=3, xpd=TRUE)
setup_plot(log='xy')
axis(1, line=5)
axis(2, line=5)
abline(h=line2user(0:4, 1), lty=3, xpd=TRUE)
abline(v=line2user(0:4, 2), lty=3, xpd=TRUE)
abline(h=line2user(0:4, 3), lty=3, xpd=TRUE)
abline(v=line2user(0:4, 4), lty=3, xpd=TRUE)
这篇关于获取日志空间中的边距线位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!