【问题标题】:ggplot - geom_segment() with mutiple arrowsggplot - 带有多个箭头的 geom_segment()
【发布时间】:2020-04-07 10:06:37
【问题描述】:

我正在研究主成分分析 (PCA)。 我发现ggfortify 效果很好,但我想做一些手动调整。

然后尝试将 PCA 结果绘制如下:

evec <- read.table(textConnection("
  PC1        PC2        PC3
  -0.5708394 -0.6158420 -0.5430295
  -0.6210178 -0.1087985  0.7762086
  -0.5371026  0.7803214 -0.3203424"
), header = TRUE, row.names = c("M1", "M2", "M3"))

res.ct <- read.table(textConnection("
  PC1        PC2        PC3
  -1.762697 -1.3404825 -0.3098503
  -2.349978 -0.0531175  0.6890453
  -1.074205  1.5606429 -0.6406848
  2.887080 -0.7272039 -0.3687029
  2.299799  0.5601610  0.6301927"
), header = TRUE, row.names = c("A", "B", "C", "D", "E"))

require(ggplot2)
require(dplyr)
gpobj <- 
  res.ct %>%
  ggplot(mapping = aes(x=PC1, y=PC2)) +
  geom_point(color="grey30") +
  annotate(geom="text", x=res.ct$PC1*1.07, y=res.ct$PC2*1.07,
           label=rownames(res.ct))

for (i in 1:nrow(evec))
{
  PCx <- evec[i,1]
  PCy <- evec[i,2]
  axisname <- rownames(evec)[[i]]
  gpobj <- gpobj +
    geom_segment(
      data = evec[i,],
      aes(
        x = 0, y = 0,
        xend = PC1, yend = PC2
        # xend = PCx, yend = PCy  #not work as intended
      ),
      arrow = arrow(length = unit(4, "mm")),
      color = "red"
    ) +
    annotate(
      geom = "text",
      x = PCx * 1.15, y = PCy * 1.15,
      label = axisname,
      color = "red"
    )
}
gpobj

代码运行良好,但是当我尝试使用注释行 xend = PCx, yend = PCy 而不是 xend = PC1, yend = PC2 时,它无法正常运行,它没有显示所有箭头。

xend = PC1, yend = PC2 效果很好:

xend = PCx, yend = PCy 没有:

问题: 当起点和终点由环境变量指定而不是由data =中的变量名引用时,为什么geom_segment()不保持前一个箭头?

【问题讨论】:

  • 您使用的是哪个 ggplot2 版本?似乎对 3.0.0 产生相同的结果。

标签: r ggplot2


【解决方案1】:

在您使用的代码中,当 PCx / PCy 在美学映射 aes(...) 内指定时(而不是将它们硬编码为 aes(...) 之外的固定美学值,就像对 annotate 层所做的那样),实际值仅在您绘制/打印 ggplot 对象gpobj 时进行评估。

这意味着PCx / PCy 的值在 for 循环之外进行评估。至此,它们对应于它们采用的最后一个值,i = 3,这就是为什么只有一个箭头段(实际上是三个箭头相互重叠)可见的原因。将xend = PCx, yend = PCy 移到aes(...) 之外应该会获得您想要的外观。

不过,我确实想知道您为什么首先选择使用 for 循环。像下面这样的东西难道不能达到同样的目的吗?

# convert row names to explicit columns
res.ct <- tibble::rownames_to_column(res.ct)
evec <- tibble::rownames_to_column(evec)

# plot
res.ct %>%
  ggplot(mapping = aes(x=PC1, y=PC2)) +
  geom_point(color="grey30") +
  geom_text(aes(x = PC1 * 1.07, y = PC2 * 1.07,
                label = rowname)) +
  geom_segment(data = evec,
               aes(x = 0, y = 0, xend = PC1, yend = PC2, group = rowname),
               arrow = arrow(length = unit(4, "mm")),
               color = "red") +
  geom_text(data = evec,
            aes(x = PC1 * 1.15, y = PC2 * 1.15, label = rowname),
            colour = "red")

【讨论】:

  • 感谢您的出色回答。我没有意识到何时评估美学变量。你的例子让我对ggplot2有了更好的理解。 (使用 ggplot2 版本 3.1.1)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-23
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多