在R Base中未知全部列时如何对Data Frame按列排序
动态列数的DataFrame排序方案
需求说明
现有一个包含若干固定列,且后续列数量随输入动态变化的DataFrame,需要在无法预先知晓所有列的情况下,按指定规则完成升序/降序排序,典型场景包括:
- 按所有列进行排序
- 先按
key1列升序排序,再按最后n列降序排序
示例数据构建
首先构建包含固定列与动态列的示例DataFrame:
# 初始化包含固定列的DataFrame dd <- data.frame(key1=c("NED", "LTU", "LAT", "ITA"), h=c(18, 3, 2, 59)) # 重复数据行以扩充样本 dd <- rbind(dd, dd, dd) # 随机生成n个辅助列(n在4-8之间随机) set.seed(2024); n <- sample(4:8, size=1) # 生成随机值填充辅助列 akeys <- matrix(sample(x=c(1,2,3), size=nrow(dd) * n, replace=TRUE), ncol=n ) # 设置辅助列列名:ak1, ak2,... colnames(akeys) <- paste0("ak", seq(n)) # 合并固定列与动态辅助列得到目标DataFrame d2 <- cbind(dd, akeys)
硬编码的局限排序方式
若预先知晓列名或列数,可通过以下硬编码方式排序,但这种方法无法适配列数动态变化的场景:
# 假设n=5,按列名指定排序规则:key1、h升序,ak1-ak5降序 id3 <- order(d2$key1, d2$h, -d2$ak1, -d2$ak2, -d2$ak3, -d2$ak4, -d2$ak5) # 按列索引指定排序规则:第1、2列升序,第3-7列降序 id4 <- order(d2[,1], d2[,2], -d2[,3], -d2[,4], -d2[,5], -d2[,6], -d2[,7])
预期排序结果
执行硬编码排序后,输出结果示例如下:
# 输出排序后的DataFrame d2[id3, ] # key1 h ak1 ak2 ak3 ak4 ak5 # 8 ITA 59 2 1 3 3 3 # 4 ITA 59 1 2 3 1 1 # 12 ITA 59 1 2 1 1 1 # 3 LAT 2 3 2 2 1 3 # 11 LAT 2 3 1 3 2 3 # 7 LAT 2 2 1 2 1 1 # 10 LTU 3 1 3 1 1 2 # 2 LTU 3 1 2 3 1 1 # 6 LTU 3 1 2 1 2 2 # 9 NED 18 3 3 1 1 1 # 5 NED 18 1 2 3 2 2 # 1 NED 18 1 2 1 2 3
动态排序实现方案
通过动态获取列数、选择排序列,并结合do.call调用order函数,实现适配动态列数的排序:
# 获取DataFrame的总列数 nc <- ncol(d2) # 选择排序依据列:固定列key1,加上最后n列 bycols <- subset(d2, select = c(key1, tail(seq(nc), n)) ) # 指定排序方向:key1升序(FALSE),后续列降序(TRUE) bysort <- c(FALSE, rep(TRUE, ncol(bycols)-1) ) # 动态生成排序索引 idx <- do.call('order', c(bycols, decreasing=list(bysort), method='radix') ) # 验证动态排序索引与硬编码索引是否一致 identical(id3, idx) # 生成排序后的DataFrame d6 <- d2[idx, ]; d6
内容的提问来源于stack exchange,提问作者clp
相关产品推荐
相关产品推荐

