[英]ggplot2 - ordered factor stacking in inverted order in barplot with positive and negative y-values
我正在尝试构建一个堆叠的条形图,但在堆栈顺序方面遇到了问题。
我有变量名称、值、计数和百分比。 值为 1-7。 分配给 5、6 或 7 的任何百分比都是负数,我怀疑这就是问题所在,但我无法弄清楚。 当我绘制这个时,堆栈中的值顺序是 5, 6, 7, 4, 3, 2, 1. 它应该是 7, 6, 5, 4, 3, 2, 1. 我什至尝试给出 5, 6 , 和 7 个负值,但这不起作用。
这是一个裸骨版本。 我希望生产的是“花式”。 但我坚持这一件事。 我总是在 ggplot2 中绊倒,尽管我很喜欢它。
df <- structure(list(name = c("cloud_data_available", "cloud_data_available",
"cloud_data_available", "cloud_data_available", "cloud_data_available",
"cloud_data_available", "cloud_data_available", "on_premise_data_available",
"on_premise_data_available", "on_premise_data_available", "on_premise_data_available",
"on_premise_data_available", "on_premise_data_available", "on_premise_data_available"
), value = structure(c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 1L, 2L, 3L,
4L, 5L, 6L, 7L), .Label = c("1", "2", "3", "4", "5", "6", "7"
), class = c("ordered", "factor")), count = c(1L, 2L, 1L, 5L,
18L, 52L, 55L, 2L, 4L, 5L, 4L, 16L, 33L, 70L), Percent = c(0.7,
1.5, 0.7, 3.7, -13.4, -38.8, -41, 1.5, 3, 3.7, 3, -11.9, -24.6,
-52.2)), row.names = c(NA, -14L), groups = structure(list(name = c("cloud_data_available",
"on_premise_data_available"), .rows = structure(list(1:7, 8:14), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), row.names = 1:2, class = c("tbl_df",
"tbl", "data.frame"), .drop = TRUE), class = "data.frame")
ggplot(df, aes(x=name, y = Percent, fill=value, label=value))+
#geom_bar(stat=", width = .5, position = position_stack(reverse = TRUE)) +
geom_col(position = "stack", width = .5) +
scale_x_discrete() +
geom_text(size = 3, position = position_stack(vjust = 0.5)) +
coord_flip()
这就是我得到的:
提前致谢! 当我来到这里时,我总是学到一些新东西。
堆栈的顺序由有序因子value
中的级别顺序决定。 所以你需要为正负百分比设置相反的顺序。
df <- df %>%
mutate(value2 = ordered(value, c("1","2","3","4","7","6","5")))
ggplot(df, aes(x=name, y = Percent, fill=value2, label=value2))+
#geom_bar(stat=", width = .5, position = position_stack(reverse = TRUE)) +
geom_col(position = "stack", width = .5) +
scale_x_discrete() +
geom_text(size = 3, position = position_stack(vjust = 0.5)) +
coord_flip()
(根据 OP 注释进行编辑):为了强制图例中的顺序,可以使用scale_fill_manual()
手动指定中断顺序:
brks <- c("1","2","3","4","5","6","7")
colrs <- c("#960019", "#D21F3C", "#FA8072", "gray", "#D0F0C0", "#C7EA46", "#4CBB17")
ggplot(df, aes(x=name, y = Percent, fill=value2, label=value2))+
#geom_bar(stat=", width = .5, position = position_stack(reverse = TRUE)) +
geom_col(position = "stack", width = .5) +
scale_x_discrete() +
geom_text(size = 3, position = position_stack(vjust = 0.5)) +
coord_flip() +
scale_fill_manual(values = colrs, breaks=brks)
这有点棘手,但我能想到的唯一方法是将数据拆分为负值和正值,并为轴的每一侧添加单独的层。
df_neg <- filter(df, value %in% c("5", "6", "7"))
df_pos <- filter(df, value %in% c("1", "2", "3", "4"))
ggplot() +
geom_col(data = df_pos, aes(x = Percent, y = name, fill = value), width = .5) +
geom_text(data = df_pos, aes(x = Percent, y = name, label = value, group = value), size = 3, position = position_stack(vjust = 0.5)) +
geom_col(data = df_neg, aes(x = Percent, y = name, fill = fct_rev(value)), width = .5) +
geom_text(data = df_neg, aes(x = Percent, y = name, label = value, group = fct_rev(value)), size = 3, position = position_stack(vjust = 0.5)) +
theme(legend.position = "bottom") +
guides(fill = guide_legend(nrow = 1, reverse = TRUE))
所以,感谢@Phil 和@Alexlok 的回答。 @Phil 成功了,但我选择了 @Alexlok,因为它教会了我关于 ggplot2 的工作原理。 为了使图例正确,最终的代码是:
df <- structure(list(name = c("cloud_data_available", "cloud_data_available",
"cloud_data_available", "cloud_data_available", "cloud_data_available",
"cloud_data_available", "cloud_data_available", "on_premise_data_available",
"on_premise_data_available", "on_premise_data_available", "on_premise_data_available",
"on_premise_data_available", "on_premise_data_available", "on_premise_data_available"
), value = structure(c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 1L, 2L, 3L,
4L, 5L, 6L, 7L), .Label = c("1", "2", "3", "4", "5", "6", "7"
), class = c("ordered", "factor")), count = c(1L, 2L, 1L, 5L,
18L, 52L, 55L, 2L, 4L, 5L, 4L, 16L, 33L, 70L), Percent = c(0.7,
1.5, 0.7, 3.7, -13.4, -38.8, -41, 1.5, 3, 3.7, 3, -11.9, -24.6,
-52.2)), row.names = c(NA, -14L), groups = structure(list(name = c("cloud_data_available",
"on_premise_data_available"), .rows = structure(list(1:7, 8:14), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), row.names = 1:2, class = c("tbl_df",
"tbl", "data.frame"), .drop = TRUE), class = "data.frame")
df <- df %>%
mutate(value2 = ordered(value, c("1","2","3","4","7","6","5")))
brks <- c("1","2","3","4","5","6","7")
colrs <- c("#960019", "#D21F3C", "#FA8072", "gray", "#D0F0C0", "#C7EA46", "#4CBB17")
ggplot(df, aes(x=name, y = Percent, fill=value2, label=ifelse(abs(Percent) < 3.5, "",
abs(Percent))))+
geom_col(position = "stack", width = .5) +
scale_x_discrete() +
scale_fill_manual(values = colrs, breaks=brks)+
geom_text(size = 3, position = position_stack(vjust = 0.5)) +
coord_flip()
现在,我当然不希望标签是“value2”。 我只是用它来查看堆栈的顺序。 我现在有百分比作为堆栈上的值。 为了美观,我想抑制非常小的数字。 所以,最终产品:
再次感谢 stackoverflow 社区!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.