2012-06-19 2 views
5

동일한 차원의 다른 행렬의 행과 동일한 순서로 행렬의 행을 넣으려고합니다. 그러나 나는 명확한 루프없이 이것을 어떻게하는지 알아낼 수 없다. 하위 집합 및 적용 또는 맵 함수를 사용하여이 작업을 수행 할 수 있어야하지만이 작업을 수행하는 방법을 알 수는 없습니다. 얻어진 sorted 행렬은 행렬 sortBy와 동일한 순서로 정렬 sortMe의 값을 포함하고,이 방법을 사용다른 행렬을 기반으로 하나의 행렬 정렬

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

감사합니다. 정말 재미 있어요! –

관련 문제