2012-06-19 12 views
5

同じ次元の別の行列の行と同じ順序で1つの行列の行を入れようとしています。しかし、私は明示的なループなしでこれを行う方法を理解することはできません。私は部分集合と適用またはマップ関数でこれを行うことができるはずですが、私はそれを行う方法を理解できません。得sorted行列はsortByマトリックスと同じ順序でソートsortMeからの値が含まれ、この方法を使用別の行列に基づいて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]] 
} 

ここ玩具例です。どのように私はループなしでこれを行うだろう任意のアイデア?

答えて

8

この(インデックスに2列の整数行列を用いた行列の2次元)トリックを行う必要があります。

sorted <- sortMe 
sorted[] <- sortMe[cbind(as.vector(sortBy), as.vector(col(sortBy)))] 
3

lapplyを使用すると効果があります。

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

しかし、もっと効率的な方法は、おそらくそこにある...

3

私はあなたにオリジナル版を貼っておくことを提案するつもりです。私が書いたオリジナルのループは、提供されている他のソリューションよりも読みやすく理解しやすい(おそらく書きやすい)と主張します。

また、ループは、他のソリューションとほぼ同じ速さである:(彼は彼のポストからそれを削除する前に、私は@Joshオブライエンのタイミングコードを借りた。)プロファイリングのため

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 
+0

感謝。それは本当に面白いです! –

関連する問題