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

时间:2019-04-10 02:28:23

标签: r sorting dataframe vector

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

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]]应该是一个数据帧。

我还想强调一点,我确实需要通过循环而不是通过将列表(“排序”)传递给命令来进行这种排序。换句话说,第一次迭代应按排序列表的第一项对数据库进行排序,这是我的代码中的向量“ sorter”。在实际应用中,不同迭代中的数据不是同一数据集。

在第一个循环之后,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    

在现实生活中,我可能还会在不同的迭代中使用不同数量的排序列。

关于建议使用“地图”功能的解决方案:我已经加载了一些地理空间软件包(mapproj,五十stater,geofacet),因此除非我卸载这些软件包,否则“地图”功能将无法正常工作。有资格使用本地“地图”功能而非地理空间地图功能的方法吗?

谢谢您的帮助!

4 个答案:

答案 0 :(得分: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 :(得分: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

答案 2 :(得分: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_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

答案 3 :(得分: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]])]),]       
}