我有一个循环,在不同的迭代中,我想使用不同的列列表对数据帧进行排序。当我对排序变量进行硬编码时,我可以进行这种排序。但是我想使用变量列表传递列名。我找不到这样做的方法。
DT <-data.frame(avar = c(1,4,3,1), bvar = c("a","f","s","b"), cvar = c(3,4,5,2))
sort1 <-c("avar", "cvar")
sort2 <-c("avar", "bvar")
sorting <-list(sort1,sort2)
DT2<-list()
for (i in 1:2) {
sorter<- sorting[[i]]
#THE FOLLOWING SOLUTION WORKS!!!
DT2[[i]] <- DT[do.call(order,DT[as.character(sorting[[i]])]),]
}
我用c(“avar”,“cvar”)排序的意思是数据首先按avar排序,然后(如果有两个avar值相同)则按cvar排序。换句话说,该向量的排序输出应该只是一个排序的数据帧(不是列表)。按c(“avar”,“bvar”)排序也是一样的。 “ps1”以上代表所提出的解决方案之一。它给我DT2 [[1]],它是两个数据帧的列表。这不是我需要的。 DT2应该是两个数据帧的列表。 DT2 [[1]]应该是一个数据帧。
我还要强调,我确实需要通过循环进行这种排序,而不是通过将列表(“排序”)传递给命令。换句话说,第一次迭代应该按排序列表的第一项对数据库进行排序,这是我的代码中的向量“排序器”。在实际应用中,不同迭代中的数据不是同一个数据集。
在第一个循环之后,DT2 [[1]]应按如下方式排序:
avar bvar cvar
1 b 2
1 a 3
3 s 5
4 f 4
在第二个循环之后,DT2 [[2]]应该被排序为:
avar bvar cvar
1 a 3
1 b 2
3 s 5
4 f 4
在现实生活中,我可能在不同的迭代中也有不同数量的排序列。
关于使用“map”函数提出的解决方案:我加载了一些geospacial包(mapproj,fivestater,geofacet),因此除非我卸载这些包,否则“map”函数不会像建议的那样工作。有没有办法有资格使用原生的“地图”功能而不是地理地图功能?
谢谢您的帮助!
使用基数R,我们可以使用order
在sorting
中的选定列上应用do.call
。我们使用lapply
来获取数据帧列表
lapply(sorting, function(x) DT[do.call(order, DT[x]), ])
#[[1]]
# avar bvar cvar
#4 1 b 2
#1 1 a 3
#3 3 s 5
#2 4 f 4
#[[2]]
# avar bvar cvar
#1 1 a 3
#4 1 b 2
#3 3 s 5
#2 4 f 4
一个dplyr
+ purrr
解决方案
library(purrr)
library(dplyr)
map(sorting, ~arrange(DT, !!!syms(.x)))
#[[1]]
# avar bvar cvar
#1 1 b 2
#2 1 a 3
#3 3 s 5
#4 4 f 4
#
#[[2]]
# avar bvar cvar
#1 1 a 3
#2 1 b 2
#3 3 s 5
#4 4 f 4
这是来自setorder
的data.table
的方法
library(data.table)
Map(setorderv, replicate(2, copy(DT), simplify = FALSE), sorting)
#[[1]]
# avar bvar cvar
#4 1 b 2
#1 1 a 3
#3 3 s 5
#2 4 f 4
#[[2]]
# avar bvar cvar
#1 1 a 3
#4 1 b 2
#3 3 s 5
#2 4 f 4
或者使用arrange_at
的dplyr
(不使用评估方式)
library(tidyverse)
map(sorting, ~ DT %>%
arrange_at(.x))
#[[1]]
# avar bvar cvar
#1 1 b 2
#2 1 a 3
#3 3 s 5
#4 4 f 4
#[[2]]
# avar bvar cvar
#1 1 a 3
#2 1 b 2
#3 3 s 5
#4 4 f 4
The following solution works for me! Other proposed solutions I tried failed to sort by two variables in a given vector simultaneously.
DT <-data.frame(avar = c(1,4,3,1), bvar = c("a","f","s","b"), cvar = c(3,4,5,2))
sort1 <-c("avar", "cvar")
sort2 <-c("avar", "bvar")
sorting <-list(sort1,sort2)
DT2<-list()
for (i in 1:2) {
#THE FOLLOWING SOLUTION WORKS!!!
DT2[[i]] <- DT[do.call(order,DT[as.character(sorting[[i]])]),]
}