按特定顺序将矩阵重新整形为3D阵列

时间:2017-12-08 15:54:19

标签: arrays r reshape

我正在尝试按特定顺序将2D矩阵重塑为3D阵列。这似乎是一个相当简单的练习,但我似乎无法找到正确的方法。

             X          Y
 [1,] 276.9421  0.0000000
 [2,] 276.4248 -5.3750000
 [3,] 276.2253 -5.3333333
 [4,] 275.9051 -3.8125000
 [5,] 275.6589 -1.8200000
 [6,] 275.6311  0.6388889
 [7,] 275.6540  2.2142857
 [8,] 275.5883  2.9296875
 [9,] 275.7367  3.2222222
 [10,] 276.4208  3.2550000
 [11,] 277.0216  3.1528926
 [12,] 277.3477  3.0104167
 [13,] 277.3471  3.3576389
 [14,] 277.5270  4.7152778
 [15,] 277.5288  5.9027778

让我们看看这个2x15矩阵。我想要的是将其重塑为包含3个样本的3D数组,其中每个样本具有5行2列,对应于该矩阵的现有结构。因此,想象一下,我想将其拆分为3个元素的列表,其中每个元素都是5x2矩阵,其顺序与上面矩阵中的顺序相同。但是我不需要一个矩阵列表,而是一个数组。

期望输出,

,,1
X          Y
[1,] 276.9421  0.0000000
[2,] 276.4248 -5.3750000
[3,] 276.2253 -5.3333333
[4,] 275.9051 -3.8125000
[5,] 275.6589 -1.8200000

,,2
X          Y
[6,] 275.6311  0.6388889
[7,] 275.6540  2.2142857
[8,] 275.5883  2.9296875
[9,] 275.7367  3.2222222
[10,] 276.4208  3.2550000

,,3
X          Y
[11,] 277.0216  3.1528926
[12,] 277.3477  3.0104167
[13,] 277.3471  3.3576389
[14,] 277.5270  4.7152778
[15,] 277.5288  5.9027778

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我想到的两个想法涉及以某种形式拆分数据,然后使用array将数据转换为您想要的形式。

首先,这里有一些示例数据:

m <- structure(c(276.9421, 276.4248, 276.2253, 275.9051, 275.6589, 
    275.6311, 275.654, 275.5883, 275.7367, 276.4208, 277.0216, 277.3477, 
    277.3471, 277.527, 277.5288, 0, -5.375, -5.3333333, -3.8125, 
    -1.82, 0.6388889, 2.2142857, 2.9296875, 3.2222222, 3.255, 3.1528926, 
    3.0104167, 3.3576389, 4.7152778, 5.9027778), .Dim = c(15L, 2L
    ), .Dimnames = list(NULL, c("X", "Y")))

m
##              X          Y
##  [1,] 276.9421  0.0000000
##  [2,] 276.4248 -5.3750000
##  [3,] 276.2253 -5.3333333
##  [4,] 275.9051 -3.8125000
##  [5,] 275.6589 -1.8200000
##  [6,] 275.6311  0.6388889
##  [7,] 275.6540  2.2142857
##  [8,] 275.5883  2.9296875
##  [9,] 275.7367  3.2222222
## [10,] 276.4208  3.2550000
## [11,] 277.0216  3.1528926
## [12,] 277.3477  3.0104167
## [13,] 277.3471  3.3576389
## [14,] 277.5270  4.7152778
## [15,] 277.5288  5.9027778

最简单的选择是将matrix转换为data.frame,每5行拆分,取消列表,并将值放入array

array(unlist(split(data.frame(m), rep(1:3, each  = 5))), c(5, 2, 3))

我想到的第二个选项是直接拆分矩阵,按列拆分。

array(unlist(split(m, rep(gl(3, 5), 2)), use.names = FALSE), c(5, 2, 3))

这些中的任何一个都可以概括为可能如下所示的函数:

mat2_3d1 <- function(inmat, n) {
  if (nrow(inmat) %% n != 0) stop("incompatible dimensions provided")
  dims <- c(nrow(inmat) %/% n, ncol(inmat), n)
  temp <- split(data.frame(inmat), rep(sequence(n), each = dims[1]))
  array(unlist(temp, use.names = FALSE), dim = dims)
}

mat2_3d1(m, 3)

或者这个:

mat2_3d2 <- function(inmat, n) {
  if (nrow(inmat) %% n != 0) stop("incompatible dimensions provided")
  dims <- c(nrow(inmat) %/% n, ncol(inmat), n)
  array(unlist(split(inmat, gl(n, dims[1])), use.names = FALSE), dim = dims)
}

mat2_3d2(m, 3)

两者都会导致:

mat2_3d2(m, 3)
## , , 1
## 
##          [,1]      [,2]
## [1,] 276.9421  0.000000
## [2,] 276.4248 -5.375000
## [3,] 276.2253 -5.333333
## [4,] 275.9051 -3.812500
## [5,] 275.6589 -1.820000
## 
## , , 2
## 
##          [,1]      [,2]
## [1,] 275.6311 0.6388889
## [2,] 275.6540 2.2142857
## [3,] 275.5883 2.9296875
## [4,] 275.7367 3.2222222
## [5,] 276.4208 3.2550000
## 
## , , 3
## 
##          [,1]     [,2]
## [1,] 277.0216 3.152893
## [2,] 277.3477 3.010417
## [3,] 277.3471 3.357639
## [4,] 277.5270 4.715278
## [5,] 277.5288 5.902778
## 

我怀疑第二个选项会更有效率,因为它只是拆分一个向量,而不是转换为data.frame然后拆分。