首页 > 解决方案 > 计算距离并添加线条ggplot

问题描述

我试图找出一种更好的方法来制作下图,而无需在 ggplot 中手动输入距离和线段。下面的代码将创建图表,但线条和文本标注是手动任务,不适用于我正在使用的大型数据集。

df<- data.frame(x=c(1,2,3,4,5,6,7,8,9),y=c(2,5,2,5,2,5,2,5,2),z=c('a','b','a','b','a','b','a','b','a'))

ggplot(df,aes(x,y,color=z))+geom_segment(aes(x = 2, y = 2, xend = 2, yend = 5),color='blue',size=1)+
  geom_segment(aes(x = 1, y = 2, xend = 3, yend = 2),color='blue',size=1)+
  geom_point(size=5)+scale_x_continuous(breaks = c(1,2,3,4,5,6,7,8,9,10,11))+
  annotate("text", x = 2, y = 2, label = "2 feet",size=6)+
  annotate("text", x = 2, y = 3.5, label = "3 feet",size=6)


图形

是的,我想标记的不仅仅是两个部分。大多数点将通过分组位于相同/相似的 y 轴定位上,例如所有红点将位于 2 上,绿点位于 3.5 上,蓝点位于 6 上。抱歉没有澄清,我想提供一个更简单的问题。模式可能不同,例如两者之间可能有中间行。

我添加了另一个图表来更好地解释我的问题。

df<- data.frame(x=c(1,2,1,3,3,3.5,5,6,5),y=c(2,3.5,6,2,3.5,6,2,3.7,6),z=c('a','b','c','a','b','c','a','b','c'))

ggplot(df,aes(x,y,color=z))+geom_segment(aes(x = 2, y = 2, xend = 2, yend = 3.5),color='blue',size=1)+
  geom_segment(aes(x = 1, y = 2, xend = 3, yend = 2),color='blue',size=1)+
  geom_segment(aes(x = 2, y = 3.5, xend = 2, yend = 6),color='blue',size=1)+
  geom_segment(aes(x = 1, y = 6, xend = 3.5, yend = 6),color='blue',size=1)+
  geom_segment(aes(x = 2, y = 3.5, xend = 6, yend = 3.5),color='blue',size=1)+
  geom_point(size=5)+scale_x_continuous(breaks = c(1,2,3,4,5,6,7,8,9,10,11))+
  annotate("text", x = 2, y = 2, label = "2 feet",size=5)+
  annotate("text", x = 2, y = 2.75, label = "1.5 feet",size=5)+
  annotate("text", x = 2, y = 4.75, label = "2.5 feet",size=5)+
  annotate("text", x = 2.2, y = 6.2, label = "2.5 feet",size=5)+
  annotate("text", x = 2.5, y = 3.6, label = "1 foot",size=5)+
  annotate("text", x = 4.5, y = 3.6, label = "3 feet",size=5)+
  expand_limits(y = c(1, 7))+scale_y_continuous(breaks = c(1,2,3,4,5,6,7))+
  theme_bw()+  theme(legend.position = 'bottom')

扩展的

标签: rggplot2

解决方案


我会使用一个函数来解决这个问题,该函数将索引值作为输入并相应地添加段和文本。要将多个图层添加到 中ggplot,请将图层放入列表中。

我还没有想出一个好方法来解决你关于在线之间创建辅助线的问题(比如你的例子中的垂直线),但它应该可以帮助你开始你的道路。

这是一个函数,它采用索引值并使用这些值来指定段的位置和反映距离的文本。

add_annotation <- function(index1, index2) {
  x1 = df[index1, 1]   # x1/x2/y1/y2 defined here for shorthand later
  x2 = df[index2, 1]
  y1 = df[index1, 2]
  y2 = df[index2, 2]

  # the function will return the last object it creates, ie this list with two objects
  list(            
    annotate("segment", color = "blue",
      x = x1, xend = x2,
      y = y1, yend = y2),

    annotate("text", color = "black", size = 5,
      x = (x1 + x2) / 2, y = (y1 + y2) / 2,
      label = paste(
        round(sqrt((x1 - x2) ^ 2 + (y1 - y2) ^ 2), digits = 1),
        "feet")
    )
  )
}

我们可以使用它一次指定一个段和标签...

ggplot(df,aes(x,y,color=z)) + 
  geom_point(size = 5) +
  add_annotation(2, 1)

在此处输入图像描述

或使用向量一次性指定一堆:

ggplot(df,aes(x,y,color=z)) + 
  geom_point(size = 5) +
  add_annotation(2, c(1,3:9))

在此处输入图像描述

我们可以输入起始和结束索引的向量,以获取示例中的所有点对点线:

ggplot(df,aes(x,y,color=z)) + 
  geom_point(size = 5) +
  add_annotation(index1 = c(1, 2, 3, 5), 
                 index2 = c(4, 5, 6, 8))

在此处输入图像描述

添加垂直线需要更多的思考。好奇其他人是否对如何解决这个问题有好的想法。


推荐阅读