【问题标题】:Any way to achieve numpy-like indexing of multi-dimensional arrays in R?有什么方法可以在 R 中实现多维数组的类似 numpy 的索引?
【发布时间】:2021-02-10 20:10:34
【问题描述】:

假设我们有一个数组,x,维数至少为 2。我们有一个 indices 列表,我们想从 x 中检索和分配它。我想编写可以处理任意维度的x 的代码。

在 numpy 中,我们可以使用 x[indices,:] 轻松完成此操作,这适用于任意尺寸的 x。如果我们想在第一个维度以外的维度上建立索引,我们可以使用numpy.transpose 将其移动到第一个维度,然后在完成所需的索引后将其转回。在 R 中,aperm 提供等效功能。

但是,由于 R 中的索引行为略有不同,因此所需的功能似乎更难以实现。考虑:

x = array(0, c(5,4,3,2))
indices = c(1,2,3)
x[indices,]

x[1, ] 中的错误:维数不正确

使用 abind 包中的asub 解决了一半的问题,允许检索值:

asub(x, indices, 1, drop=FALSE)

除了以编程方式生成表达式x[indices,,,,],根据x 的维度插入所需的许多逗号,然后调用eval,我不确定是否有一种简单的方法来进行赋值。

有没有更好的方法可以在 R 中实现预期的结果?

【问题讨论】:

    标签: r


    【解决方案1】:

    以下适用于在任何 1-k 维度中分配常数:

    x = array(0, c(5,4,3,2))
    indices = c(1,2,3)
    
    k <- 1 # Dimension to subassign
    x[slice.index(x, k) %in% indices] <- 5
    

    但是,如果您想与indices 并行进行子赋值,这会变得有点不方便,尤其是在更高维度上,因为我们必须匹配数组的顺序。二维示例:

    x = array(0, c(5,4,3,2))
    k <- 2
    x[slice.index(x, k) %in% indices] <- rep(1:3, each = dim(x)[1])
    

    我想出的最佳选择如下:

    subassign_array <- function(x, i, k, value) {
      each <- pmax(prod(dim(x)[seq_len(k - 1)]), 1)
      x[slice.index(x, k) %in% i] <- rep(value, each = each)
      x
    }
    

    例如将第 3 维中的第 1 和第 2 元素替换为 1 和 2:

    subassign_array(x, 1:2, 3, 1:2)
    

    然而,这并没有涵盖子分配的所有可能情况。

    【讨论】:

    • 我应该澄清一下我正在努力解决的那种子分配:考虑y = array(1, c(3, 4, 3, 2)),一个可以填充任意值的正确形状的数组。本质上,我希望能够做到x[indices,] = y。不过,这个例子是说明性的,对常量赋值很有帮助。我可以看到如何修改它以进行数组分配。
    • 如果您认为您的修改对其他人也有用,请随时发布您自己的答案。
    • 对数组赋值的修改很简单:x[slice.index(x,k) %in% indices] &lt;- y
    【解决方案2】:

    您可以决定使用 R 函数。我不建议这样做,尽管您可以在以下行中写一些东西:

    np_array <- function(x){
      structure(x, class = c("np_array", class(x)))
    }
    
    print.np_array <- function(x){
      print(unclass(x))
    }
      
    "[.np_array" <-function(x,...){
      h <- match.call()
      h_len <- length(h)
      n <- seq_along(dim(x)) + 2
      n_len <- length(n)
      h[[2]]<- substitute(unclass(x))
      if(h_len - 2 < n_len){
        for(i in tail(n, n_len-h_len+2))
          h[i] <- h[i-1]
       }
      h[[1]]<-`[`
      eval(h, parent.frame())
    }
    

    现在你可以这样做了:

    x <- np_array(array(0, c(5,4,3,2)))
    x[1,]
    
    , , 1
    
         [,1] [,2] [,3]
    [1,]    0    0    0
    [2,]    0    0    0
    [3,]    0    0    0
    [4,]    0    0    0
    
    , , 2
    
         [,1] [,2] [,3]
    [1,]    0    0    0
    [2,]    0    0    0
    [3,]    0    0    0
    [4,]    0    0    0
    
    x[1,2,]
         [,1] [,2]
    [1,]    0    0
    [2,]    0    0
    [3,]    0    0
    
    x[,2,]
    , , 1
    
         [,1] [,2] [,3]
    [1,]    0    0    0
    [2,]    0    0    0
    [3,]    0    0    0
    [4,]    0    0    0
    [5,]    0    0    0
    
    , , 2
    
         [,1] [,2] [,3]
    [1,]    0    0    0
    [2,]    0    0    0
    [3,]    0    0    0
    [4,]    0    0    0
    [5,]    0    0    0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-05
      • 2020-03-25
      • 2015-04-19
      • 1970-01-01
      • 1970-01-01
      • 2021-01-04
      相关资源
      最近更新 更多