ggplot用geom_bar中的百分比替换计数

Posted

技术标签:

【中文标题】ggplot用geom_bar中的百分比替换计数【英文标题】:ggplot replace count with percentage in geom_bar 【发布时间】:2014-09-06 17:03:48 【问题描述】:

我有一个数据框d:

> head(d,20)
   groupchange Symscore3
1            4         1
2            4         2
3            4         1
4            4         2
5            5         0
6            5         0
7            5         0
8            4         0
9            2         2
10           5         0
11           5         0
12           5         1
13           5         0
14           4         1
15           5         1
16           1         0
17           4         0
18           1         1
19           5         0
20           4         0

我正在策划的:

ggplot(d, aes(groupchange, y=..count../sum(..count..),  fill=Symscore3)) +
  geom_bar(position = "dodge") 

以这种方式,每个条形代表其在整个数据中的百分比。

相反,我希望每个条形代表一个相对百分比;即用groupchange = k 获得的bar 的总和应该是1

【问题讨论】:

请考虑更新答案以反映下面更准确和简洁的答案,使用 position = "fill" 特别是对于专门询问 ggplot 包的问题 否则,当使用 position = "fill" 时,当 geom_bar 函数本身计算比例时,人们依赖手动汇总 请考虑更新所选答案,以免低效方法持续存在整个社区。我想引起您和社区的注意。 @HoneyBuddha 我不同意我的方法是否效率低下。这取决于imo的情况。对于这个简单的用例,您可能是对的。但是,在处理大型数据集时(根据我的经验),先总结然后绘制会更有效。此外,当总结比简单的百分比更复杂时,最好先总结然后绘制。 【参考方案1】:

首先总结和转换你的数据:

library(dplyr)
d2 <- d %>% 
  group_by(groupchange, Symscore3) %>% 
  summarise(count = n()) %>% 
  mutate(perc = count/sum(count))

然后你可以绘制它:

ggplot(d2, aes(x = factor(groupchange), y = perc*100, fill = factor(Symscore3))) +
  geom_bar(stat="identity", width = 0.7) +
  labs(x = "Groupchange", y = "percent", fill = "Symscore") +
  theme_minimal(base_size = 14)

这给出了:


或者,您可以使用 scales 包中的 percent 函数:

brks <- c(0, 0.25, 0.5, 0.75, 1)

ggplot(d2, aes(x = factor(groupchange), y = perc, fill = factor(Symscore3))) +
  geom_bar(stat="identity", width = 0.7) +
  scale_y_continuous(breaks = brks, labels = scales::percent(brks)) +
  labs(x = "Groupchange", y = NULL, fill = "Symscore") +
  theme_minimal(base_size = 14)

给出:

【讨论】:

鉴于下面更准确的答案,使用 position = "fill" - 特别是对于专门询问 ggplot 包的问题,​​我相信这个答案可能会导致整个社区持续存在低效方法.我想引起您和社区的注意。 @HoneyBuddha 我确实按照 OP 的要求使用了 ggplot2。这并不意味着我不能使用其他工具/包。关于效率低下,见my comment under the question。 对不起,我并不是要建议您不使用 ggplot2。也许,您可以编辑以至少包含 position = "fill" 选项 - 因为,大多数人只看到最接受的答案,可能会错过他们可能对许多新 R 用户有帮助的非常简单的解决方案。我只是想建议作为一个中间立场。如果您这样做,请告诉我,以便我删除这些 cmets。 @HoneyBuddha 我怀疑大多数人是否只看接受的答案:我发布了相当多的答案,至少获得了几个赞成票(其中一些甚至超过了接受的答案)。此外,在position = "fill" 选项中进行编辑对我来说就像是在锻炼。这也被 SO 上的大多数人认为是不公平的行为。【参考方案2】:

如果您的目标是用最少的代码进行可视化,请使用 position = "fill" 作为geom_bar() 中的参数。

如果你想在组内百分比,@Jaap 的 dplyr 答案是正确的答案。

这是一个使用上述数据集复制/粘贴的可重现示例:

library(tidyverse)

d <- data_frame(groupchange = c(4,4,4,4,5,5,5,4,2,5,5,5,5,4,5,1,4,1,5,4),
                Symscore3 = c(1,2,1,2,0,0,0,0,2,0,0,1,0,1,1,0,0,1,1,0))

ggplot(d, aes(x = factor(groupchange), fill = factor(Symscore3))) +
  geom_bar(position="fill")

【讨论】:

对于使用小型数据集的人来说,在代码清晰度/方法效率方面,此选项可能优于公认的答案。 这是使用geom_bar()在计数和比例之间快速转换的好方法【参考方案3】:

我们还可以在比例中添加标签,而无需在源数据框中显式计算它们。

library(tidyverse)

d <- data_frame(groupchange = c(4,4,4,4,5,5,5,4,2,5,5,5,5,4,5,1,4,1,5,4),
                Symscore3 = c(1,2,1,2,0,0,0,0,2,0,0,1,0,1,1,0,0,1,1,0)) %>%
  mutate_all(as.character)  # treat the numbers as categories

ggplot(d, aes(x=groupchange, fill=Symscore3)) +
  geom_bar(position="fill") +
  geom_text(
    aes(label=signif(..count.. / tapply(..count.., ..x.., sum)[as.character(..x..)], digits=3)),
    stat="count",
    position=position_fill(vjust=0.5)) +
  labs(y="Proportion")

本解决方案中的geom_text标签改编自here。

【讨论】:

以上是关于ggplot用geom_bar中的百分比替换计数的主要内容,如果未能解决你的问题,请参考以下文章

ggplot关于群体百分比的条形图

是否可以用ggplot2在R中以科学计数形式显示绘图geom_text数据标签?

如何双重填充具有两个特征的 geom_bar

GGplot geom_bar 以均匀间距堆叠项目

按值重新排序 geom_bar ggplot2 中的条形图

按值重新排序 geom_bar ggplot2 中的条形图