2012-06-19 172 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

感谢剖析。这真的很有趣! –

相关问题