循环移位阵列R.

时间:2017-05-17 19:13:31

标签: arrays r

我正在尝试在R中循环移动N维数组。以下是移动2D矩阵pracma的{​​{1}}包中的示例:

a

我正在尝试移动一个N维数组,这是我到目前为止所提出的:

if (is.matrix(a) && length(sz) == 2) {
    n <- nrow(a); m <- ncol(a)
    s1 <- sz[1] %% n
    s2 <- sz[2] %% m
    a <- a[(1:n-s1-1) %% n + 1, (1:m-s2-1) %% m + 1]
}

我想到的想法是分别循环移动for循环中的每个维度。但我无法弄清楚是否有办法做到这一点,因为矢量/矩阵类型代码(预先给出尺寸)将无法在这种情况下工作......

更具体地说,您必须在语法代码中明确索引每个维度,但如果您不知道维度有多少,这似乎是不可能的。 (或者,更有可能的是,我只是不知道如何)

1 个答案:

答案 0 :(得分:2)

您可以使用以下方法执行此操作:

# using map2 from purrr for simplicity, though you could also use lapply
library(purrr)

circshift_any <- function(a, sz) {
  indexers <- map2(dim(a), sz, function(len, s) (1:len - s - 1) %% len + 1)
  indexing_matrix <- as.matrix(do.call(expand.grid, indexers))

  array(a[indexing_matrix], dim(a))
}

这使用了两个技巧:

  1. 您可以使用另一个矩阵索引矩阵,而不仅仅是使用逗号分隔的向量(例如,您可以执行as.matrix(mtcars)[cbind(1:3, 2:4)]。它会将其转换为向量,但您可以将其返回到数组相同的尺寸。

  2. 您可以使用expand.grid创建多个向量的所有组合。通过给它你想要的索引向量,你可以让每一个都适当重复。

  3. 通过将其与pracma的输出进行比较,您可以确认这适用于2d矩阵:

    a <- array(1:100, c(5, 20))
    
    identical(pracma::circshift(a, c(3, 6)), circshift_any(a, c(3, 6)))
    identical(pracma::circshift(a, c(23, 19)), circshift_any(a, c(23, 19)))