如何在事先不知道所有列的情况下按所有列对数据框(在 R 库中)进行排序

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

我有一个带有许多固定列的数据框, 后跟可变数量的列,具体取决于输入。

dd <- data.frame(key1=c("NED", "LTU", "LAT", "ITA"), h=c(18, 3, 2, 59))      # Two columns.
dd <- rbind(dd, dd, dd)                                                      # example dataframe.

# Append a random number of auxiliary columns, ak1, ak2, ...
set.seed(2024); n <- sample(4:8, size=1)                                     # number of aux. columns.
akeys <- matrix(sample(x=c(1,2,3), size=nrow(dd) * n, replace=TRUE),
                ncol=n
               )                                                             # with random values 1..3.
colnames(akeys) <- paste0("ak", seq(n))                                      # column names: ak1, ak2, ...

d2 <- cbind(dd, akeys)                                                       # append n columns for sorting.
                                                                             # Assuming n = 5.
d3 <- d2[order(d2$key1, d2$h, -d2$ak1, -d2$ak2, -d2$ak3, -d2$ak4, -d2$ak5),]      # Sort all columns by name.
d4 <- d2[order(d2[,1], d2[,2], -d2[,3], -d2[,4], -d2[,5], -d2[,6], -d2[, 7]), ]   # Sort by column number.

问:如何在事先不知道列的情况下按(选择的)所有列对数据框进行降序或升序排序。

例如:

  • 按所有列对数据框进行排序。
  • 按 key1(升序)对数据帧进行排序,然后按最后 n 列(降序)排序。
# Output d3
d3
#    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

编辑(@jay.sf)。 要按选择的列进行排序:

nc     <- ncol(d2)                                        # number of columns in d2.
bycols <- subset(d2, select = c(key1, tail(seq(nc), n)) ) # select columns by name and index in one line.
d6     <- d2[do.call('order', bycols), ]                  # select by sort keys.

编辑2 如何对不同的列进行不同方向的排序,递增,递减?

r dataframe sorting
2个回答
2
投票

order
do.call
一起使用。

> d2[do.call('order', d2), ]
   key1  h ak1 ak2 ak3 ak4 ak5
12  ITA 59   1   2   1   1   1
4   ITA 59   1   2   3   1   1
8   ITA 59   2   1   3   3   3
7   LAT  2   2   1   2   1   1
11  LAT  2   3   1   3   2   3
3   LAT  2   3   2   2   1   3
6   LTU  3   1   2   1   2   2
2   LTU  3   1   2   3   1   1
10  LTU  3   1   3   1   1   2
1   NED 18   1   2   1   2   3
5   NED 18   1   2   3   2   2
9   NED 18   3   3   1   1   1

> d2[do.call('order', c(d2, decreasing=TRUE)), ]
   key1  h ak1 ak2 ak3 ak4 ak5
9   NED 18   3   3   1   1   1
5   NED 18   1   2   3   2   2
1   NED 18   1   2   1   2   3
10  LTU  3   1   3   1   1   2
2   LTU  3   1   2   3   1   1
6   LTU  3   1   2   1   2   2
3   LAT  2   3   2   2   1   3
11  LAT  2   3   1   3   2   3
7   LAT  2   2   1   2   1   1
8   ITA 59   2   1   3   3   3
4   ITA 59   1   2   3   1   1
12  ITA 59   1   2   1   1   1

2
投票

您可以运行以下代码来使用所有列进行排序。请注意,排序是通过引用进行的。请注意,该解决方案并非基于内置函数。

data.table::setorderv(d2)

   key1  h ak1 ak2 ak3 ak4 ak5
12  ITA 59   1   2   1   1   1
4   ITA 59   1   2   3   1   1
8   ITA 59   2   1   3   3   3
7   LAT  2   2   1   2   1   1
11  LAT  2   3   1   3   2   3
3   LAT  2   3   2   2   1   3
6   LTU  3   1   2   1   2   2
2   LTU  3   1   2   3   1   1
10  LTU  3   1   3   1   1   2
1   NED 18   1   2   1   2   3
5   NED 18   1   2   3   2   2
9   NED 18   3   3   1   1   1

请注意,此函数有两个参数来自定义排序的方式以及使用哪些列。参数

cols
指定要使用的列(默认为所有列),参数
order
指定如何使用每列(递增或递减顺序);在
order
中,
1
用于递增顺序,
-1
用于递减顺序,并且其长度可以等于用于排序的列数。 要根据第一列按升序对剩余列进行降序对 data.frame 进行排序,可以使用以下代码:

data.table::setorderv(d2, order=c(1, rep(-1, length(d2)-1)))
© www.soinside.com 2019 - 2024. All rights reserved.