2011-09-22 17 views
10

En R, tengo una lista de objetos no triviales (no son objetos simples como escalares de los que se puede esperar que R pueda definir una orden). Quiero ordenar la lista La mayoría de los lenguajes permiten que el programador proporcione una función o similar que compare un par de elementos de lista que se pasan a una función de clasificación. ¿Cómo puedo ordenar mi lista?Ordene una lista de elementos no triviales en R

+0

¿Puedes proporcionar un fragmento de esta lista de elementos no triviales para que otros tengan una idea de lo que estás hablando? Consejos para escribir una pregunta reproducible aquí: http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example – Chase

Respuesta

14

Para hacer esto es tan simple que puedo decir que sus objetos son listas con dos elementos, un nombre y un valor. El valor es numérico; eso es lo que queremos ordenar. Puede imaginarse tener más elementos y la necesidad de hacer algo más complejo de ordenar.

La página de ayuda sort nos dice que sort utiliza xtfrm; xtfrm a su vez nos dice que utilizará los métodos == y > para la clase de x[i].

En primer lugar voy a definir un objeto que quiero para ordenar:

xx <- lapply(c(3,5,7,2,4), function(i) list(name=LETTERS[i], value=i)) 
class(xx) <- "myobj" 

Ahora, ya xtfrm trabajos sobre los x[i] 's, necesito definir una función que devuelve [ los elementos deseados, pero aún con la clase derecha

`[.myobj` <- function(x, i) { 
    class(x) <- "list" 
    structure(x[i], class="myobj") 
} 

Ahora necesitamos == y > funciones para la clase myobj; esto potencialmente podría ser más inteligente al vectorizar estos adecuadamente; pero para la función de clasificación, sabemos que solo vamos a pasar myobj de longitud 1, así que solo usaré el primer elemento para definir las relaciones.

`>.myobj` <- function(e1, e2) { 
    e1[[1]]$value > e2[[1]]$value 
} 

`==.myobj` <- function(e1, e2) { 
    e1[[1]]$value == e2[[1]]$value 
} 

Ahora sort just works.

sort(xx) 

Podría considerarse más adecuada para escribir una función completa Ops para su objeto; sin embargo, para ordenar, esto parece ser todo lo que necesitas. Consulte p.89-90 en Venables/Ripley para obtener más información sobre cómo hacerlo utilizando el estilo S3. Además, si puede escribir fácilmente una función xtfrm para sus objetos, eso sería más simple y probablemente más rápido.

+0

Gracias Aaron. Fantástica respuesta. – Chris

+1

Eso es mucho trabajo para construir una solución menos general que la que se puede construir con bits R regulares: estos son dos usos de 'orden' que ordenan primero el valor: 'xx [orden (como.caracter (sapply (xx," ["," value ")))]', y luego en el nombre: 'xx [orden (como.carácter (sapply (xx, "[", "name")))] 'sin ninguna referencia a los métodos de clase. –

+0

@DWin tiene toda la razón; si puedes hacer algo más inteligente, ¡deberías! – Aaron

4

La función order le permitirá determinar el orden de los caracteres o los argumentos numéricos y romper los lazos con los argumentos subsiguientes. Debes ser más específico sobre lo que quieres. Produzca un ejemplo de un "objeto no trivial" y especifique el orden que desea en algún objeto R. Las listas son probablemente la mayoría de los objetos no vectorial:

> slist <- list(cc=list(rr=1), bb=list(ee=2, yy=7), zz="ww") 
> slist[order(names(slist))] # alpha order on names() 
$bb 
$bb$ee 
[1] 2 
$bb$yy 
[1] 7 
$cc 
$cc$rr 
[1] 1  
$zz 
[1] "ww" 

slist[c("zz", "bb", "cc")] # an arbitrary ordering 
$zz 
[1] "ww" 
$bb 
$bb$ee 
[1] 2 
$bb$yy 
[1] 7 
$cc 
$cc$rr 
[1] 1 
1

Una opción es crear un método xtfrm para sus objetos. Las funciones como order toman múltiples columnas que funcionan en algunos casos. También hay algunas funciones especializadas para casos específicos como mixedsort en el paquete gtools.

Cuestiones relacionadas