r plyr

Crear columnas a partir de factores y contar



plyr (2)

Un problema aparentemente fácil es mantenerme muy ocupado.

Tengo un marco de datos:

> df1 Name Score 1 Ben 1 2 Ben 2 3 John 1 4 John 2 5 John 3

Me gustaría crear un resumen de la tabla como este:

> df2 Name Score_1 Score_2 Score_3 1 Ben 1 1 0 2 John 1 1 1

Entonces df2 debe (i) mostrar solo "Nombres" únicos y (ii) crear columnas a partir de los factores únicos en "Puntaje" y (iii) contar el número de veces que una persona recibió dicho puntaje.

Yo he tratado:

df2 <- ddply(df1, c("Name"), summarise ,Score_1 = sum(df1$Score == 1) ,Score_2 = sum(df1$Score == 2) ,Score_3 = sum(df1$Score == 3))

que produce:

Name Score_1 Score_2 Score_3 1 Ben 2 2 1 2 John 2 2 1

Entonces mi intento cuenta incorrectamente todas las ocurrencias en lugar de contar "por grupo"

EDITAR: Según los comentarios, también intenté reshape (posiblemente solo lo hice mal):

> reshape(df1, idvar = "Name", timevar = "Score", direction = "wide") Name 1 Ben 3 John

Para empezar, falta la columna "Puntuación", pero peor que eso, de mi investigación sobre la reshape , no estoy convencido de que voy a obtener un recuento de cada factor, que es el punto central.


Podemos usar dplyr/tidyr

library(dplyr) library(tidyr) df1 %>% group_by(Name) %>% mutate(n=1, Score= paste(''Score'', Score, sep=''_'')) %>% spread(Score, n, fill=0) # Name Score_1 Score_2 Score_3 # (chr) (dbl) (dbl) (dbl) #1 Ben 1 1 0 #2 John 1 1 1


Solo necesita hacer una ligera modificación en su código. Debería usar .(Name) lugar de c("Name") :

ddply(df1, .(Name), summarise, Score_1 = sum(Score == 1), Score_2 = sum(Score == 2), Score_3 = sum(Score == 3))

da:

Name Score_1 Score_2 Score_3 1 Ben 1 1 0 2 John 1 1 1

Otras posibilidades incluyen:

1. table(df1) como @alexis_laz mencionado en los comments , esto da:

> table(df1) Score Name 1 2 3 Ben 1 1 0 John 1 1 1

2. La función dcast del paquete reshape2 (o data.table que tiene la misma función dcast ):

library(reshape2) # or library(data.table) dcast(df1, Name ~ paste0("Score_", Score), fun.aggregate = length)

da:

Name Score_1 Score_2 Score_3 1 Ben 1 1 0 2 John 1 1 1