ggplot2中geom_col如何用Total_In_Class变量设置柱宽?
问题描述
我是首次发帖,若有问题欢迎提出建设性意见。我使用ggmosaic包的titanic数据绘制了柱状图,希望让柱宽匹配Total_In_Class变量,但尝试geom_col的width参数及在aes中设置width=Total_In_Class均无效,请问是否有实现方法或需更换可视化方式?
原代码如下:
library(tidyverse) library(ggmosaic) titanic %>% group_by(Class, Sex, Age, Survived) %>% tally() %>% spread(key = Survived, value = n, fill = 0) %>% mutate(Classification = paste("Class: ", Class, " Sex: ", Sex, " Age: ", Age)) %>% mutate(Total_In_Class = Yes + No) %>% mutate(Percent_Survived = Yes / Total_In_Class) %>% ggplot() + geom_col(aes(x = Classification, y = Percent_Survived)) + geom_text(aes(x = Classification, y = Percent_Survived, label = Total_In_Class), vjust = -.3) + theme(axis.text.x = element_text(angle = -90, vjust = -.05))
附原图:
解决方案
geom_col不支持直接按变量设置柱宽,因为它的x轴是离散分类,每个分类的位置固定,width参数无法实现按变量调整宽度。你可以用两种方式解决:
方式一:用geom_rect手动绘制可控宽度的柱子
通过计算每个分类的x轴起始、结束位置和宽度比例,手动绘制柱子:
library(tidyverse) library(ggmosaic) titanic_processed <- titanic %>% group_by(Class, Sex, Age, Survived) %>% tally() %>% spread(key = Survived, value = n, fill = 0) %>% mutate(Classification = paste("Class: ", Class, " Sex: ", Sex, " Age: ", Age)) %>% mutate(Total_In_Class = Yes + No) %>% mutate(Percent_Survived = Yes / Total_In_Class) %>% # 计算宽度占比和x轴位置 mutate(width_prop = Total_In_Class / sum(Total_In_Class)) %>% arrange(Classification) %>% mutate(x_start = cumsum(width_prop) - width_prop, x_end = cumsum(width_prop), x_mid = (x_start + x_end)/2) ggplot(titanic_processed) + geom_rect(aes(xmin = x_start, xmax = x_end, ymin = 0, ymax = Percent_Survived, fill = Classification)) + geom_text(aes(x = x_mid, y = Percent_Survived, label = Total_In_Class), vjust = -.3) + scale_x_continuous(breaks = titanic_processed$x_mid, labels = titanic_processed$Classification) + theme(axis.text.x = element_text(angle = -90, vjust = -.05)) + labs(x = "Classification")
方式二:直接使用ggmosaic的马赛克图
马赛克图天生会按组内样本量比例展示宽度,完美匹配你的需求,无需手动计算:
library(tidyverse) library(ggmosaic) ggplot(titanic) + geom_mosaic(aes(x = product(Class, Sex, Age), fill = Survived, weight = n)) + labs(x = "Classification", fill = "Survived")
内容的提问来源于stack exchange,提问作者Merloo
相关产品推荐
相关产品推荐

