r中矩阵的排序

ewm0tg9j  于 2023-04-18  发布在  其他
关注(0)|答案(3)|浏览(140)

我有一个像下面这样的矩阵,但有n

set.seed(123)
mt <- replicate(5, sample(1:3, 4, replace = TRUE))
mt
#>      [,1] [,2] [,3] [,4] [,5]
#> [1,]    3    3    3    1    3
#> [2,]    3    2    1    2    3
#> [3,]    3    2    2    3    1
#> [4,]    2    2    2    1    1

为了逐行排序,我使用以下代码和order函数,类似于here

od2 <- order(mt[1, ], mt[2, ], mt[3, ], mt[4, ])
mt[, od2]
#>      [,1] [,2] [,3] [,4] [,5]
#> [1,]    1    3    3    3    3
#> [2,]    2    1    2    3    3
#> [3,]    3    2    2    1    3
#> [4,]    1    2    2    1    2

有没有什么方法可以使这段代码适用于n行?我没有成功地将第二个版本的答案作为注解给出。我不熟悉do.call函数。

ssm49v7z

ssm49v7z1#

do.call需要 a list作为函数调用的参数。 因此,您需要将矩阵的行拆分为列表。函数asplit可以通过 * 按边距拆分数组或矩阵 * 来实现。

mt[,do.call(order, asplit(mt, 1))]
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    1    3    3    3    3
#[2,]    2    1    2    3    3
#[3,]    3    2    2    1    3
#[4,]    1    2    2    1    2

asplit当前(4.2.3)通过选择切片并在for循环中填充列表来执行此操作。其他选项可以在converting a matrix to a listConvert a matrix to a list of column-vectors中找到。
将一些可能的方法与较大的矩阵进行比较:

m <- matrix(sample(0:9, 1e6, TRUE), 1e3)

bench::mark(
asplit = m[,do.call(order, asplit(m, 1))],
data.frame = m[, do.call(order, data.frame(t(m)))],
splitRow = m[, do.call(order, split(m, row(m)))],
lapply = m[,do.call(order, lapply(1:nrow(m), function(i) m[i,]))],
splitNrow = m[, do.call(order, split(m, 1:nrow(m)))],
apply = m[, do.call(order, apply(m, 1, identity, simplify = FALSE))],
tapply = m[, do.call(order, tapply(m, row(m), identity))]
)

结果

expression     min  median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time
  <bch:expr> <bch:t> <bch:t>     <dbl> <bch:byt>    <dbl> <int> <dbl>   <bch:tm>
1 asplit      8.44ms  9.02ms     111.    19.25MB     73.8    30    20      271ms
2 data.frame  6.88ms  7.24ms     138.    15.47MB     80.3    36    21    261.4ms
3 splitRow   19.79ms 19.98ms      48.9   31.01MB     73.3    10    15    204.6ms
4 lapply      6.79ms  6.99ms     141.    11.57MB     33.8    54    13    384.2ms
5 splitNrow   8.36ms  8.55ms     117.     7.76MB     16.3    50     7    428.8ms
6 apply       7.53ms  7.74ms     128.    15.38MB     50.6    43    17    335.9ms
7 tapply     27.64ms 28.47ms      35.4   38.73MB    165.      3    14     84.7ms

方法data.framelapply是最快的,splitNrow分配的额外内存量最少,但asplit并不落后,更通用,也适用于数组,并允许轻松更改余量。

68de4m5k

68de4m5k2#

通过修改this answer,使其能够使用大量t转换按行排序,您可以执行以下操作:

t(t(mt)[do.call(order, as.data.frame(t(mt))),])

#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    3    3    3    3
# [2,]    2    1    2    3    3
# [3,]    3    2    2    1    3
# [4,]    1    2    2    1    2

或者,更简单的(根据@Ronak Shah的评论):

mt[, do.call(order, data.frame(t(mt)))]
kuarbcqp

kuarbcqp3#

带有split的选项

mt[, do.call(order, split(mt, row(mt)))]
      [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    3    3    3
[2,]    2    1    2    3    3
[3,]    3    2    2    1    3
[4,]    1    2    2    1    2

相关问题