如何按年份和地区分组排序,获取Top3免费参观人数最多的博物馆?
问题描述
我有一个包含name(博物馆名称)、no_entrees_gratuites(免费参观人数)、year(年份)、region(地区)列的DataFrame,结构如下:
$ name : chr [1:13233] "Musée de la Folie Marco" "Musée de la Poterie" "Musée Alsacien" "Musée Historique" ... $ no_entrees_gratuites: num [1:13233] 2339 538 1329 3305 723 ... $ year : num [1:13233] 2008 2008 2008 2008 2008 ... $ region : chr [1:13233] "Grand Est" "Grand Est" "Grand Est" "Grand Est" ...
数据示例:
name no_entrees_gratuites year region Musée du Louvre 4117897 2008 Ile-de-France Musée Fabre 131553 2008 Occitanie Château de Versailles 1696929 2008 Ile-de-France Musée d'Art et d'Histoire 602183 2008 Occitanie Musée d'Orsay 1327622 2008 Ile-de-France Muséum d'Histoire Naturelle 150530 2008 Occitanie
我需要按年份、地区分组,筛选出每组内免费参观人数最多的前3家博物馆,预期结果如下:
name no_entrees_gratuites year region Musée du Louvre 4117897 2008 Ile-de-France Château de Versailles 1696929 2008 Ile-de-France Musée d'Orsay 1327622 2008 Ile-de-France Musée d'Art et d'Histoire 602183 2008 Occitanie Muséum d'Histoire Naturelle 150530 2008 Occitanie Musée Fabre 131553 2008 Occitanie
之前尝试了全局排序的方法,都不符合需求:
- 使用dplyr的
arrange全局排序:
musees_entrees_gratuites_per_region_year <- musees_entrees_gratuites_per_region_year %>% arrange(desc(no_entrees_gratuites))
- 使用
order函数全局排序:
musees_entrees_gratuites_per_region_year[with(musees_entrees_gratuites_per_region_year,order(musees_entrees_gratuites_per_region_year$no_entrees_gratuites, musees_entrees_gratuites_per_region_year$name)),]
解决方案
可以用dplyr的分组+筛选组合操作,核心是按年份和地区分组后,提取每组内的TopN数据:
方法1:使用slice_max(推荐)
library(dplyr) result <- musees_entrees_gratuites_per_region_year %>% group_by(year, region) %>% # 每组取免费参观人数最多的前3个,with_ties=FALSE避免并列时多取数据 slice_max(no_entrees_gratuites, n = 3, with_ties = FALSE) %>% # 按年份、地区排序,组内按参观人数降序排列 arrange(year, region, desc(no_entrees_gratuites)) %>% ungroup() # 取消分组,根据后续操作需求可选
如果需要保留并列排名的所有行(比如多个博物馆参观人数相同且都在前3),将with_ties参数设为TRUE即可。
方法2:使用rank函数
result <- musees_entrees_gratuites_per_region_year %>% group_by(year, region) %>% # 给每组内的博物馆按参观人数降序排名,ties.method="first"处理并列情况 mutate(rank = rank(desc(no_entrees_gratuites), ties.method = "first")) %>% # 筛选排名前3的行 filter(rank <= 3) %>% # 按年份、地区、排名排序 arrange(year, region, rank) %>% # 移除排名列 select(-rank) %>% ungroup()
内容的提问来源于stack exchange,提问作者Lumb
相关产品推荐
相关产品推荐

