2012-06-19 48 views
5

Tôi đang cố gắng đặt các hàng của một ma trận theo thứ tự giống như các hàng của một ma trận khác có cùng kích thước. Tuy nhiên tôi không thể tìm ra cách để làm điều này mà không có một vòng lặp rõ ràng. Có vẻ như tôi sẽ có thể làm điều này với subsetting và một chức năng áp dụng hoặc bản đồ, nhưng tôi không thể tìm ra cách để làm điều đó.Sắp xếp một ma trận dựa trên một ma trận khác

Dưới đây là một ví dụ đồ chơi:

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]] 
} 

Sử dụng phương pháp này, kết quả sorted ma trận chứa các giá trị từ sortMe được sắp xếp theo thứ tự giống như ma trận sortBy. Bất kỳ ý tưởng làm thế nào tôi muốn làm điều này mà không có vòng lặp?

Trả lời

8

này (sử dụng một ma trận số nguyên hai cột để chỉ số hai chiều của ma trận) nên làm các trick:

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

Sử dụng lapply sẽ hoạt động.

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

Nhưng có lẽ là một cách hiệu quả hơn ...

3

Tôi sẽ đề nghị bạn dán cho bạn phiên bản gốc của bạn. Tôi cho rằng vòng lặp ban đầu bạn đã viết có phần dễ đọc hơn và dễ hiểu hơn (cũng có thể dễ viết hơn) so với các giải pháp khác được cung cấp.

Ngoài ra, các vòng lặp là gần nhanh như các giải pháp khác: (Tôi mượn mã thời gian @Josh O'Brien trước khi ông loại bỏ nó từ bài của ông.)

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

Cám ơn profiling. Điều đó thực sự thú vị! –

Các vấn đề liên quan