R语言分组排序:多阶最小值优先的排名逻辑优化需求
用tidyverse实现分组内多维度排序排名
需求说明
在分组内对物种按以下规则排序并生成排名:
- 优先比较排序后数值的第1个最小值,更小的物种排名靠前;
- 若第1个最小值相同,比较第2个最小值,以此类推直到第N个最小值;
- 若所有排序后的数值完全相同,则样本量更少的物种排名靠前;
- 所有维度都相同的物种,排名一致。
示例数据
先构造测试用的示例数据:
library(tidyverse) set.seed(123) df <- tibble( group = rep(c("A", "B"), each = 12), species = rep(c("sp1", "sp2", "sp3"), each = 4, times = 2), value = c( # Group A 1,1,2,3, # sp1: 排序后[1,1,2,3] 1,1,1,4, # sp2: 排序后[1,1,1,4] 1,2,3,4, # sp3: 排序后[1,2,3,4] # Group B 5,5,5,5, # sp1: 所有值均为5,样本量4 5,5,5,5, # sp2: 所有值均为5,样本量4 5,5,5,3 # sp3: 排序后[3,5,5,5] ) )
实现代码
df_ranked <- df %>% # 按分组+物种聚合,生成排序后的值列表和样本量 group_by(group, species) %>% summarise( sorted_vals = list(sort(value)), n = n(), .groups = "drop_last" ) %>% # 将排序后的列表展开为多列(val_1, val_2...对应第1到第N个最小值) unnest_wider(sorted_vals, names_sep = "_") %>% # 按分组依次按val_1→val_2→...排序,最后按样本量升序 arrange(across(starts_with("val_")), n) %>% # 生成组内密集排名(相同维度的物种排名一致) mutate(rank = dense_rank(str_c(across(starts_with("val_")), collapse = "-"))) %>% # 整理输出列 select(group, species, rank, n) %>% ungroup()
输出结果
运行代码后得到的排名结果:
# A tibble: 6 × 4 group species rank n <chr> <chr> <int> <int> 1 A sp2 1 4 2 A sp1 2 4 3 A sp3 3 4 4 B sp3 1 4 5 B sp1 2 4 6 B sp2 2 4
代码解释
- 聚合排序值:通过
group_by(group, species)分组后,用sort(value)生成每个物种的数值排序列表,同时记录样本量n; - 展开排序列:
unnest_wider将列表拆分为多列,确保每个排序后的最小值都成为独立的排序依据; - 多维度排序:
arrange(across(starts_with("val_")), n)会自动按val_1到val_N的顺序依次比较,最后按样本量升序处理所有值相同的情况; - 生成排名:用
str_c(across(...), collapse = "-")将所有排序列拼接成字符串,再用dense_rank生成组内排名,保证所有维度一致的物种获得相同排名。
内容的提问来源于stack exchange,提问作者Tal Dahan
相关产品推荐
相关产品推荐

