You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的映射里:

  1. 先筛选所有冠军记录
  2. 按国籍分组统计每个国家的冠军总数
  3. 按冠军总数降序排序,取前10条
  4. 用处理好的汇总数据绘图,逻辑清晰且可控。

问题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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 19:27:03