代码之家  ›  专栏  ›  技术社区  ›  Cyrus Mohammadian

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

  •  0
  • Cyrus Mohammadian  · 技术社区  · 7 年前

    如何将每个类别的百分比添加到轴的堆叠条形图中,而不是填充。例如,我有以下数据集:

    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)
    

    enter image description here

    我想要的是一种自动添加 总百分比 从y轴开始计算各组,忽略各组内的百分比。我的工作流程确定了正确的百分比,但会在堆栈中的每个子组上复制它。我想要 geom_text 放置在酒吧结束后的空白处。

    请注意,这个问题并不是以下问题的重复- Adding percentage labels to a bar chart in ggplot2 -因为这个问题涉及的是每个条形图中有堆叠组时的百分比(前者仅用于条形图)。

    此外,强调自动化。我可以做到以下几点,但在我的真实数据集中,我有更多的年龄组间隔,这使得下面的方法不可行。

    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) 
    

    enter image description here

    0 回复  |  直到 7 年前
        1
  •  1
  •   Parfait    7 年前

    考虑使用分组百分比计算进行注释。因为你需要把三个数和六个数相加, annotate 可以从分组系列中分离。此外,使用适当的性别和年龄组百分比。在另一个下面 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]], "%"))
    

    Plot Output


    对于动态注释,可能必须使用 ggplot 使用 Reduce 在哪里 + (实际上不是加号算术运算符)作为 +.gg() 操作人员然后打电话 mapply 反复浏览 unique(grp_pct) 传入x坐标位置并注释标签。剩下的挑战是最佳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)
             )
           )
    )
    

    Plot Output

    推荐文章