Crear columnas a partir de factores y contar
plyr (2)
Esta pregunta ya tiene una respuesta aquí:
- ¿Cómo obtengo una tabla de contingencia? 6 respuestas
- Maneras más rápidas de calcular frecuencias y emitir de 4 a 4 respuestas
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