2010-10-21 35 views
6

Estoy intentando dar sentido a cómo ordenar un data.frame basado en múltiples columnas en otro. Esta pregunta does this with vectors. ¿Alguien puede sugerir una forma de hacer el equivalente con data.frames?R: Ordenar columnas múltiples por otro data.frame?

Aquí hay algunos datos de muestra.

x1 <- data.frame(a=1:5, b=letters[1:5], c=rnorm(5)) 
x2 <- data.frame(a=c(4,4,2), b=c("d", "d", "b"), d=rnorm(3)) 

Así que quiero ordenar x2 por las dos primeras columnas de x1. Mis datos real es mucho más complicado, pero esto se replica la idea ...

Respuesta

9

Realmente depende de cómo se ve realmente tu información. Como se ve en este momento, sólo necesita una columna para ordenar, y que se hace fácilmente:

x2[order(match(x2[,1],x1[,1])),] 

Si necesita más de una columna, esto se convierte en un poco más complicado. Tendrá que especificar cuál desea ordenar por primera vez, y lo que un segundo, por ejemplo:

x1 <- data.frame(a=rep(1:3,2), b=rep(letters[2:4],each=2), c=rnorm(6)) 
x2 <- data.frame(a=c(3,3,2), b=c("c", "d", "b"), d=rnorm(3)) 


x2[order(match(
    paste(x2[,1],x2[,2]), 
    paste(x1[,1],x1[,2])) 
),] 

esta forma se ordenan en la primera columna, y luego en el segundo. Debe tener en cuenta que necesita todas las combinaciones en x2 también en x1. T

2

Adjuntar una columna de rango a las columnas correspondientes de x1:

len <- dim(x1)[1] 
x1. <- cbind(x1[,1:2], rank=1:len) 

Combinar en x2 (esto es como un SQL unirse; véase la documentación de mezcla para cómo especificar qué sucede si hay ambigüedades como varios partidos o no partidos):

x2. <- merge(x2, x1.) 

Ordenar:

x2.[order(x2.[,'rank']),] 
1

Esto se puede hacer con precisión usando plyr. respuesta Joris funcionaría bastante bien, pero potencialmente podría missort al combinar cadenas:

> paste ("A A","B") 
[1] "A A B" 
> paste ("A","A B") 
[1] "A A B" 

Usted puede obtener una respuesta exacta usando join.keys y match:

x1 <- data.frame(a=rep(1:3,2), b=rep(letters[2:4],each=2), c=rnorm(6)) 
x2 <- data.frame(a=c(3,3,2), b=c("c", "d", "b"), d=rnorm(3)) 

library(plyr) 
keys<-join.keys(x1,x2,c("a","b")) 
matches<-match(keys$y,keys$x,nomatch=(keys$n+1)) 
x2[order(matches),] 

Esto debe manejar la mayoría de los casos límite, la lista no coincidentes tamaños, etc. Los elementos sin coincidencia en ambas columnas de índice se colocan al final de la lista.

Cuestiones relacionadas