R数组索引。如何使用矩阵为第三维度索引三维数组

6
我有一个关于索引三维数组的问题。
假设我有一个三维数组。
x<- c(1:36)
dim(x) <- c(3,4,3) 

现在我想根据一个矩阵从这个数组中提取值,该矩阵保存了所有[i,j]位置的第3维索引。
y <- c(rep(1,4),rep(2,4),rep(3,4))
dim(y) <- c(3,4)

y
      [,1] [,2] [,3] [,4]
[1,]    1    1    2    3
[2,]    1    2    2    3
[3,]    1    2    3    3

所以结果应该是这样的:
     [,1] [,2] [,3] [,4]
[1,]    1    4   19   34
[2,]    2   17   20   35
[3,]    3   18   33   36

有没有一种优雅的方法来做这件事?我知道如何使用两个for循环遍历数组,但对于我的数据来说这太慢了。
2个回答

7

help("[")告诉我们:

矩阵和数组

[...]

第三种索引方式是使用数值矩阵,每个维度有一列:索引矩阵的每一行选择数组的一个元素,并且结果是一个向量。

因此,我们将您的y矩阵转换为符合这个形状。

library(reshape2)
z <- x[as.matrix(melt(y))]
dim(z) <- dim(y)
#     [,1] [,2] [,3] [,4]
#[1,]    1    4   19   34
#[2,]    2   17   20   35
#[3,]    3   18   33   36

非常感谢您的帮助。是的,阅读帮助文件是一个非常好的主意。总是如此。顺便问一下,在索引矩阵中是否可以使用一些条件测试?例如 x>3? - Atomhamster

5

我认为这是一次进行代码高尔夫的机会。将其转化为一行代码是完全可行的:

> `dim<-`(x[cbind(c(row(y)), c(col(y)), c(y))], dim(y))
     [,1] [,2] [,3] [,4]
[1,]    1    4   19   34
[2,]    2   17   20   35
[3,]    3   18   33   36

正如@Roland的回答所示,矩阵/数组索引涉及创建一个n列矩阵,并将每个维度的行、列等位置设置为n维数组的行、列等位置。我们可以使用row()和col()函数来提取y中每个元素的行和列位置:
> row(y)
     [,1] [,2] [,3] [,4]
[1,]    1    1    1    1
[2,]    2    2    2    2
[3,]    3    3    3    3
> col(y)
     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]    1    2    3    4
[3,]    1    2    3    4

y本身提供了第三维位置信息。将每个位置信息用c()包装成向量,使它们可以 cbind在一起创建提取矩阵。

然后,使用dim<-()来将所有内容放在一行上,非常有趣。


1
谢谢Thomas。我喜欢你的雄心壮志。我也是一个只在可能的情况下使用基本函数的忠实粉丝。但是我必须说,我不理解你对dim的有趣使用。它是如何工作的?反引号的作用是什么? - Atomhamster
@Atomhamster 当你执行 dim(x) <- dim(y) 时,实际上你正在执行 dim<-(x, dim(y)),其中 "dim<-" 是一个函数的名称。当你想要使用像 dim<-()names<-() 这样的函数而不必先创建左侧对象时,这是非常有用的。(反引号只是让你直接调用 "dim<-()" 函数,但它们很难在此评论标记中编写。) - Thomas
谢谢@Thomas的解释。知道这个技巧非常有趣。我猜它可以在我的函数中节省很多行代码。 - Atomhamster
@Atomhamster 另一种更直观的方法可能是来自setter包:https://cran.r-project.org/web/packages/setter/setter.pdf - Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接