变量长度不等时在Base R中绘制分组反向条形图
解决Base R/ggplot分组反向条形图问题(2007欧歌赛数据)
我明白你在绘制分组反向条形图时遇到了数据缺失导致的报错问题——部分参赛国没有给冠亚季军打分,使得数据结构不完整,无法直接用于分组绘图。下面我会先帮你整理好数据,再分别提供Base R和ggplot的解决方案。
第一步:数据预处理(关键!解决缺失值问题)
你现有数据已经过滤掉了0分和本国打分的情况,但还需要筛选出目标国家(塞尔维亚、乌克兰、俄罗斯)的打分记录,并将数据转换为适合分组绘图的格式,同时填补缺失的打分(用0表示未打分):
# 从现有数据中筛选出给冠亚季军的打分 target_countries <- c("Serbia", "Ukraine", "Russia") evro2007_target <- evro2007_zero[evro2007_zero$`To country` %in% target_countries, ] # 转换为宽格式:每个国家对应三个目标国的分数,缺失值填0 library(tidyr) evro2007_wide <- pivot_wider(evro2007_target, id_cols = `From country`, names_from = `To country`, values_from = Points, values_fill = 0) # 提取国家列表和分数矩阵(用于Base R绘图) country_names <- evro2007_wide$`From country` score_matrix <- as.matrix(evro2007_wide[, target_countries])
方案一:Base R 分组反向条形图
这里我们用barplot()函数,设置horiz=TRUE实现反向条形,同时用矩阵输入来实现分组效果:
# 定义三个分组的颜色 group_colors <- c("darkred", "steelblue", "forestgreen") # 绘制反向分组条形图 barplot(t(score_matrix), # 转置矩阵,让每个国家对应一行分组条 horiz = TRUE, # 反向条形(X轴为分数,Y轴为国家) col = group_colors, names.arg = country_names, # Y轴的国家名称 xlab = "Points", ylab = "From Country", main = "2007 Eurovision: Scores Given to Top 3 Countries", las = 1) # 让Y轴标签横向显示,避免重叠 # 添加图例 legend("bottomright", legend = target_countries, fill = group_colors, title = "To Country")
为什么这样做?
- 转置矩阵是因为
barplot()默认按列绘制分组,转置后每个国家的三个分组条会垂直排列(对应Y轴的一个国家位置) values_fill=0填补了缺失的打分,确保每个国家都有三个分数值,避免绘图时的长度不匹配报错
方案二:ggplot2 分组反向条形图
如果你需要ggplot代码,下面是完整的实现,用长格式数据更适合ggplot的语法:
library(ggplot2) # 确保数据是长格式(如果之前用了宽格式,需要转回来) evro2007_long <- pivot_longer(evro2007_wide, cols = target_countries, names_to = "To country", values_to = "Points") # 绘制反向分组条形图 ggplot(evro2007_long, aes(x = Points, y = `From country`, fill = `To country`)) + geom_col(position = "dodge") + # 分组条形并列 coord_flip() + # 反向坐标轴,实现X轴分数、Y轴国家的效果 scale_fill_manual(values = group_colors) + labs(title = "2007 Eurovision: Scores Given to Top 3 Countries", x = "Points", y = "From Country", fill = "To Country") + theme_minimal() + theme(axis.text.y = element_text(size = 8)) # 调整Y轴标签大小,避免重叠
注意事项
- 如果你的R版本较旧,
tidyr::pivot_wider()/pivot_longer()可能需要换成spread()/gather(),功能是一样的:# 旧版本tidyr的宽格式转换 evro2007_wide <- spread(evro2007_target, key = `To country`, value = Points, fill = 0) # 旧版本tidyr的长格式转换 evro2007_long <- gather(evro2007_wide, key = `To country`, value = Points, target_countries)
内容的提问来源于stack exchange,提问作者user13646116
相关产品推荐
相关产品推荐

