ggplot2:为每组添加平均线

28
library(ggplot2)

orderX <- c("A" = 1, "B" = 2, "C" = 3)
y <- rnorm(20)
x <- as.character(1:20)
group <- c(rep("A", 5), rep("B", 7), rep("C", 5), rep("A", 3))
df <- data.frame(x, y, group)
df$lvls <- as.numeric(orderX[df$group])

ggplot(data = df, aes(x=reorder(df$x, df$lvls), y=y)) + 
geom_point(aes(colour = group)) + 
geom_line(stat = "hline", yintercept = "mean", aes(colour = group))
我想创建这样的图表: graph with averages for each group 当我不需要重新排序X值时,它可以正常工作,但是当我使用重新排序时,它就不再起作用了。

我认为你在这里使用reorder是错误的,因为它只会重新排列X,而不是groups或Y。这将用错误的Y绘制错误的X! - Alex Brown
除非X仅表示索引,否则请勿在图中使用它(改用抖动?) - Alex Brown
那么我的使用重新排序是错误的。在我的真实数据中,x上的值是每个单独测量的标签,我希望看到它们。这些标签在组内的顺序并不重要。 - wligtenberg
也许另一个导致它在我的情况下无法工作的原因是我的x值不是数字,而是字符。 - wligtenberg
1
+1 一个简洁的问题,带有示例数据和图片。如果可能的话,每个都给予+1。 - Alex Brown
2个回答

18
从您的问题来看,我认为df$x与您的数据无关,特别是如果您可以重新排序的话。那么,将group用作x如何?并且使用jitter来实际分离点的x位置:
ggplot(data=df, aes(x=group,y=y,color=group)) + geom_point() +
geom_jitter(position = position_jitter(width = 0.4)) +
geom_errorbar(stat = "hline", yintercept = "mean",
  width=0.8,aes(ymax=..y..,ymin=..y..))

由于hline比较复杂,我使用了errorbar代替h_line(并将ymax和ymin折叠为y)。如果有更好的解决方案,欢迎分享。

alt text


更新

如果您想保留X的顺序,请尝试此解决方案(带有修改后的X)。

df$x = factor(df$x)

ggplot(data = df, aes(x, y, group=group)) + 
facet_grid(.~group,space="free",scales="free_x") + 
geom_point() + 
geom_line(stat = "hline", yintercept = "mean")

alt text


这确实几乎是我想要的,但是我希望能够在x轴上看到原始的x值。 - wligtenberg
当您进行上述重新排序时,数据会混乱。您应该对原始数据框进行排序,而不仅仅是x值。您想要在图表中交错显示x值吗?如果是这样,您想把平均值放在哪里? - Alex Brown
你在哪里找到 geom_line(stat="hline", yintercept="mean") 的文档?这真的很酷,我以前从未见过。 - Alex Brown
我实际上记不得了,明天会在工作的机器上查一下。肯定在浏览器历史记录里面。 :) - wligtenberg
这是我找到的地方:http://learnr.wordpress.com/2009/07/02/ggplot2-version-of-figures-in-lattice-multivariate-data-visualization-with-r-part-3/ - wligtenberg
我已经运行了你的代码,但是geom_line对于平均值给出了这个错误:Error in tapply(1:nrow(data), splitv, list) : arguments must have same length。你有什么想法吗?另外,为什么在问题中xas char,这会使得在分面中的x按字母顺序排序,如1 10 ..2 20 .. - Pablo Marin-Garcia

8

很遗憾,在ggplot2 2.x版本中,这种方法已经失效。

以下代码正好提供了我想要的内容,但需要进行一些额外的前期计算:

library(ggplot2)
library(data.table)

orderX <- c("A" = 1, "B" = 2, "C" = 3)
y <- rnorm(20)
x <- as.character(1:20)
group <- c(rep("A", 5), rep("B", 7), rep("C", 5), rep("A", 3))
dt <- data.table(x, y, group)
dt[, lvls := as.numeric(orderX[group])]
dt[, average := mean(y), by = group]
dt[, x := reorder(x, lvls)]
dt[, xbegin := names(which(attr(dt$x, "scores") == unique(lvls)))[1], by = group]
dt[, xend := names(which(attr(dt$x, "scores") == unique(lvls)))[length(x)], by = group]

ggplot(data = dt, aes(x=x, y=y)) + 
    geom_point(aes(colour = group)) +
    facet_grid(.~group,space="free",scales="free_x") + 
    geom_segment(aes(x = xbegin, xend = xend, y = average, yend = average, group = group, colour = group))

生成的图片:

在此输入图片描述


10
我不确定这个方法是否能够完全解决你的问题,但我找到了一个新的使用ggplot2 v2.1.0的解决方案来解决类似的问题:stat_summary(fun.y = "mean", fun.ymin = "mean", fun.ymax= "mean", size= 0.3, geom = "crossbar") - Lauren Samuels
1
我尝试过那个,它会在x轴上每个项目创建一条水平线。原因是x轴是离散的。 - wligtenberg

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