将百分比添加到 GGplot2 中的分组条形图列
Adding Percentages to a Grouped Barchart Columns in GGplot2
希望有人可以帮助我用百分比标记分组条形图的列。我找不到可以成功完成工作的现有 post。以下是基本示例数据框的代码。
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)
我苦恼的是如何添加列标签。具体来说,我想知道如何添加基本频率计数以及百分比。不是两者都在一起,而是一个或另一个。我无法使任何一个工作。我试过使用 "+geom_text(aes(labels=" 但我不确定要放什么作为标签,因为我在 ggplot 代码中使用了 stat="identity" 。
另外,对于百分比,我需要先用dplyr计算吗,还是我可以在ggplot代码中计算百分比?我也不太了解 R 中的标签,所以不确定如何添加实际的 % 符号。
希望有人能告诉我实现这一切的基本方法!
您可以使用 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)
这是一个预先汇总数据并在绘制数据时使用 stat="identity"
的示例:假设百分比不是所有值的百分比,而是每个季度内的百分比。让我们也堆叠条形图并将百分比作为文本添加到条形图:
首先,创建数据摘要。我们将使用 dplyr
以便我们可以使用链接 (%>%
) 运算符。我们将计算值的数量,计算 Year
和 variable
的每个组合中的百分比,我们还将添加 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")
1 你可以用 round
代替,但我更喜欢 sprintf
因为即使小数部分为零,它也会在小数位保留一个零, 而 round
returns 只是小数部分为零时的整数部分。例如,比较 round(3.04, 1)
和 sprintf("%1.1f", 3.04)
更新: 回答您评论中的问题:
第二个"group_by line"是什么原因?我们已经计算了 Year、variable 和 value 的每个组合的计数。现在,我们想知道,在 Year 和 variable 的每个组合中,value="Satisfied" 的百分比和 value="Dissatisfied" 的百分比。为此,我们只想按年份和变量分组。
解释 y=n.pos
行。这是我们计算每个百分比标签的 y 位置的地方。我们希望标签位于每个条的中间,但条是堆叠的。如果我们只使用 cumsum(n)
标签将位于每个条形部分的顶部。我们减去 0.5*n
以便每个标签的 y 位置将减少包含该标签的条形部分高度的一半。
这是一个示例:假设我们有三个高度分别为 1、2 和 3 的条形部分(按此顺序从下到上堆叠),我们想要计算标签的 y 位置。
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
这给出了在每个条形部分内垂直居中标签的 y 位置。
如何按百分比降序排列 x 轴列?默认情况下,ggplot 按 x
变量类别的顺序对离散 x 轴进行排序。对于字符变量,顺序将按字母顺序排列。对于因子变量,排序将是因子水平的排序。
在我的例子中,summary$variable
的等级如下:
levels(summary$variable)
[1] "Q1" "Q2"
要按 pct
重新排序,一种方法是使用 reorder
函数。比较这些(使用上面的摘要数据框):
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)
请注意,在第二个图中,"Q1" 和 "Q2" 的顺序现在已经颠倒了。但是,请注意,在左侧面板中,Q1 堆栈更高,而在右侧面板中,Q2 堆栈更高。通过分面,您可以在每个面板中获得相同的 x 轴排序,通过比较所有 Q1 值的 sum 和 sum 所有 Q2 值。 Q2的总和较小,所以他们先走。当您使用 position="dodge"
时也会发生同样的情况,但我使用 "stack" 以便更容易看到发生了什么。希望下面的示例有助于澄清问题。
# Fake data
values = c(4.5,1.5,2,1,2,4)
dat = data.frame(group1=rep(letters[1:3], 2), group2=LETTERS[1:6],
group3=rep(c("W","Z"),3), pct=values/sum(values))
levels(dat$group2)
[1] "A" "B" "C" "D" "E" "F"
# plot group2 in its factor order
ggplot(dat, aes(group2, pct)) +
geom_bar(stat="identity", position="stack", colour="red", lwd=1)
# plot group2, ordered by -pct
ggplot(dat, aes(reorder(group2, -pct), pct)) +
geom_bar(stat="identity", colour="red", lwd=1)
# plot group1 ordered by pct, with stacking
ggplot(dat, aes(reorder(group1, pct), pct)) +
geom_bar(stat="identity", position="stack", colour="red", lwd=1)
# Note that in the next two examples, the x-axis order is b, a, c,
# regardless of whether you use faceting
ggplot(dat, aes(reorder(group1, pct), pct)) +
geom_bar(stat="identity", position="stack", colour="red", lwd=1) +
facet_grid(.~group3)
ggplot(dat, aes(reorder(group1, pct), pct, fill=group3)) +
geom_bar(stat="identity", position="stack", colour="red", lwd=1)
有关通过设置因子顺序对轴值进行排序的更多信息,this blog post 可能会有所帮助。
希望有人可以帮助我用百分比标记分组条形图的列。我找不到可以成功完成工作的现有 post。以下是基本示例数据框的代码。
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)
我苦恼的是如何添加列标签。具体来说,我想知道如何添加基本频率计数以及百分比。不是两者都在一起,而是一个或另一个。我无法使任何一个工作。我试过使用 "+geom_text(aes(labels=" 但我不确定要放什么作为标签,因为我在 ggplot 代码中使用了 stat="identity" 。
另外,对于百分比,我需要先用dplyr计算吗,还是我可以在ggplot代码中计算百分比?我也不太了解 R 中的标签,所以不确定如何添加实际的 % 符号。
希望有人能告诉我实现这一切的基本方法!
您可以使用 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)
这是一个预先汇总数据并在绘制数据时使用 stat="identity"
的示例:假设百分比不是所有值的百分比,而是每个季度内的百分比。让我们也堆叠条形图并将百分比作为文本添加到条形图:
首先,创建数据摘要。我们将使用 dplyr
以便我们可以使用链接 (%>%
) 运算符。我们将计算值的数量,计算 Year
和 variable
的每个组合中的百分比,我们还将添加 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")
1 你可以用 round
代替,但我更喜欢 sprintf
因为即使小数部分为零,它也会在小数位保留一个零, 而 round
returns 只是小数部分为零时的整数部分。例如,比较 round(3.04, 1)
和 sprintf("%1.1f", 3.04)
更新: 回答您评论中的问题:
第二个"group_by line"是什么原因?我们已经计算了 Year、variable 和 value 的每个组合的计数。现在,我们想知道,在 Year 和 variable 的每个组合中,value="Satisfied" 的百分比和 value="Dissatisfied" 的百分比。为此,我们只想按年份和变量分组。
解释
y=n.pos
行。这是我们计算每个百分比标签的 y 位置的地方。我们希望标签位于每个条的中间,但条是堆叠的。如果我们只使用cumsum(n)
标签将位于每个条形部分的顶部。我们减去0.5*n
以便每个标签的 y 位置将减少包含该标签的条形部分高度的一半。这是一个示例:假设我们有三个高度分别为 1、2 和 3 的条形部分(按此顺序从下到上堆叠),我们想要计算标签的 y 位置。
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
这给出了在每个条形部分内垂直居中标签的 y 位置。
如何按百分比降序排列 x 轴列?默认情况下,ggplot 按
x
变量类别的顺序对离散 x 轴进行排序。对于字符变量,顺序将按字母顺序排列。对于因子变量,排序将是因子水平的排序。在我的例子中,
summary$variable
的等级如下:levels(summary$variable) [1] "Q1" "Q2"
要按
pct
重新排序,一种方法是使用reorder
函数。比较这些(使用上面的摘要数据框):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)
请注意,在第二个图中,"Q1" 和 "Q2" 的顺序现在已经颠倒了。但是,请注意,在左侧面板中,Q1 堆栈更高,而在右侧面板中,Q2 堆栈更高。通过分面,您可以在每个面板中获得相同的 x 轴排序,通过比较所有 Q1 值的 sum 和 sum 所有 Q2 值。 Q2的总和较小,所以他们先走。当您使用
position="dodge"
时也会发生同样的情况,但我使用 "stack" 以便更容易看到发生了什么。希望下面的示例有助于澄清问题。# Fake data values = c(4.5,1.5,2,1,2,4) dat = data.frame(group1=rep(letters[1:3], 2), group2=LETTERS[1:6], group3=rep(c("W","Z"),3), pct=values/sum(values)) levels(dat$group2) [1] "A" "B" "C" "D" "E" "F" # plot group2 in its factor order ggplot(dat, aes(group2, pct)) + geom_bar(stat="identity", position="stack", colour="red", lwd=1) # plot group2, ordered by -pct ggplot(dat, aes(reorder(group2, -pct), pct)) + geom_bar(stat="identity", colour="red", lwd=1) # plot group1 ordered by pct, with stacking ggplot(dat, aes(reorder(group1, pct), pct)) + geom_bar(stat="identity", position="stack", colour="red", lwd=1) # Note that in the next two examples, the x-axis order is b, a, c, # regardless of whether you use faceting ggplot(dat, aes(reorder(group1, pct), pct)) + geom_bar(stat="identity", position="stack", colour="red", lwd=1) + facet_grid(.~group3) ggplot(dat, aes(reorder(group1, pct), pct, fill=group3)) + geom_bar(stat="identity", position="stack", colour="red", lwd=1)
有关通过设置因子顺序对轴值进行排序的更多信息,this blog post 可能会有所帮助。