根据R中的特定列值对列块进行排序

时间:2014-06-05 18:57:42

标签: r dataframe

我在r中有一个data.frame。从第2列开始,每4列形成一个块。我需要根据3,7,11,...元素值的顺序对这些块进行整体排序。也就是说,移动这些4列块,使其第二列值按递增顺序排列。

例如,如果我们有一个数据框如下

0 7 2 3 4 1 2 2 3 4 2 1 8 3 9 1 7
4 9 1 2 1 8 1 0 4 5 1 3 2 1 3 2 7
...

我希望结果是

0 1 2 2 3 3 9 1 7 4 2 1 8 7 2 3 4
4 1 3 2 7 5 1 3 2 8 1 0 4 9 1 2 1
...

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:1)

在每一行中,您根据每个4列块中的第一个值进行排序。这可以通过以下方式完成:

dat = rbind(c(0, 7, 2, 3, 4, 1, 2, 2, 3, 4, 2, 1, 8, 3, 9, 1, 7),
            c(4, 9, 1, 2, 1, 8, 1, 0, 4, 5, 1, 3, 2, 1, 3, 2, 7))
t(apply(dat, 1, function(x) {
  to.sort <- x[seq(2, ncol(dat), by=4)]
  x[c(1, rep(order(to.sort), each=4)*4 - c(2, 1, 0, -1))]
}))
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
# [1,]    0    1    2    2    3    3    9    1    7     4     2     1     8
# [2,]    4    1    3    2    7    5    1    3    2     8     1     0     4
#      [,14] [,15] [,16] [,17]
# [1,]     7     2     3     4
# [2,]     9     1     2     1

apply的每一行都在调用dat函数。首先,我们将每个4列块的第一个值抓取到一个名为to.sort的变量中。然后,我们操纵order函数的输出来构造行的索引;每个4列块都会回收c(2, 1, 0, -1),并使我们能够返回该块中的所有四列。

将此概括为一个函数,并不是很难将这个操作推广到任何数量的列,以便在开始s和任何块大小b时跳过:

order.blocks <- function(dat, s, b) {
  t(apply(dat, 1, function(x) {
    to.sort <- x[seq(s+1, ncol(dat), by=b)]
    if (s > 0) padding <- seq(s) else padding <- NULL
    x[c(padding, rep(order(to.sort), each=b)*b + seq(s+1-b, s))]
  }))
}
order.blocks(dat, 1, 2)
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
# [1,]    0    1    2    1    8    1    7    2    3     3     4     3     9
# [2,]    4    0    4    1    3    2    1    2    7     3     2     5     1
#      [,14] [,15] [,16] [,17]
# [1,]     4     2     7     2
# [2,]     8     1     9     1