【问题标题】:Can you change the order of factors in a faceted, stacked bar chart in ggplot2?您可以更改 ggplot2 中多面堆叠条形图中的因子顺序吗?
【发布时间】:2016-06-07 22:48:51
【问题描述】:

我正在尝试制作一个图表,显示不同年龄组中拥有 18 岁以下孩子的男性和女性的百分比。我想要一个包含两个条形的图表(一个代表男性,一个代表女性)每个年龄组并排;我希望两个条形图显示底部有孩子的百分比,而不是顶部(堆叠条形)。我不知道如何在 ggplot2 中制作这样的图表,非常感谢您的建议。

我使用 dplyr 计算了我的分组统计数据:

kid18summary <- marsub %>% 
group_by(AgeGroup, sex, kid_under_18) %>% 
summarise(n=n()) %>% 
mutate(freq = n/sum(n))

产生了这个:

dput(kid18summary)
structure(list(AgeGroup = c("Age<40", "Age<40", "Age<40", "Age<40", 
"Age41-49", "Age41-49", "Age41-49", "Age41-49", "Age50-64", "Age50-64", 
"Age50-64", "Age50-64"), sex = structure(c(1L, 1L, 2L, 2L, 1L, 
1L, 2L, 2L, 1L, 1L, 2L, 2L), .Label = c("Male", "Female"), class = "factor"), 
    kid_under_18 = c("No", "Yes", "No", "Yes", "No", "Yes", "No", 
    "Yes", "No", "Yes", "No", "Yes"), freq = c(0.625, 0.375, 
    0.636833046471601, 0.363166953528399, 0.349557522123894, 
    0.650442477876106, 0.444897959183673, 0.555102040816327, 
    0.724852071005917, 0.275147928994083, 0.819548872180451, 
    0.180451127819549)), .Names = c("AgeGroup", "sex", "kid_under_18", 
"freq"), class = c("grouped_df", "tbl_df", "tbl", "data.frame"
), row.names = c(NA, -12L), vars = list(AgeGroup, sex), drop = TRUE, indices = list(
    0:1, 2:3, 4:5, 6:7, 8:9, 10:11), group_sizes = c(2L, 2L, 
2L, 2L, 2L, 2L), biggest_group_size = 2L, labels = structure(list(
    AgeGroup = c("Age<40", "Age<40", "Age41-49", "Age41-49", 
    "Age50-64", "Age50-64"), sex = structure(c(1L, 2L, 1L, 2L, 
    1L, 2L), .Label = c("Male", "Female"), class = "factor")), class = "data.frame", row.names = c(NA, 
-6L), vars = list(AgeGroup, sex), drop = TRUE, .Names = c("AgeGroup", 
"sex")))

我可以绘制每个年龄组和性别中没有 18 岁以下孩子的人的百分比:

ggplot(kid18summary, aes(x = factor(AgeGroup), y = freq, fill = factor(sex)), color = factor(sex)) +
  geom_bar(position = "dodge", stat = "identity") + scale_y_continuous(labels = percent)

或者我可以制作一个多面的堆叠条形图,它更接近我想要的,因为我想同时显示“是”和“否”,即使百分比加起来是100 因为我认为比较彩色条比比较负空间更容易。唯一的麻烦是,无论我做什么,“否”都在底部,“是”在顶部,我希望反过来。 (理想情况下,我真的很想为男人和女人有不同的颜色,说有孩子的男人是深蓝色的,没有孩子的男人是浅蓝色的;有孩子的女人是深红色的,没有孩子的女人是浅红色的,但我已经放弃了暂时这样。)

我尝试以多种方式改变因素的顺序,但都完全不成功。

正如ggplot2 documentation 中所建议的那样,我尝试直接更改因子级别的顺序:

kid18summary$kid_under_18 < as.factor(kid18summary$kid_under_18)
o <- c("Yes", "No")  # which I've also changed to ("No", "Yes"), which makes no difference; the order of the Yes and No in the legend changes, but the "Yes" bars stay on top
kid18summary$kid_under_18 <- factor(kid18summary$kid_under_18, levels = o)

kid18summary$kid_under_18

我已经尝试了另一个问题中建议的答案并添加了另一个有序因素:

kid18summary <- transform(kid18summary, stack.ord = factor(kid_under_18, levels = c("Yes", "No"), ordered = TRUE))
ggplot(kid18summary, aes(x = factor(sex), y = freq, fill = factor(stack.ord)), color = factor(stack.ord)) + geom_bar(stat = "identity") + scale_y_continuous(labels = percent) + facet_wrap(~AgeGroup, nrow=1)

或者只是添加另一个虚拟变量:

kid18summary$orderfactor <- "NA"
kid18summary$orderfactor[kid18summary$kid_under_18 == "Yes"] <- 0
kid18summary$orderfactor[kid18summary$kid_under_18 == "No"] <- 1
ggplot(kid18summary, aes(x = factor(sex), y = freq, fill = factor(orderfactor)), color = factor(orderfactor)) + geom_bar(stat = "identity") + scale_y_continuous(labels = percent) + facet_wrap(~AgeGroup, nrow=1)

所有这些都为我提供了很多不同的方式,我可以在栏中切换是和否组的颜色,但实际上并不是哪个在顶部。

【问题讨论】:

  • 设置填充因子的级别顺序后,您需要按该因子对数据集进行排序。见this answer
  • 另外,不同组合的不同颜色可能是可行的。如果您仍然感兴趣,您可以在查看 this question/answer 后提出相关问题

标签: r plot ggplot2


【解决方案1】:

根据 aosmith 建议的答案,我得到了以下结果,这正是我想要的:

ggplot(arrange(df, kid_under_18), aes(x = factor(sex), y = freq, fill = interaction(sex, factor(kid_under_18))), color = factor(kid_under_18)) + 
geom_bar(stat = "identity") + scale_y_continuous(labels = percent) + 
facet_wrap(~AgeGroup, nrow=1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-15
    • 1970-01-01
    • 2018-02-15
    • 1970-01-01
    • 2017-09-17
    • 1970-01-01
    • 2022-08-19
    • 2019-05-19
    相关资源
    最近更新 更多