在R语言中如何排序一列同时保留另一列的原有顺序?
解决R语言中按分组排序同时保留分组原始顺序的问题
这个需求其实很常见——你想要按每个region分组对year升序排列,但严格保留region在原始数据里的出现顺序(而不是按region的数值大小排序)对吧?之前用order或arrange没成功,应该是因为默认会按region的数值排序,忽略了它的原始出现顺序。我给你几种可行的方法:
1. 使用dplyr包(tidyverse风格)
这是最直观的方法,核心是先把region转换成因子,指定其levels为原始数据中region的唯一出现顺序,这样排序时就会遵循这个自定义顺序:
首先构造你的示例数据:
sales <- data.frame( year = c(2006,2006,2006,2006,2006,2007,2007,2007,2007,2007), region = c(1,101,107,11,13,1,101,107,11,13) )
然后执行排序:
library(dplyr) # 提取region的原始唯一出现顺序 region_original_order <- unique(sales$region) sales_sorted <- sales %>% # 将region转为因子,指定levels为原始顺序 mutate(region = factor(region, levels = region_original_order)) %>% # 先按region的自定义顺序排序,再按year升序 arrange(region, year) %>% # 可选:如果需要将region转回整数类型(默认因子转整数会取levels的索引,所以要先转字符) mutate(region = as.integer(as.character(region))) print(sales_sorted)
2. 使用Base R
如果你不想加载额外的包,可以用Base R的方法,通过match给每个region分配一个对应原始顺序的分组ID,再按这个ID和year排序:
# 提取region的原始唯一出现顺序 region_original_order <- unique(sales$region) # 给每行数据分配对应原始顺序的分组ID sales$group_id <- match(sales$region, region_original_order) # 按分组ID和year排序,然后去掉临时的group_id列 sales_sorted_base <- sales[order(sales$group_id, sales$year), c("year", "region")] print(sales_sorted_base)
3. 使用data.table包(高效处理大数据)
如果你处理的是大数据集,data.table的方法会更高效:
library(data.table) setDT(sales) # 直接通过match获取原始顺序的索引,再按该索引和year排序 sales_sorted_dt <- sales[order(match(region, unique(region)), year)] print(sales_sorted_dt)
输出结果
以上三种方法都会得到你期望的结果:
year region 1 2006 1 2 2007 1 3 2006 101 4 2007 101 5 2006 107 6 2007 107 7 2006 11 8 2007 11 9 2006 13 10 2007 13
内容的提问来源于stack exchange,提问作者syoon
相关产品推荐
相关产品推荐

