我正在寻找一种将
geom_segment()
与 geom_point()
组合并定义 position
的方法,使其始终连接到 linewidth
。
library(ggplot2)
# Sample data for geom_segment
segment_data <- data.frame(
y = 1:5,
x = as.POSIXct(c("2024-04-15 08:00:00", "2024-04-15 08:15:00", "2024-04-15 08:30:00", "2024-04-15 08:45:00", "2024-04-15 09:00:00")),
xend = as.POSIXct(c("2024-04-15 09:00:00", "2024-04-15 09:15:00", "2024-04-15 09:30:00", "2024-04-15 09:45:00", "2024-04-15 10:00:00"))
)
# Sample data for geom_point
point_data <- data.frame(
y = c(1, 2, 3, 4, 5), # Adjusted y values for points
x = as.POSIXct(c("2024-04-15 08:05:00", "2024-04-15 08:20:00", "2024-04-15 08:35:00", "2024-04-15 08:50:00", "2024-04-15 09:05:00"))
)
linewidth <- 2
ggplot() +
geom_segment(segment_data, mapping = aes(x = x, xend = xend, y = y),
linewidth = linewidth) +
geom_point(point_data, mapping = aes(x = x, y = y),
shape = 25, color = "black", fill = "red", size = 5,
position = position_nudge(y = linewidth/25))
这给出了所需的图,其中点本质上是沿线段线的指示符:
在此示例中,
linewidth
为 2,微移为 linewidth/25
,这是非常任意的。我本以为linewidth/2
就足够了。
如何定义
y
的 position_nudge()
值,以便无论 linewidth
的值如何,情况都是如此?
感谢您的考虑。
TL;DR:正如 Jon Spring 所说,您需要混合使用数据单位和绝对单位才能做到这一点。这是
shape = 25
偏移量所需的公式:0.55 * unit(fontsize, "pt") + unit((lwd * .pt) / .stroke * 0.5, "pt")
。
现在来看实际例子;首先:让我们以同样的方式设置:
library(ggplot2)
# Sample data for geom_segment
segment_data <- data.frame(
y = 1:5,
x = as.POSIXct(c("2024-04-15 08:00:00", "2024-04-15 08:15:00", "2024-04-15 08:30:00", "2024-04-15 08:45:00", "2024-04-15 09:00:00")),
xend = as.POSIXct(c("2024-04-15 09:00:00", "2024-04-15 09:15:00", "2024-04-15 09:30:00", "2024-04-15 09:45:00", "2024-04-15 10:00:00"))
)
# Sample data for geom_point
point_data <- data.frame(
y = c(1, 2, 3, 4, 5), # Adjusted y values for points
x = as.POSIXct(c("2024-04-15 08:05:00", "2024-04-15 08:20:00", "2024-04-15 08:35:00", "2024-04-15 08:50:00", "2024-04-15 09:05:00"))
)
linewidth <- 2
然后我们将制作两个图。我们稍后将使用的一个,以及包含点图层的一个。
p <- ggplot() +
geom_segment(segment_data, mapping = aes(x = x, xend = xend, y = y),
linewidth = linewidth, colour = "grey50")
p2 <- p +
geom_point(point_data, mapping = aes(x = x, y = y),
shape = 25, color = "black", fill = "red", size = 5)
从最后一张图中,我们将提取图层的图形对象(grob)。从 grob 中,您可以提取计算所需的图形参数,例如点的
fontsize
和线段的 lwd
。
现在这个公式是我通过一些尝试和错误得到的,但是当
linewidth
和 size
变化时应该非常一致。我们只需将其添加到点的预先存在的 y 坐标中,然后将其绘制为自定义图层。
segments <- layer_grob(p2, i = 1)[[1]]
points <- layer_grob(p2, i = 2)[[1]]
points$y <- points$y + 0.55 * unit(points$gp$fontsize, "pt") +
unit((segments$gp$lwd * .pt) / .stroke * 0.5, "pt")
p + annotation_custom(points)
但需要注意的是,这不适用于任何形状。您可以看到圆圈漂浮在线条上方。
points$pch <- 21
p + annotation_custom(points)
创建于 2024-04-15,使用 reprex v2.1.0
要使其适用于其他形状,请调整公式中的
0.55
以适应新形状。