带有组和构面的堆叠 ggplot 条形图的百分比标签

Posted

技术标签:

【中文标题】带有组和构面的堆叠 ggplot 条形图的百分比标签【英文标题】:Percentage labels for a stacked ggplot barplot with groups and facets 【发布时间】:2021-07-01 14:34:40 【问题描述】:

我正在尝试将百分比标签添加到堆叠和多面条形图(位置='填充')。我希望每个条形显示的百分比相加。

我正在使用这样的数据集:

## recreate dataset
Village<-c(rep('Vil1',10),rep('Vil2',10))
livestock<-c('p','p','p','c','c','s','s','s','g','g',
             'p','p','c','c','s','s','s','s','g','g')
dose<-c(3,2,1,2,1,3,2,1,2,1,
        2,1,2,1,4,3,2,1,2,1)
Freq<-c(4,5,5,2,3,4,1,1,6,8,
      1,3,2,2,1,1,3,2,1,1)
df<-data.frame(Village,livestock,dose,Freq)

我成功地绘制了它并添加了标签,每个 X 变量(牲畜)的总和为 100%:

## create dose categories (factors)
df$dose<-as.character(df$dose)
df$dose[as.numeric(df$dose)>3]<-'>3'
df$dose<-factor(df$dose,levels=c('1','2','3','>3'))
## percentage barplot
ggplot(data = df, aes(x=livestock, y=Freq, fill=dose)) +
  geom_bar(position='fill', stat='identity') +
  labs(title="Given doses of different drugs in last 6months (livestock)", 
       subtitle='n=89',x="Livestock",y="Percentage",
       fill = "Nr. of\ndoses") +
  theme(axis.text.x = element_text(angle = 45, hjust=1))+ 
  scale_y_continuous(labels=percent)+
  facet_wrap(~Village)+
  geom_text(aes(label = percent(..y../tapply(..y..,..x..,sum)[..x..])),
            stat = "identity",position = position_fill(vjust=0.5))

有谁知道我可以如何更改 ggplot 中的标签代码,以便每个条形的百分比加起来为 100%?也许与..group..有关?

我尝试了类似的方法:Label percentage in faceted filled barplot in ggplot2 put I can't make it work for my data.

【问题讨论】:

【参考方案1】:

最简单的方法是预先转换您的数据,以便可以直接使用分数。

library(tidyverse)
library(scales)

# Assume df is as in example code
df <- df %>% group_by(Village, livestock) %>%
  mutate(frac = Freq / sum(Freq))

ggplot(df, aes(livestock, frac, fill = dose)) +
  geom_col() +
  geom_text(
    aes(label = percent(frac)),
    position = position_fill(0.5)
  ) +
  facet_wrap(~ Village)

如果你坚持不预先转换数据,你可以自己写一个小辅助函数。

bygroup <- function(x, group, fun = sum, ...) 
  splitted <- split(x, group)
  funned   <- lapply(splitted, fun, ...)
  funned   <- mapply(function(x, y) 
    rep(x, length(y))
  , x = funned, y = splitted)
  unsplit(funned, group)

然后您可以通过将组设置为 x 和(未记录的)PANEL 列来使用它。

library(ggplot2)
library(scales)

# Assume df is as in example code
ggplot(df, aes(livestock, Freq, fill = dose)) +
  geom_col(position = "fill") +
  geom_text(
    aes(
      label = percent(after_stat(y / bygroup(y, interaction(x, PANEL))))
    ),
    position = position_fill(0.5)
  ) +
  facet_wrap(~ Village)

【讨论】:

非常感谢!!这非常有效!我担心预处理会更多的代码,但这是非常合理的,谢谢!【参考方案2】:

只是为了添加@teunbrand的解决方案: 我按照@teunbrand 的建议计算了分数,并且效果很好。但是,我开始收到非常奇怪且持续存在的警告消息:

Warning messages:
1: Unknown or uninitialised column: `times`. 
2: Unknown or uninitialised column: `times`. 
3: Unknown or uninitialised column: `times`. 
4: Unknown or uninitialised column: `times`. 
5: Unknown or uninitialised column: `Var1`. 

我在这里阅读了这个问题,这似乎是一个已知的错误:Persistent "Unknown or uninitialised column" warnings

我可以通过取消分组并将 tibble 重新转换为数据框来消除警告。

df <- as.data.frame(df %>% group_by(Village, livestock) %>%
  mutate(frac = Freq / sum(Freq)) %>% ungroup())

【讨论】:

以上是关于带有组和构面的堆叠 ggplot 条形图的百分比标签的主要内容,如果未能解决你的问题,请参考以下文章

ggplot2:3路交互堆积条形图的分组条形图

堆叠条形图将变量转换为ggplot2 R中不相关变量的基于存在缺失的百分比

R语言ggplot2可视化堆叠的条形图(stacked bar plot)并在每一个条形图的的中间添加对应的数值值标签定位在geom_col堆叠的条形图中的每个条形段的中间

使用ggplot为数据框中的每一行创建堆叠条形图的功能

R语言ggplot2可视化:计算dataframe中每个数据列缺失值的个数使用堆叠的条形图(Stacked Barplot)可视化每个数据列的缺失值的情况(自定义堆叠条形图的形式)

R语言ggplot2可视化堆叠条形图(stacked bar plot)并且在每个条形图的顶端使用数值标签表示整个条形的加和值(sum value above the stacked bar)