如何在dplyr中按动态数量的列对数据框排序?
用dplyr::arrange()按可变数量列排序的解决方案
问题背景
现有如下数据框:
data = data.frame(A = c(3,2,1), B = c(2,1,1), C = c(1,2,1))
需要根据数量可变的列对数据框排序:排序列可能是单列(如c('B')),也可能是多列(如c('C', 'A'),即先按C列排序,再按A列排序)。直接传递字符向量到dplyr::arrange()会报错,比如:
arranging_columns <- c('C', 'B') arranged <- dplyr::arrange(data, {arranging_columns})
报错信息:
Error in `dplyr::arrange()`: ℹ In argument: `..1 = arranging_columns`. Caused by error: ! `..1` must be size 3 or 1, not 2.
期望输出:
A B C 1 1 1 3 2 1 2 1 2
解决方法
方法1:用rlang::syms()转换并展开参数
将字符向量转换为符号列表,再通过!!!运算符将其展开为arrange()的多个列参数:
library(dplyr) library(rlang) data = data.frame(A = c(3,2,1), B = c(2,1,1), C = c(1,2,1)) arranging_columns <- c('C', 'B') arranged <- arrange(data, !!!syms(arranging_columns)) print(arranged)
运行结果:
A B C 1 1 1 1 2 3 2 1 3 2 1 2
方法2:用dplyr::across()(dplyr 1.0.0+适用)
使用across()结合all_of()来指定排序列,写法更简洁:
arranged <- arrange(data, across(all_of(arranging_columns))) print(arranged)
all_of()用于精准匹配字符向量中的列名,确保across()正确识别目标列。
两种方法都支持1列或多列的排序场景,比如当排序列为单列c('B')时,执行以下代码即可得到按B列排序的结果:
arranging_columns <- c('B') arrange(data, !!!syms(arranging_columns)) # 或 arrange(data, across(all_of(arranging_columns)))
输出:
A B C 1 2 1 2 2 1 1 1 3 3 2 1
内容的提问来源于stack exchange,提问作者Isaac Feldman
相关产品推荐
相关产品推荐

