5

同じ次元の別の行列の行と同じ順序で1つの行列の行を配置しようとしています。ただし、明示的なループなしでこれを行う方法を完全に理解することはできません。サブセット化と適用またはマップ関数を使用してこれを実行できるはずですが、その方法がわかりません。

これがおもちゃの例です:

sortMe <- matrix(rnorm(6), ncol=2)
sortBy <- matrix(c(2,1,3, 1,3,2), ncol=2)

sorted <- sortMe 
for (i in 1:ncol(sortMe)) {
  sorted[,i] <- sortMe[,i][sortBy[,i]]
}

この方法を使用すると、結果の行列には、行列と同じ順序で並べ替えられsortedた値が含まれます。ループなしでこれをどのように行うかについてのアイデアはありますか?sortMesortBy

4

3 に答える 3

9

これ(2列の整数行列を使用して行列の2つの次元にインデックスを付ける)は、次のトリックを実行する必要があります。

sorted <- sortMe
sorted[] <- sortMe[cbind(as.vector(sortBy), as.vector(col(sortBy)))]
于 2012-06-19T20:26:00.637 に答える
3

を使用lapplyすると機能します。

matrix(unlist(lapply(1:2, function(n) sortMe[,n][sortBy[,n]])), ncol=2)

しかし、おそらくもっと効率的な方法があります...

于 2012-06-19T20:22:24.333 に答える
3

元のバージョンを貼り付けることをお勧めします。あなたが書いた元のループは、提供されている他のソリューションよりもいくらか読みやすく、理解しやすい(おそらく書きやすい)と私は主張します。

また、ループは他のソリューションとほぼ同じくらい高速です:(彼が投稿から削除する前に@Josh O'Brienのタイミングコードを借りました。)

set.seed(444)
n = 1e7
sortMe <- matrix(rnorm(2 * n), ncol=2)
sortBy <- matrix(c(sample(n), sample(n)), ncol=2)

#---------------------------------------------------------------------------
# @JD Long, original post.
system.time({
    sorted_JD <- sortMe
    for (i in 1:ncol(sortMe)) {
        sorted_JD[, i] <- sortMe[, i][sortBy[, i]]
    } 
})
#   user  system elapsed 
#  1.190   0.165   1.334 

#---------------------------------------------------------------------------
# @Julius (post is now deleted).
system.time({
    sorted_Jul2 <- sortMe
    sorted_Jul2[] <- sortMe[as.vector(sortBy) + 
        rep(0:(ncol(sortMe) - 1) * nrow(sortMe), each = nrow(sortMe))]
})
#   user  system elapsed 
#  1.023   0.218   1.226 

#---------------------------------------------------------------------------
# @Josh O'Brien
system.time({
    sorted_Jos <- sortMe
    sorted_Jos[] <- sortMe[cbind(as.vector(sortBy), as.vector(col(sortBy)))]
})
#   user  system elapsed 
#  1.070   0.217   1.274 

#---------------------------------------------------------------------------
# @Justin
system.time({
    sorted_Just = matrix(unlist(lapply(1:2,
        function(n) sortMe[,n][sortBy[,n]])), ncol=2)
})
#   user  system elapsed 
#  0.989   0.199   1.162 


all.equal(sorted_JD, sorted_Jul2)
# [1] TRUE
all.equal(sorted_JD, sorted_Jos)
# [1] TRUE
all.equal(sorted_JD, sorted_Just)
# [1] TRUE
于 2012-06-20T01:21:09.033 に答える