ggplot分面累积直方图

5
我有以下数据。
set.seed(123)
x = c(rnorm(100, 4, 1), rnorm(100, 6, 1))
gender = rep(c("Male", "Female"), each=100)
mydata = data.frame(x=x, gender=gender)

我希望使用ggplot绘制两个累积直方图(一个为男性,另一个为女性)。以下是我尝试过的代码:

ggplot(data=mydata, aes(x=x, fill=gender)) + stat_bin(aes(y=cumsum(..count..)), geom="bar", breaks=1:10, colour=I("white")) + facet_grid(gender~.)

但我得到了这个图表: enter image description here 显然,这不正确。如何获得正确的图表呢,就像这样: enter image description here 谢谢!
3个回答

1
我建议对每个分组的每个区间预先计算出累加和(cumsum),然后使用 geom_histogram 进行绘图。
mydata %>%
    mutate(x = cut(x, breaks = 1:10, labels = F)) %>%      # Bin x
    count(gender, x) %>%                                   # Counts per bin per gender
    mutate(x = factor(x, levels = 1:10)) %>%               # x as factor
    complete(x, gender, fill = list(n = 0)) %>%            # Fill missing bins with 0
    group_by(gender) %>%                                   # Group by gender ...
    mutate(y = cumsum(n)) %>%                              # ... and calculate cumsum
    ggplot(aes(x, y, fill = gender)) +                     # The rest is (gg)plotting
    geom_histogram(stat = "identity", colour = "white") + 
    facet_grid(gender ~ .)

enter image description here


1
Maurits,感谢您的快速回答,但是您的条形图并不完全符合间隔。此外,如果可能的话,我正在寻找一种更简单的方法,避免显式计算累积频率。 - Alfredo Sánchez
1
"Maurits,感谢您的快速回答,但是您的条形图并没有完全适合间隔。" 你是什么意思?数字应该居中于条形上,这才是直方图的正确方式。而在您的情况下,数字位于条形之间,这是不正确的。 - Maurits Evers
在这种情况下,x变量是连续的,因此我绘制了一个直方图。在直方图中,条形的宽度必须是间隔的宽度。例如,第一根条的底部必须是从1到2的间隔,而不应该居中于2。无论如何,我对此并不太担心。对我来说更重要的是是否有更简单的方法来做到这一点。再次感谢! - Alfredo Sánchez
“在直方图中,条形的宽度必须是间隔的宽度”这句话从何而来?这是不正确的,也与直方图的标准定义和解释完全不一致。无论如何,我已经给出了我的建议和一个简单的解决方案。在ggplot内进行数据操作是不好的实践,我肯定不会称之为更简单的解决方案,但这显然是你的选择。” - Maurits Evers
@AlfredoSánchez 嗯,这是一个奇怪的定义(和参考)。更传统地说(例如 Pearson、Fisher 等),在直方图中(Fisher 称其为“频率图”),您将连续变量分成“箱子”,并绘制每个箱子的计数。箱号是一种有序变量(即有序分类变量),对应于连续变量的一个区间。对于等大小的间隔(如此处的情况),宽度完全无关紧要。作为轴标签,您可以显示箱号(就像我所做的那样),或者区间的左右边界。两者都是可以接受的。 - Maurits Evers
显示剩余2条评论

0

和 @Edo 一样,我也是来到这里寻找这个问题的答案。@Edo 的解决方案对我非常有帮助,非常棒。但是我在这里补充一些内容,以增加信息密度并允许在不同情况下进行比较。

library(ggplot2)

set.seed(123)
x = c(rnorm(100, 4, 1), rnorm(50, 6, 1))
gender = c(rep("Male", 100), rep("Female", 50))
grade = rep(1:3, 50)
mydata = data.frame(x=x, gender=gender, grade = grade)

ggplot(mydata, aes(x, 
                   y = ave(after_stat(density), group, FUN = cumsum)*after_stat(width),
                   group = interaction(gender, grade),
                   color = gender)) +
    geom_line(stat = "bin") +
    scale_y_continuous(labels = scales::percent_format()) +
    facet_wrap(~grade)

我重新调整了y,使得累积图总是以100%结束。否则,如果组的大小不同(就像原始示例数据中一样),那么累积图的最终高度也不同。这会掩盖它们的相对分布。

其次,我使用geom_line(stat="bin")而不是geom_histogram(),这样我可以在一个面板上放置多条线。这样我就可以轻松比较它们。

最后,因为我还想跨facet进行比较,所以我需要确保ggplot组变量使用的不仅仅是color=gender。我们使用group = interaction(gender, grade)手动设置它。 plot_output_of_code


-1

一百万年后的回答...

我也遇到了同样的问题,正在寻找解决方案,最终我自己解决了它,所以在这里分享一下,以便其他人需要时可以参考。

需要注意的是:不需要进行任何预处理!

ggplot(mydata) +
    geom_histogram(aes(x = x, y = ave(..count.., group, FUN = cumsum), 
                       fill = gender, group = gender),
                       colour = "gray70", breaks = 1:10) +
    facet_grid(rows = "gender")

enter image description here


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