ggplot2:`position_nudge` 对应于`linewidth`

问题描述 投票:0回答:1

我正在寻找一种将

geom_segment()
geom_point()
组合并定义
position
的方法,使其始终连接到
linewidth

Reprex

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
的值如何,情况都是如此?

感谢您的考虑。

r ggplot2
1个回答
0
投票

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
以适应新形状。

© www.soinside.com 2019 - 2024. All rights reserved.