将百分比添加到GGplot2中的分组条形图列

时间:2016-03-03 03:11:20

标签: r ggplot2 dplyr reshape2

希望有人可以帮我标记带百分比的分组条形图的列。我无法找到一个可以成功完成工作的现有帖子。下面是基本示例数据帧的代码。

Service<-c("AS","AS","PS","PS","RS","RS","ES","ES")

Year<-c("2015","2016","2015","2016","2015","2016","2015","2016")

Q1<-c("Dissatisfied","Satisfied","Satisfied","Satisfied","Dissatisfied","Dissatisfied","Satisfied","Satisfied")

Q2<-c("Dissatisfied","Dissatisfied","Satisfied","Dissatisfied","Dissatisfied","Satisfied","Satisfied","Satisfied")

Example<-data.frame(Service,Year,Q1,Q2)

接下来,我用Reshape2将其熔化,以便我可以沿x轴绘制Q1和Q2列变量。然后我创建了一个带有ggplot2的基本分组条形图,其中y轴为计数,然后是年份。

ExampleM<-melt(Example,id.vars=c("Service","Year"))

ggplot(ExampleM,aes(x=variable,stat="identity",fill=value)) + 
  geom_bar(position="dodge") + facet_grid(~Year)

我挣扎的是如何添加列标签。具体来说,我想知道如何添加基本频率计数以及百分比。不是一起,而是一个或另一个。我无法做任何工作。我尝试过使用&#34; + geom_text(aes(labels =&#34;但我不知道该放什么标签,因为我使用了stat =&#34; identity&#34; in ggplot代码。

另外,对于百分比,我是否需要先用dplyr计算它,还是可以计算ggplot代码中的百分比?我对R中的标签也不太了解,所以不确定如何添加实际的%符号。

希望有人能告诉我实现这一切的基本方法!

1 个答案:

答案 0 :(得分:8)

您可以使用stat_count geom="text"将计数添加为文本。 ..count..ggplot为保存计数值而创建的内部变量。下面的示例显示了如何使用stat_count添加计数和百分比,当然,您可以选择仅包含其中一个。

stat="identity"aes内没有做任何事情。你通常把它放在geom里面。但在这种情况下,您不希望stat="identity",因为您实际上希望ggplot计算每个类别中的值的数量。如果您使用的数据框的列已包含每个类别的计数,则可以将stat="identity"geom_bar一起使用。

要创建标签文字,请使用paste0将计算出的值(例如,..count../sum(..count..)*100为百分比)与%符号等文字相结合。此外,在这种情况下,我使用换行符\n将百分比和计数放在单独的行上。 sprintf是一种格式化函数,在这种情况下会生成四舍五入到一位小数的值。 1

ggplot(ExampleM, aes(x=variable, fill=value)) + 
  geom_bar(position="dodge") + 
  stat_count(aes(label=paste0(sprintf("%1.1f", ..count../sum(..count..)*100),
                              "%\n", ..count..), y=0.5*..count..), 
             geom="text", colour="white", size=4, position=position_dodge(width=1)) +
  facet_grid(~Year)

enter image description here

以下是您预先汇总数据并在绘制数据时使用stat="identity"的示例:假设您需要在每个季度内使用百分比,而不是百分比是所有值的百分比。让我们也堆叠条形图并将百分比添加到条形图中:

首先,创建数据摘要。我们将使用dplyr,以便我们可以使用链接(%>%)运算符。我们会计算值的数量,计算Yearvariable的每个组合中的百分比,我们还会添加n.pos来为堆积条中的文本位置提供y值曲线图。

library(dplyr)

summary = ExampleM %>% group_by(Year, variable, value) %>%
  tally %>%
  group_by(Year, variable) %>%
  mutate(pct = n/sum(n),
         n.pos = cumsum(n) - 0.5*n)

现在为情节。请注意,我们提供y=n。由于我们已对数据进行了预先汇总(而不是在geom_bar内计算了计数和百分比),因此我们需要stat="identity"

ggplot(summary, aes(x=variable, y=n, fill=value)) +
  geom_bar(stat="identity") +
  facet_grid(.~Year) + 
  geom_text(aes(label=paste0(sprintf("%1.1f", pct*100),"%"), y=n.pos), 
            colour="white") 

enter image description here

1 您可以使用round代替,但我更喜欢sprintf,因为即使小数部分为零,它在小数位也保持为零,而{{1}当小数部分为零时,只返回整数部分。例如,比较roundround(3.04, 1)

更新:要回答评论中的问题:

  1. 第二个“group_by line”的原因是什么?我们计算了Year,variable和value的每个组合的计数。现在,我们想知道,在年份和变量的每个组合中,有多少百分比具有价值=“满意”,百分比有多少=“不满意”。为此,我们只想按年份和变量进行分组。

  2. 解释sprintf("%1.1f", 3.04)行。这是我们计算每个百分比标签的y位置的地方。我们希望标签位于每个条形图的中间,但条形图是堆叠的。如果我们仅使用y=n.pos,则标签将位于每个条形区域的顶部。我们减去cumsum(n),以便每个标签的y位置将减少包含该标签的条形部分高度的一半。

    这是一个例子:假设我们有三个高度分别为1,2和3的条形区域(按顺序从下到上堆叠),我们想要计算标签的y位置。

    0.5*n

    这给出了在每个条形区域内垂直居中标签的y位置。

  3. 如何按百分比的降序排列x轴列?默认情况下,ggplot通过h = 1:3 cumsum(h) # 1 3 6 0.5 * h # 0.5 1.0 1.5 cumsum(h) - 0.5 * h # 0.5 2.0 4.5 变量类别的排序来排序离散的x轴。对于字符变量,排序将按字母顺序排列。对于因子变量,排序将是因子级别的排序。

    在我的示例中,x的级别如下:

    summary$variable

    要按levels(summary$variable) [1] "Q1" "Q2" 重新排序,一种方法是使用pct功能。比较这些(使用上面的摘要数据框):

    reorder

    请注意,在第二个图中,“Q1”和“Q2”的顺序现在已经反转。但是,请注意左侧面板中的Q1堆栈较高,而在右侧面板中,Q2堆栈较高。使用刻面,您可以在每个面板中获得相同的x轴排序,通过比较所有Q1值的总和总和所有Q2值。 Q2的总和较小,因此它们先行。使用summary$pct2 = summary$pct + c(0.3, -0.15, -0.45, -0.4, -0.1, -0.2, -0.15, -0.1) ggplot(summary, aes(x=variable, y=pct2, fill=value)) + geom_bar(position="stack", stat="identity") + facet_grid(~Year) ggplot(summary, aes(x=reorder(variable, pct2), y=pct2, fill=value)) + geom_bar(position="stack", stat="identity") + facet_grid(~Year) 时会发生同样的情况,但我使用“堆栈”可以更容易地看到发生了什么。下面的例子有望帮助澄清事情。

    position="dodge"

    有关通过设置因子顺序排序轴值的更多信息,this blog post可能会有所帮助。