第一次在统计之都论坛发帖,如有冒犯欢迎指正。

现有一个结构为int [1:100, 1:100, 1:3]的三维数组A,数组中的每一个元素是0-255之间的整数。(是的,A是一个100x100的24位图像,图像的颜色是分红绿蓝三个通道存储的)

另有一个结构为int [1:2, 1:5]的、两行五列的矩阵B,B的每一列表示一个坐标,即两个0-100之间的整数。比如:

> B
     [,1] [,2] [,3] [,4] [,5]
[1,]   69   69   72   72   78
[2,]   10   11   45   46    5

请问我有没有办法在不使用循环的条件下,以B作为索引,读取A中对应坐标的颜色,得到一个结果为5x3或者3x5的矩阵?

失败的尝试一:将B转置以后得到5x2的矩阵,留出第三维的下标不写,但是这种情况下会产生数据结构错误:

> A[t(B),]
Error in A[t(B), ] : incorrect number of dimensions

失败的尝试二:将B的两行(X坐标和Y坐标)分别读取出来,作为A的下标索引。但是这种情况下会取得所有X坐标和Y坐标交叉处的值:

> A[B[1,],B[2,],]
, , 1

     [,1] [,2] [,3] [,4] [,5]
[1,]  237  237   34   34  255
[2,]  237  237   34   34  255
[3,]  237  237  255   34  237
[4,]  237  237  255   34  237
[5,]  237  237  255  255  237

, , 2

     [,1] [,2] [,3] [,4] [,5]
[1,]   28   28  177  177  242
[2,]   28   28  177  177  242
[3,]   28   28  242  177   28
[4,]   28   28  242  177   28
[5,]   28   28  242  242   28

, , 3

     [,1] [,2] [,3] [,4] [,5]
[1,]   36   36   76   76    0
[2,]   36   36   76   76    0
[3,]   36   36    0   76   36
[4,]   36   36    0   76   36
[5,]   36   36    0    0   36

但是我觉得这个情况稍好一点。有没有可能在这个基础上改进,或者使用其他方法,得到类似于下面这样的结果:

     [,1] [,2] [,3] [,4] [,5]
[1,]  237  237  255   34  237
[2,]   28   28  242  177   28
[3,]   36   36    0   76   36

    不熟悉论坛发布等宽字符内容的方式,内容格式不太适合阅读,抱歉。

      Heterogeneity

      apply(A[B[1, ], B[2, ], ], 3, diag) 

      就好了。你已经很接近了,只是没意识到在第三维上,对角线元素就是你要的东西。剩下的由于第一维和第二维坐标交叉得到的元素都应该扔掉,所以你对第三维应用一个对角线函数 diag() 即可。这个办法不是很高效,因为是先取了大量的不需要的值然后再取子集,有点绕道,但在 R 的层面上应该只能做到这样了;要真正高效读取那些你需要的值,可能还得用底层语言暴力循环(比如 Rcpp 应该是一个好的选择)。

      Heterogeneity 没事,你的主要问题是你不知道反引号(backtick)和单引号之间的区别,代码块应该用反引号。我帮你编辑了。

        COS 八卦群里有杨大侠给出了满分答案,否定了我上面“在 R 的层面上应该只能做到这样了”这个说法:

        apply(A, 3, `[`, t(B))

        今天是我用 R 十几年第一次看方括号的文档 ?`[`,里面有一句:

        When indexing arrays by [ a single argument i can be a matrix with as many columns as there are dimensions of x; the result is then a vector with elements corresponding to the sets of indices in each row of i.

        太烧脑。如果是我,我……我还是选择用循环吧,要烧就烧电脑……

          dapengde 三维数组还好啦,起码还可以想象立方体,对立方体用 apply() 函数也就是把立方体切片(得到一层一层的矩阵),然后对每一片应用一个函数。要是更高维的数组,就不方便用立体想象力了。

          6 天 后

          续个万能狗尾——

          A <- array(sample(256,3e4,T)-1,dim = c(100,100,3))
          B <- matrix(sample(100,10,T),ncol = 5)
          sapply(1:3, function(i) {A[cbind(t(B ),i)]})

          我的问题是 sapply(1:n, FUNCTION) 真会比for循环快么?

            5 个月 后
            1 年 后
            Heterogeneity 更改标题为「【已解决】R语言中以矩阵引用多维数组的元素
            9 个月 后