2012-06-19 28 views
5

Estoy tratando de poner las filas de una matriz en el mismo orden que las filas de otra matriz de la misma dimensión. Sin embargo, no puedo entender cómo hacerlo sin un bucle explícito. Parece que debería poder hacer esto con subconjuntos y una función de aplicación o mapa, pero no puedo encontrar la manera de hacerlo.Ordenar una matriz en función de otra matriz

Aquí está un ejemplo de juguete:

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

Usando este método, la sorted matriz resultante contiene los valores de sortMe ordenados en el mismo orden que la matriz sortBy. ¿Alguna idea de cómo haría esto sin el bucle?

Respuesta

8

Este (usando una matriz de enteros de dos columnas de índice de dos dimensiones de la matriz) debe hacer el truco:

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

El uso de lapply funcionaría.

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

Pero es probable que haya una manera más eficiente ...

3

Voy a sugerirle que le pegue su versión original. Yo diría que el ciclo original que escribió es algo más fácil de leer y comprender (también probablemente más fácil de escribir) que las otras soluciones que se ofrecen.

Además, el bucle es casi tan rápido como las otras soluciones: (I prestado código de tiempo de @ Josh O'Brien antes de que él lo quitó de su puesto.)

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

Gracias por perfiles. ¡Eso es realmente interesante! –

Cuestiones relacionadas