ggplot按x轴total_meeting值重排y轴bizdev失效问题求助
问题:ggplot中按total_meeting重排y轴bizdev未生效
背景数据与处理流程
原始数据集结构:
df <- tibble( bizdev = c("Jerry Harding", "Steve Vargas", "Steve Vargas", "Jerry Harding", "Jerry Harding", "David Burton"), company = c("Jones, Figueroa and Moon", "Stanley, Porter and Mccoy", "Gardner and Sons", "Parks-Chen", "Bond Group", "Lopez-Johnson"), date = as.Date(c("2020-04-06", "2020-04-24", "2020-04-19", "2020-04-11", "2020-04-06", "2020-05-07")), category = c("Mid-tier", "Indie", "Indie", "Indie", "Indie", "Enterprise") )
数据转换代码:
consol <- df %>% mutate(meeting_month = as_factor(month(date, abbr = TRUE, label = TRUE)), .keep = 'unused') %>% group_by(bizdev, category, meeting_month) %>% summarise(total_meeting = n(), .groups = "drop_last")
转换后数据集(部分示例):
# Groups: bizdev, category [22] bizdev category meeting_month total_meeting <chr> <chr> <ord> <int> 1 Bobby Adams Enterprise Apr 2 2 Bobby Adams Indie Mar 12 3 Bobby Adams Indie Apr 13 4 Bobby Adams Indie May 12 5 Bobby Adams Mid-tier Mar 6 6 Bobby Adams Mid-tier Apr 6 7 Bobby Adams Mid-tier May 3 8 David Burton Enterprise May 2 9 David Burton Indie Mar 30 10 David Burton Indie Apr 31
问题现象
使用以下代码绘图时,y轴的bizdev未按total_meeting的预期值排序(比如Steve Vargas的total_meeting高于Joel English,但位置错误):
consol %>% ggplot(aes(x = total_meeting, y = reorder(bizdev, -total_meeting), fill = category)) + geom_bar(stat = 'identity') + theme_classic()
原因分析
reorder(bizdev, -total_meeting)默认会对每个bizdev对应的所有total_meeting值取算术平均值作为排序依据,而非你需要的总会议数、最大单月会议数等汇总值。当一个bizdev同时存在高值和低值记录时,均值会拉平排序权重,导致显示顺序不符合预期。
解决方案
方案1:按每个bizdev的总会议数排序
先计算每个业务开发人员的累计会议总数,再基于该值排序y轴:
# 计算每个bizdev的总会议数 bizdev_total <- consol %>% group_by(bizdev) %>% summarise(total_all = sum(total_meeting)) %>% ungroup() # 合并数据并绘图 consol %>% left_join(bizdev_total, by = "bizdev") %>% ggplot(aes(x = total_meeting, y = reorder(bizdev, -total_all), fill = category)) + geom_col() + # geom_col是geom_bar(stat='identity')的简写,更直观 theme_classic()
方案2:按每个bizdev的最大单月会议数排序
如果需要按单月最高会议数排序:
# 计算每个bizdev的最大单月会议数 bizdev_max <- consol %>% group_by(bizdev) %>% summarise(max_meeting = max(total_meeting)) %>% ungroup() # 合并数据并绘图 consol %>% left_join(bizdev_max, by = "bizdev") %>% ggplot(aes(x = total_meeting, y = reorder(bizdev, -max_meeting), fill = category)) + geom_col() + theme_classic()
方案3:用forcats包的fct_reorder2直接排序
借助forcats包的fct_reorder2函数,可直接在ggplot中基于指定规则排序,无需提前合并数据:
library(forcats) consol %>% ggplot(aes(x = total_meeting, y = fct_reorder2(bizdev, total_meeting, category, .fun = max), # 按每个bizdev的最大total_meeting排序 fill = category)) + geom_col() + theme_classic()
内容的提问来源于stack exchange,提问作者Ong K.S
相关产品推荐
相关产品推荐

