如何在条形上方添加计数以及条形内填充百分比?

时间:2019-04-21 15:49:28

标签: r ggplot2 label percentage stacked-chart

我有一些数据,其中每个观察值包含2个因子,类(A和E之间的字母)和标志(0或1)。应用了group_by(classes,flag)和summary(frequency = n())之后,我得到了一个与此类似的数据帧:

classes <-as.factor(c("A", "A", "B", "B", "C", "C", "D", "D", "E", "E"))
    flag <- as.factor(rep(c(0,1),10))
    quantity <- c(856, 569, 463, 125, 795, 313, 1000, 457, 669, 201)
    df <- data.frame(classes, flag, quantity)

我设法通过以下代码获得了想要的图表(有序条形,每个级别的水平条形,每个条形填充标志的比例):

    ggplot(df, aes(x = reorder(classes, -quantity), y = quantity)) +
      geom_bar(aes(fill = as.factor(flag)), stat="identity") +
      theme(axis.text.x=element_text(angle = 90, hjust = 1)) +
      labs(x = NULL, y = "Quantity", fill = "flag") +
      scale_fill_manual(values=c("firebrick","dodgerblue4"), 
      labels=c("1"="Yes","0"="No"))+
      theme(axis.ticks = element_blank())

但是,我不确定如何使用geom_text()来包括每个小节顶部的总计数和小节内填充值的比例。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

我不知道一种自动执行此操作的方法,可能是在图外计算比例和总和最简单的方法。

对图外的类进行重新排序更加容易,以便您的文本可以取代因子级别。

df$x <- reorder(df$classes, -df$quantity)

接下来,您可以计算所需的统计信息。下面我假设如果按类划分df,则总是按flag = 0flag = 1的顺序排列,因此我们可以将x[2]/x[1]作为比例。

text_df <- data.frame(
  class = sapply(split(df$classes,  df$classes), unique),
  sum   = sapply(split(df$quantity, df$classes), sum),
  prop  = sapply(split(df$quantity, df$classes), function(x){x[2]/(x[1]+x[2])})
)

然后,让text_df$classdf$x进行相同的排序。

text_df$class <- factor(text_df$class, levels = levels(df$x))

然后我们使绘图类似于您的示例,请记住我们之前对x变量进行了重新排序:

ggplot(df, aes(x = x, y = quantity)) +
  geom_bar(aes(fill = as.factor(flag)), stat="identity") +
  theme(axis.text.x=element_text(angle = 90, hjust = 1)) +
  labs(x = NULL, y = "Quantity", fill = "flag") +
  scale_fill_manual(values=c("firebrick","dodgerblue4"), 
                    labels=c("1"="Yes","0"="No"))+
  theme(axis.ticks = element_blank())

并为文本添加两个几何,一个为比例,一个为总和;两者都有y偏移。

 +geom_text(data = text_df, 
            aes(x = class, 
                y = sum + 100, # some offset
                label = sum)) +
  geom_text(data = text_df,
            aes(x = class, 
                y = sum - 100, # opposite offset
                label = scales::percent(prop)))

我认为可以达到目的。祝你好运!