ggplot2绘制越野跑国家冠军数Top10排序柱状图问题咨询
问题1:reorder函数的用法是否正确
你的写法属于凑巧能跑通但极不规范的情况,不推荐这么用。
原因是你提前筛选了所有rank == '1'的记录,这时候整个数据集的rank列全是字符型的"1",你在reorder里传入sum作为汇总函数时,R会隐式把字符"1"转成数值1再求和,最终得到每个国籍的冠军总数完成排序。但这个逻辑非常隐蔽,后续如果数据筛选逻辑变了很容易出bug,正确做法是提前汇总统计好每个国籍的冠军数之后,直接对汇总后的数值列排序。
问题2:限制展示前10名的最优实现方式
你原来的top_n用法完全错误,才会导致结果异常:top_n是对数据集的行做筛选,你在未汇总的原始明细数据上,指定按字符型的nationality选前10,R根本不知道你要按什么规则排序选前10,返回的结果自然是错的。
最优实现逻辑是先处理数据再绘图,不要把统计逻辑丢到ggplot的映射里:
- 先筛选所有冠军记录
- 按国籍分组统计每个国家的冠军总数
- 按冠军总数降序排序,取前10条
- 用处理好的汇总数据绘图,逻辑清晰且可控。
问题3:统计国籍出现次数的逻辑位置
你猜对了,确实是sum函数在起计数作用,但这是隐式类型转换带来的巧合效果,不是正规的统计方法。
你筛选后所有rank值都是字符"1",R在执行sum运算时,会自动把字符类型的"1"转换成数值1,求和的结果就是该国籍对应的冠军记录条数,也就是你要的冠军次数。但这种写法非常不规范,正常统计分类变量的出现次数,应该用dplyr的count()函数,或者group_by()+summarise(n = n())的标准写法,逻辑明确不会踩类型转换的坑。
修正后的可运行代码
library(tidyverse) # 读取数据 ultra_rankings <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-10-26/ultra_rankings.csv') # 先处理数据:筛选冠军→按国籍计数→取前10 top10_nation <- ultra_rankings %>% filter(rank == 1) %>% # 筛选冠军记录 count(nationality, name = "champion_count", sort = TRUE) %>% # 按国籍统计冠军数,自动排序 slice_head(n = 10) # 取前10名 # 绘图 ggplot(top10_nation, aes(x = reorder(nationality, -champion_count), y = champion_count)) + geom_col(fill = "steelblue") + # geom_col是stat=identity的柱状图简写 labs( title = "各国冠军数量排名", caption = "数据来源:runrepeat.com", x = "跑者国籍", y = "冠军总次数" ) + theme(plot.title = element_text(hjust = 0.5))
内容的提问来源于stack exchange,提问作者kproctor
相关产品推荐
相关产品推荐

