2017-05-17 24 views
1

は、2Dマトリックスaシフトのpracmaパッケージの例である:循環シフトアレイR

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] 
} 

IシフトしようとしていますここではN次元の配列、及び、私は、これまでに作ってみたものです:

else if (is.array(a) && length(sz) > 2) { 
    n <- dim(a) 
    l <- length(n) 
    for (i in 1:l) { 
     s <- sz[i] %% n[i] 
     #???? 
    } 

私が考えていたアイデアは、別途のためのループ内で循環シフトに各次元になります。しかし、ベクトル/行列型コード(次元があらかじめ与えられている)がこの状況では機能しないので、私はそれを行う方法があるかどうかわかりません...

具体的にはプラクマコード内の各ディメンションを明示的に索引付けする必要がありますが、ディメンションの数がわからない場合は不可能と思われます。あなたは、次のアプローチでこれを行うことができます

答えて

2

(あるいは、より可能性が高い、私は方法がわからない):

することができます
  1. 指数a:

    # 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)) 
    } 
    

    これは、二つのトリックを使用していますあなたはカンマで区切られたベクトルだけでなく、別の行列を使って行列を作成することもできます(例えば、as.matrix(mtcars)[cbind(1:3, 2:4)]を実行するとベクターに変換されますが、同じ次元の配列に戻すことができます)。

  2. expand.gridを使用して、複数のベクトルのすべての組み合わせを作成できます。あなたが望むインデックスベクトルを与えることによって、それらのそれぞれを適切に繰り返すことができます。

あなたは、これは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)))