Hen*_*ndy 6 r ggplot2 ggrepel abline
现有问题询问有关在以下位置标记单个geom_abline()内容的问题ggplot2:
这些都没有达到我想要向散点图添加多条参考线的用例,目的是允许对斜率范围内的点进行轻松分类。这是该图的可重现示例:
library(ggplot2)
set.seed(123)
df <- data.frame(
x = runif(100, 0, 1),
y = runif(100, 0, 1))
lines <- data.frame(
intercept = rep(0, 5),
slope = c(0.1, 0.25, 0.5, 1, 2))
p <- ggplot(df, aes(x = x, y = y)) +
geom_point() +
geom_abline(aes(intercept = intercept, slope = slope),
linetype = "dashed", data = lines)
p
Run Code Online (Sandbox Code Playgroud)
由于我发现无法通过其他问题以编程方式执行此操作,因此我通过数据框“缩放”手动方法,使用反复试验来找出合理的标签位置。
labels <- data.frame(
x = c(rep(1, 3), 0.95, 0.47),
y = c(0.12, 0.28, 0.53, 1, 1),
label = lines$slope)
p + geom_text(aes(label = label), color = "red", data = labels)
Run Code Online (Sandbox Code Playgroud)
还有比反复试验更好的方法吗?虽然这对于 5 行来说还算不错,但我仍然必须在导出时进一步重新调整,因为 R 会话中的原型与生成的图像之间的绘图纵横比和间距不同。程序化标签将提供巨大帮助。
对于一些想法:
c(0, 1),以对应于沿线的位置ggplot2是否可以从对象内部(我不熟悉)中提取最小/最大 x/y 位置作为计算位置的“作弊”?本质上,如果我知道 的像素位置(0, intercept),我就已经知道斜率,因此对于这个例子,我只需要知道max(x)或 的像素位置max(y),具体取决于我们触及周界的位置ggrepel,它找出了如何在试图避免重叠的同时标记点这是一个查看新产品的好机会geomtextpath,它看起来真的很酷。它有一堆几何图形可以沿着不同类型的路径放置文本,因此您可以将标签投影到线条上。
但是,我找不到按照您想要的方式设置 hjust 参数的好方法:文本根据绘图的范围而不是文本所在的路径对齐。在这种情况下,默认的 hjust = 0.5 意味着标签位于 x = 0.5(因为 x 范围是 0 到 1;不同的范围会有不同的位置)。您可以进行一些调整,但我很快就让标签离开了绘图的范围。如果在中间或中间附近可以,那么这是一个看起来相当不错的选择。
library(ggplot2)
library(geomtextpath)
library(dplyr)
# identical setup from the question
p +
geom_textabline(aes(intercept = intercept, slope = slope, label = as.character(slope)),
data = lines, gap = FALSE, offset = unit(0.2, "lines"), text_only = TRUE)
Run Code Online (Sandbox Code Playgroud)

或者,由于您已经有了直线方程,因此您可以做一些代数来找到坐标。求解 x(其中 y 为其最大值),并求解 y(其中 x 为其最大值);对于其中的每一个,使用pmin将它们限制在图表的范围内。例如,斜率 = 0.5 的线在 x = 2 之前不会达到 y = 1,而 x = 2 位于图表之外,因此将其限制为绘图的最大 x。如何定义 max 可能有所不同:可能是数据中包含的最大值,您也可以从保存的绘图对象中提取该最大值(不确定是否存在这些不同的情况),或者可以从面板布局或中断。或者更多想法如何提取 ggplot2 对象的绘图轴范围?。这取决于你。
# y = intercept + slope * x
xmax <- max(df$x)
# or layer_scales(p)$x$get_limits()[2] for data range
# or ggplot_build(p)$layout$panel_params[[1]]$y.range[2] for panel range
ymax <- max(df$y)
lines_calc <- lines %>%
mutate(xcalc = pmin((ymax - intercept) / slope, xmax),
ycalc = pmin(intercept + slope * xmax, ymax))
p +
geom_text(aes(x = xcalc, y = ycalc, label = as.character(slope)),
data = lines_calc, vjust = 0, nudge_y = 0.02)
Run Code Online (Sandbox Code Playgroud)
