2010-04-12 15 views
16

estoy usando el "por" función en R para picar una trama de datos y aplicar una función a diferentes partes, así:Convertir a "por" objeto de una trama de datos en I

pairwise.compare <- function(x) { 
Nright <- ... 
Nwrong <- ... 
Ntied <- ... 
return(c(Nright=Nright, Nwrong=Nwrong, Ntied=Ntied)) 
} 
Z.by <- by(rankings, INDICES=list(rankings$Rater, rankings$Class), FUN=pairwise.compare) 

el resultado (Z.by) se ve algo como esto:

: 4 
: 357 
Nright Nwrong Ntied 
    3  0  0 
------------------------------------------------------------ 
: 8 
: 357 
NULL 
------------------------------------------------------------ 
: 10 
: 470 
Nright Nwrong Ntied 
    3  4  1 
------------------------------------------------------------ 
: 11 
: 470 
Nright Nwrong Ntied 
    12  4  1 

lo que me gustaría es tener este resultado convertida en una trama de datos (con las entradas NULL que no están presentes) por lo que se ve así:

Rater Class Nright Nwrong Ntied 
1  4 357  3  0  0 
2 10 470  3  4  1 
3 11 470  12  4  1 

¿Cómo hago eso?

Respuesta

8

Considere el uso de ddply en el paquete plyr en lugar de por. Maneja el trabajo de agregar la columna a su marco de datos.

16

La función devuelve una lista by, por lo que puede hacer algo como esto:

data.frame(do.call("rbind", by(x, column, mean))) 
+0

Eso casi hace lo que yo quiero, me sale un cuadro de datos con las columnas Nright, Nwrong y Ntied, pero no produce las columnas Evaluador y de clase. –

+2

Sugeriría cambiar su función 'pairwise.compare' para devolver esos dos campos. De lo contrario, tendrá que usar una rutina 'lapply' (o' plyr') para obtener los nombres y valores de la lista (que es un paso adicional). – Shane

+0

Parece que plyr es en realidad una solución más simple que en este caso, simplemente no sabía sobre ese paquete antes. –

3

hilo viejo, pero para cualquier persona que busca para este tema:

analysis = by(...) 
data.frame(t(vapply(analysis,unlist,unlist(analysis[[1]])))) 

unlist() tendrá un elemento de una salida by() (en este caso, analysis) y expresarlo como un vector llamado. vapply() no se ha unido a todos los elementos de analysis y muestra el resultado. Requiere un argumento ficticio para conocer el tipo de salida, que es lo que analysis[[1]] está ahí para. Es posible que deba agregar una verificación de que el análisis no está vacío si eso es posible. Cada salida será una columna, por lo que t() la transpone a la orientación deseada donde cada entrada de análisis se convierte en una fila.

+0

Esta solución no funciona si tiene tipos mixtos en su data.frame (como los caracteres en una columna y los numéricos en otro), porque se basa en 'vapply'. En este caso específico, la solución anterior de Shane funciona perfectamente bien sin embargo. – Jealie

2

Esto amplía la solución de Shane de usar rbind() pero también agrega columnas que identifican grupos y elimina grupos NULL, dos características que se solicitaron en la pregunta. Al usar funciones de paquete base, no se requieren otras dependencias, por ejemplo, plyr.

simplify_by_output = function(by_output) { 
    null_ind = unlist(lapply(by_output, is.null)) # by() returns NULL for combinations of grouping variables for which there are no data. rbind() ignores those, so you have to keep track of them. 
    by_df = do.call(rbind, by_output) # Combine the results into a data frame. 
    return(cbind(expand.grid(dimnames(by_output))[!null_ind, ], by_df)) # Add columns identifying groups, discarding names of groups for which no data exist. 
} 
2

lo haría

x = by(data, list(data$x, data$y), function(d) whatever(d)) 
array(x, dim(x), dimnames(x)) 
Cuestiones relacionadas