2012-06-19 173 views
5

我試圖按照與同一維度的另一個矩陣的行相同的順序放置一個矩陣的行。但是我不能完全弄清楚如何在沒有顯式循環的情況下做到這一點。看來我應該可以通過子集和應用或Map函數來做到這一點,但我無法弄清楚如何去做。基於另一個矩陣對一個矩陣排序

這裏的一個玩具例子:使用此方法,將所得sorted矩陣包含從sortMe以相同的順序作爲sortBy矩陣排序的值

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

這(使用兩列整數矩陣指數矩陣的兩個維度)應該做的伎倆:

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

感謝剖析。這真的很有趣! –

相關問題