通过列名列表按多列对数据帧进行排序

问题描述 投票:0回答:4

我有一个循环,在不同的迭代中,我想使用不同的列列表对数据帧进行排序。当我对排序变量进行硬编码时,我可以进行这种排序。但是我想使用变量列表传递列名。我找不到这样做的方法。

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 sorting dataframe vector
4个回答
1
投票

使用基数R,我们可以使用ordersorting中的选定列上应用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

1
投票

一个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

0
投票

这是来自setorderdata.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_atdplyr(不使用评估方式)

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

0
投票
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]])]),]       
}
© www.soinside.com 2019 - 2024. All rights reserved.