简体   繁体   English

如何将每个类别的百分比添加到堆叠条形图(ggplot2)(用于“非百分比”堆叠图)

[英]How to add percent of each category to stacked bar chart (ggplot2) (for a “non-percent” stacked chart)

How can I add the percent of each category to a stacked bar chart of the axis and not the fill. 如何将每个类别的百分比添加到堆积的轴条形图中,而不是填充中。 For example, I have the following dataset: 例如,我有以下数据集:

df<-structure(list(age_group = structure(c(3L, 3L, 5L, 3L, 5L, 5L, 
5L, 3L, 5L, 5L, 4L, 4L, 4L, 3L, 5L), .Label = c("65+", "55-64", 
"45-54", "35-44", "25-34", "18-24"), class = "factor"), Gender = c("F", 
"M", "M", "M", "F", "M", "M", "M", "F", "M", "M", "F", "M", "F", 
"M")), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-15L), .Names = c("age_group", "Gender"))

dat <- aggregate(list(value = 1:NROW(df)), df[c("age_group", "Gender")], length)
dat$proportion <- ave(dat$value, dat$age_group, FUN = function(x) (x/sum(x)*100))
dat$proportionR <- round(dat$proportion, digits =0)

dat<-dat %>%
  group_by(age_group) %>%
  mutate(age_per = sum(value)) %>%
  ungroup() %>%
  mutate(age_per = round((age_per/sum(value))*100))

ggplot(dat, aes(x = age_group, y = value, fill = Gender)) +
  geom_col() + coord_flip() + ylab("Visits 2018-2019") +xlab("") +
  scale_fill_manual(values= c("#740404", "#AB6868", "#D5B3B3"), labels = c("Females", "Males", "N/A")) +
  theme(legend.title=element_blank()) +
  geom_text(aes(label = paste0(age_per, "%")), hjust = 2.7, position = "stack", color = "white", size =5)

在此处输入图片说明

What I would like is an automated way to add the total percent for each group from the y-axis while disregarding the percentages within each group. 我想要的是一种自动方法,可以从y轴添加每个组的总百分比 ,而忽略每个组中的百分比。 My work flow identifies the correct percent but replicates it over each subgroup within the stack. 我的工作流程确定了正确的百分比,但将其复制到堆栈中的每个子组上。 I would like the geom_text to be placed in the white space right after bar ends. 我希望将geom_text放在小节结束后的空白处。

Just as a note, the question is not a duplicate of the following SO Q - Adding percentage labels to a bar chart in ggplot2 -because this question deals with percents when there are stacked groups within each bar (the former is just for bar plots). 请注意,该问题不是以下SO Q的重复内容- 在ggplot2中向条形图中添加百分比标签 -因为当每个条中有堆叠组时,此问题处理的是百分比(前者仅用于条形图) 。

Also, emphasis on automated. 另外,强调自动化。 I can do the following but in my real data set I have many more age group intervals, which makes the below approach untenable. 我可以执行以下操作,但是在我的真实数据集中,我有更多的年龄段间隔,这使得以下方法难以成立。

ggplot(dat, aes(x = age_group, y = value, fill = Gender)) +
  geom_col() + coord_flip() + ylab("Visits 2018-2019") +xlab("") +
  scale_fill_manual(values= c("#740404", "#AB6868", "#D5B3B3"), labels = c("Females", "Males", "N/A")) +
  theme(legend.title=element_blank()) +
  geom_text(aes(y= 5.2, x=1, label = "33%"), color = "#740404", size =5) +
  geom_text(aes(y= 3.2, x=2, label = "20%"), color = "#740404", size =5) +
  geom_text(aes(y= 7.2, x=3, label = "47%"), color = "#740404", size =5) 

在此处输入图片说明

Consider annotating using a grouping percent calculation. 考虑使用分组百分比计算进行注释。 Since you need to add three numbers with a series of six, annotate can diverge from grouping series. 由于您需要将三个数字与六个序列相加,因此annotate可以与分组序列有所不同。 Also, use the appropriate gender and age group percentages. 另外,使用适当的性别和年龄组百分比。 And below another base::ave call replaces your dplyr::group_by : 在另一个base::ave调用下面替换您的dplyr::group_by

agg_df <- aggregate(list(value = 1:NROW(df)), df[c("age_group", "Gender")], length)

dat <- within(agg_df, {
  proportion <- ave(value, age_group, FUN = function(x) (x/sum(x)*100))
  proportionR <- round(proportion, digits=0)

  age_per <- round((ave(value, age_group, Gender, FUN=sum) / sum(value)) * 100)      
  grp_pct <- round((ave(value, age_group, FUN=sum) / sum(value)) * 100)
})

dat
#   age_group Gender value grp_pct age_per proportionR proportion
# 1     45-54      F     2      33      13          40   40.00000
# 2     35-44      F     1      20       7          33   33.33333
# 3     25-34      F     2      47      13          29   28.57143
# 4     45-54      M     3      33      20          60   60.00000
# 5     35-44      M     2      20      13          67   66.66667
# 6     25-34      M     5      47      33          71   71.42857



ggplot(dat, aes(x = age_group, y = value, fill = Gender)) +
  geom_col() + coord_flip() + ylab("Visits 2018-2019") +xlab("") +
  scale_fill_manual(values= c("#740404", "#AB6868", "#D5B3B3"), 
                    labels = c("Females", "Males", "N/A")) +
  theme(legend.title=element_blank()) +
  geom_text(aes(label = paste0(age_per, "%")), hjust = 2.7, 
            position = "stack", color = "white", size =5) + 
  annotate("text", x=1, y=5.25, label = paste0(dat$grp_pct[[1]], "%")) +
  annotate("text", x=2, y=3.25, label = paste0(dat$grp_pct[[2]], "%")) +
  annotate("text", x=3, y=7.25, label = paste0(dat$grp_pct[[3]], "%"))

绘图输出


For dynamic annotating, you may have to use the functional form of ggplot using Reduce where the + (not actually the plus arithmetic operator) is exposed as +.gg() operator. 对于动态注释,您可能必须使用ggplot Reduceggplot功能形式,其中+ (实际上不是加号算术运算符)被公开为+.gg()运算符。 Then, call mapply to iterate through unique(grp_pct) to pass in x coordinate location and annotate label. 然后,调用mapply以遍历unique(grp_pct)以传递x坐标位置并注释标签。 Remaining challenge is that the best y coordinate is unknown. 剩下的挑战是最佳y坐标是未知的。

Reduce(ggplot2:::`+.gg`, 

       c(list(ggplot(dat, aes(x = age_group, y = value, fill = Gender)),
              geom_col(), coord_flip(), ylab("Visits 2018-2019"), xlab(""),
              scale_fill_manual(values= c("#740404", "#AB6868", "#D5B3B3"),
                              labels = c("Females", "Males", "N/A")),
              theme(legend.title=element_blank()),
              geom_text(aes(label = paste0(age_per, "%")), hjust = 2.7, 
                        position = "stack", color = "white", size =5) 
         ),
         Map(function(x_loc, g_lab) annotate("text", x=x_loc, y=7.25,
                                                label = paste0(g_lab, "%")),
             seq(length(unique(dat$grp_pct))), unique(dat$grp_pct)
         )
       )
)

绘图输出

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM