ggplot2:在每组的堆叠条形图中显示相对百分比

ggplot2: show relative % in a stacked barplot per group

我正在尝试为每个组绘制一个基本条形图。

由于值非常大,我想显示 对于每个柱状图 (即组),柱状图 中每个组的 % .
我设法显示了总数的百分比,但这不是我所期望的:在每个栏中,我希望 % 的总和等于 100%。

有没有不改变数据帧的简单方法?

(DF <- data.frame( year = rep(2015:2017, each = 4), 
                   Grp = c("Grp1", "Grp2", "Grp3", "Grp4"),
                   Value = trunc(rnorm(12, 2000000, 100000))) )


ggplot(DF) +
  geom_bar(aes(x = year, y = Value, fill = Grp), 
               stat = "identity", 
               position = position_stack()) +
  geom_text(aes(x = year, y = Value, group = Grp, 
                label = percent(Value/sum(Value))) ,
                position = position_stack(vjust = .5))

使用 position = "fill" 将比例转换为比例,使用 scale_y_continuous(labels = percent_format()) 将比例转换为百分比。

DF <- data.frame( year = rep(2015:2017, each = 4), 
                   Grp = c("Grp1", "Grp2", "Grp3", "Grp4"),
                   Value = trunc(rnorm(12, 2000000, 100000)))

library(ggplot2)
library(scales)
ggplot(DF, aes(year, Value, fill = Grp)) +
    geom_bar(stat = "identity", position = "fill") +
    geom_text(aes(label = percent(Value / sum(Value))),
              position = position_fill()) +
    scale_y_continuous(labels = percent_format())

您可以按年份为百分位数创建一个新变量:

library(dplyr)
library(ggplot2)
library(scales)

DF <- DF %>% group_by(year) %>% mutate(ValuePer=(Value/sum(Value))) %>% ungroup()

ggplot(DF, aes(year, ValuePer, fill = Grp)) +
  geom_bar(stat = "identity", position = "fill") +
  geom_text(aes(label = percent(ValuePer)),
        position = position_fill())+
  scale_y_continuous(labels = percent_format())

我会为每个柱使用单个 geom_text,同时使用 dplyryear(柱)过滤数据。检查是否是您需要的:

(DF <- data.frame( year = rep(2015:2017, each = 4), 
                   Grp = c("Grp1", "Grp2", "Grp3", "Grp4"),
                   Value = trunc(rnorm(12, 2000000, 100000))) )
library(dplyr)

ggplot(DF) +
  geom_bar(aes(x = year, y = Value, fill = Grp), 
           stat = "identity", 
           position = position_stack()) +
  geom_text(data = DF %>% filter(year == 2015),
    aes(x = year, y = Value, 
                label = scales::percent(Value/sum(Value))) ,
            position = position_stack(vjust = .5)) +
  geom_text(data = DF %>% filter(year == 2016),
            aes(x = year, y = Value, 
                label = scales::percent(Value/sum(Value))) ,
            position = position_stack(vjust = .5)) +
  geom_text(data = DF %>% filter(year == 2017),
            aes(x = year, y = Value, 
                label = scales::percent(Value/sum(Value))) ,
            position = position_stack(vjust = .5))

这里不需要参数 group。可能有更优雅的解决方案,但这是我能想到的解决方案。告诉我这是否是您正在等待的输出:

也许创建一个新列来进行正确的计算。我无法弄清楚如何在 aes() 内部进行计算,就像您刚才计算总体百分比的方式一样,Value 应该按 year 分组。

至少你自己得到了 Y 轴的实际值和 Year 分组的 % inside bars。我建议通过堆叠这样的东西来更改此标签:

scale_y_continuous(breaks = seq(0,8*10^6,10^6),
                 labels = c(0, paste(seq(1,8,1),'M')))

结果如下:

你可以适应你的环境。

好的,集齐你所有的技巧,我终于明白了: 我需要调整我的 DF,这是我想避免的,但它仍然很简单,所以它有效

library(dplyr)
library(ggplot2)
library(scales)

DF <- DF %>% group_by(year) %>% mutate(ValuePer=(Value/sum(Value))) %>% ungroup()

ggplot(DF, aes(year, Value, fill = Grp)) +
  geom_bar(stat = "identity", position = "stack") +
  geom_text(aes(label = percent(ValuePer)),
            position = position_stack()) +
  scale_y_continuous(labels = unit_format("M", 1e-6) )