【问题标题】:Fill multidimensional array by row逐行填充多维数组
【发布时间】:2015-10-23 16:01:36
【问题描述】:

在提出问题之前,我要指出,here 有人问过类似的问题,但这个帖子并没有真正回答我的问题。

考虑以下维度数组:

 1D: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
 2D: [[1,2,3,4,5,6,7,8], [9,10,11,12,13,14,15,16]]
 3D: [[[1,2,3,4],[5,6,7,8]], [[9,10,11,12],[13,14,15,16]]]
 4D: [[[[1,2],[3,4]], [[5,6],[7,8]], [[[9,10],[11,12]], [[13,14],[15,16]]]]
 ...
  • 一维数组的长度为 16
  • 二维数组是 2x8
  • 3D 阵列为 2x2x4
  • 4D 数组是 2x2x2x2

假设我想创建数组。对于前两个,我可以在 R 中做这样的事情

oneD <- array(1:16, dim=16) # class(oneD) = array
twoD <- array(1:16, dim=8) # class(twoD) = matrix

但是,二维数组现在表示为

[[1,3,5,7,9,11,13,15], [2,4,6,8,10,12,14,16]]

我知道解决这个问题的两种方法。

twoD <- aperm(array(1:16, dim=8))
twoD <- matrix(1:16, nrow=2, byrow=TRUE)

但是,这些方法不适用于填充 3D 和 4D 数组。我在下面填写它们,但我希望它们与我上面的定义相匹配。

threeD <- array(1:16, dim=c(2,2,4)) # class(threeD) = array
fourD <- array(1:16, dim=c(2,2,2,2)) # class(fourD) = array

编辑

bgoldst 的回答让我意识到事实上 aperm 确实可以满足我的需求。

threeD <- aperm(array(1:16, dim=c(2,2,4))
# threeD[1,1,1] = 1
# threeD[1,1,2] = 2
# threeD[1,2,1] = 3
# threeD[1,2,2] = 4
# threeD[2,1,1] = 5
# ....

【问题讨论】:

  • 这些叫数组吗?从结构上看,它们更像树。
  • 另外,也许length() 可以帮助你?
  • 您的思维方式似乎是行主导的。如果使用 R,您应该将矩阵和数组构造视为面向列的,
  • 你用 R 构建的结构没有提供你认为的那样。你应该把它们打印出来。

标签: arrays r matrix multidimensional-array vector


【解决方案1】:

按照您写入数据的方式,您需要先在最深的维度上填充数组,然后再在较浅的维度上填充数组。这与 R 通常填充矩阵/数组的方式相反。

还需要说一下,这与简单的逐行填充略有不同。为了使用您的 3D 数组来说明这一点,您已经指出它需要 4 个 z 切片,并且最里面的“子数组”的长度为 4。这意味着您需要先填充 z 切片,然后跨列,然后跨行。这不仅仅是按行填充,而是按最深维度到最浅维度(或从最大到最小,如果您愿意的话)。诚然,这个概念通常被称为“按行”或“行主要顺序”,但我不关心这些术语,因为它们太二维了,而且它们也误导了 IMO,因为考虑了行成为最浅的维度。

详细说明:最好将填充顺序视为维度而不是沿维度。想象一个 r×c×z 立方体。如果您面向立方体的正面(即,面向由 z = 1 形成的 r×c 矩阵),如果您move along row r = 1,即沿着顶行从左到右,那么你也在along(或within) z-slice z = 1。沿维度移动的想法没有帮助。但是,如果您将这种从左到右的移动视为 列,那么这是完全明确的。因此,跨行意味着上下,跨列意味着左右,跨z切片意味着前后。另一种思考方式是每个各自的运动都沿着维度“轴”,虽然我通常不喜欢这样想,因为那时你必须引入轴的概念。无论如何,这就是为什么我不关心术语“按行”和“行主要顺序”(以及类似的“列主要顺序”),因为考虑该运动(IMO)的正确方法是 对于 2D 跨列,对于更高维度,跨最深维度(后跟较浅维度)。

您可以通过首先构建具有反向维度的数组,然后将它们转置为“去反向”(?)维度来实现要求。这将根据需要布置数据。当然,对于 1D,不需要转置,对于 2D,我们可以使用 t(),但对于更高维度,我们需要 aperm()。并且方便的是,当您调用 aperm() 而不指定 perm 参数时,默认情况下它会反转输入的维度;这就像打电话给t()

array(1:16,16);
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16
t(array(1:16,c(8,2))); ## alternatives: matrix(1:16,2,byrow=T), aperm(array(1:16,c(8,2)))
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,]    1    2    3    4    5    6    7    8
## [2,]    9   10   11   12   13   14   15   16
aperm(array(1:16,c(4,2,2))); ## same as aperm(array(1:16,c(4,2,2)),3:1)
## , , 1
##
##      [,1] [,2]
## [1,]    1    5
## [2,]    9   13
##
## , , 2
##
##      [,1] [,2]
## [1,]    2    6
## [2,]   10   14
##
## , , 3
##
##      [,1] [,2]
## [1,]    3    7
## [2,]   11   15
##
## , , 4
##
##      [,1] [,2]
## [1,]    4    8
## [2,]   12   16
##
aperm(array(1:16,c(2,2,2,2))); ## same as aperm(array(1:16,c(4,2,2)),4:1)
## , , 1, 1
##
##      [,1] [,2]
## [1,]    1    5
## [2,]    9   13
##
## , , 2, 1
##
##      [,1] [,2]
## [1,]    3    7
## [2,]   11   15
##
## , , 1, 2
##
##      [,1] [,2]
## [1,]    2    6
## [2,]   10   14
##
## , , 2, 2
##
##      [,1] [,2]
## [1,]    4    8
## [2,]   12   16
##

【讨论】:

  • 谢谢 - 我感谢您对跨维度填充订单的解释,并且 aperm 函数正是我想要的。我没有意识到 R 总是首先填充浅维度。
猜你喜欢
  • 1970-01-01
  • 2019-01-18
  • 1970-01-01
  • 2020-08-02
  • 2011-01-11
  • 1970-01-01
  • 2012-11-27
相关资源
最近更新 更多