在循环中使用多个geom_segment丰富ggplot2图表?

12

我成功地使用以下内容创建了一个图形:

# suppose I have a p <- ggplot(data=df, ...) then the following works 
# I get those two segments plotted correctly
p <- p + geom_segment(aes(x=1,y=103,xend=1,yend=107))
p <- p + geom_segment(aes(x=5,y=103,xend=5,yend=107))

然而,如果我这样做:

values <- c(1, 5)
for (i in values) {
   p <- p + geom_segment(aes(x=i,y=103,xend=i,yend=107))
}

它不起作用,只创建了最后一个片段。有人能指导一下这里出了什么问题吗?

2个回答

20
这与aes()值的惰性求值有关。你绑定了变量i,但在循环中实际上并没有对它进行任何操作。这些映射直到你实际上打印p才会被解析。本质上,这意味着它们都被绑定到i,并且在循环退出后,i将具有最后一次循环期间的值。
因此,问题真正出在这里不应该使用aes(),因为你并不需要活动绑定。只需要在aes()之外设置xxend值即可。(而且由于y是常量,它们也应该在aes()之外)。
values <- c(1, 5)
for (i in values) {
   p <- p + geom_segment(x=i, y=103, xend=i, yend=107)
}

我发布的内容将修复它。在循环中不要在geom_segment()中使用aes() - MrFlick
这正是我所想的。你知道为什么在for循环中添加print语句或使用force不能解决问题吗? - csgillespie
@csgillespie 因为在这种情况下,你仍然绑定到变量 i,而不是值。只有在实际绘制图形时,aes才能强制解析名称。在这种情况下,force有时很有用,但由于aes的非标准评估,它在这种情况下无法帮助。 - MrFlick

18

另一种方法是完全避免使用循环。您可以将分段数据打包到与主数据不同的数据框中,并使用 aes() 一次性绘制所有内容,如下所示:

segment_data = data.frame(
    x = c(1, 5),
    xend = c(1, 5), 
    y = c(103, 103),
    yend = c(107, 107)
)

p = ggplot(df, ...) +
geom_segment(data = segment_data, aes(x = x, y = y, xend = xend, yend = yend))

3
这看起来更好。我甚至无法让另一个答案工作! - aaiezza
1
@SkyWalker,你能把这个设为答案吗? - Taylor White

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接