2011-11-15 6 views
11

que tengo un conjunto de datos con cerca de 3 millones de filas y la siguiente estructura:La forma más rápida para formar de nuevo los valores de variables como columnas

PatientID| Year | PrimaryConditionGroup 
--------------------------------------- 
1  | Y1 | TRAUMA 
1  | Y1 | PREGNANCY 
2  | Y2 | SEIZURE 
3  | Y1 | TRAUMA 

ser bastante nuevo en R, tengo algunos problemas para encontrar el camino correcto para formar de nuevo los datos en la estructura detalla a continuación:

PatientID| Year | TRAUMA | PREGNANCY | SEIZURE 
---------------------------------------------- 
1  | Y1 | 1  | 1   | 0 
2  | Y2 | 0  | 0   | 1 
3  | Y1 | 1  | 0   | 1 

Mi pregunta es: ¿Cuál es la manera más rápida/más elegante para crear un hoja.de.datos, donde los valores de PrimaryConditionGroup se convierten en columnas, agrupados por PatientID y año (contando el número de ocurrencias)?

Respuesta

12

Probablemente hay formas más sucintas de hacer esto, pero para la velocidad pura, es difícil de superar un data.table solución basada en:

df <- read.table(text="PatientID Year PrimaryConditionGroup 
1   Y1 TRAUMA 
1   Y1 PREGNANCY 
2   Y2 SEIZURE 
3   Y1 TRAUMA", header=T) 

library(data.table) 
dt <- data.table(df, key=c("PatientID", "Year")) 

dt[ , list(TRAUMA = sum(PrimaryConditionGroup=="TRAUMA"), 
      PREGNANCY = sum(PrimaryConditionGroup=="PREGNANCY"), 
      SEIZURE = sum(PrimaryConditionGroup=="SEIZURE")), 
    by = list(PatientID, Year)] 

#  PatientID Year TRAUMA PREGNANCY SEIZURE 
# [1,]   1 Y1  1   1  0 
# [2,]   2 Y2  0   0  1 
# [3,]   3 Y1  1   0  0 

EDIT:aggregate() proporciona una solución 'base R' que podría o puede que no sea más idiomático. (La única complicación es que agregada devuelve una matriz, en lugar de un hoja.de.datos; la segunda línea debajo de correcciones de eso.)

out <- aggregate(PrimaryConditionGroup ~ PatientID + Year, data=df, FUN=table) 
out <- cbind(out[1:2], data.frame(out[3][[1]])) 

2a Edición Por último, una solución sucinta utilizando el paquete reshape se llega a el mismo lugar.

library(reshape) 
mdf <- melt(df, id=c("PatientID", "Year")) 
cast(PatientID + Year ~ value, data=j, fun.aggregate=length) 
+0

+1 'ddply' no será mucho menos tipeo, en realidad, y por supuesto será mucho más lento. – joran

+1

¿Por qué siquiera consideraría ddply para este problema? – hadley

+0

Hola Josh, gracias, esto funciona como se espera y funciona muy bien. ¿Cuál sería la forma más concisa/idiomática de reformar los datos? (Si el rendimiento no era una preocupación) – Matt

1

No son rápidos melt y dcast métodos específicos data.table implementados en C, en versiones >=1.9.0. Aquí hay una comparación con otras respuestas excelentes de la publicación de @Josh en datos de 3 millones de filas (simplemente excluyendo el agregado base ::: ya que tarda bastante).

Para obtener más información sobre la entrada de NOTICIAS, vaya here.

Supongo que tiene 1000 pacientes y 5 años en total. Puede ajustar las variables patients y year en consecuencia.

require(data.table) ## >= 1.9.0 
require(reshape2) 

set.seed(1L) 
patients = 1000L 
year = 5L 
n = 3e6L 
condn = c("TRAUMA", "PREGNANCY", "SEIZURE") 

# dummy data 
DT <- data.table(PatientID = sample(patients, n, TRUE), 
       Year = sample(year, n, TRUE), 
       PrimaryConditionGroup = sample(condn, n, TRUE)) 

DT_dcast <- function(DT) { 
    dcast.data.table(DT, PatientID ~ Year, fun.aggregate=length) 
} 

reshape2_dcast <- function(DT) { 
    reshape2:::dcast(DT, PatientID ~ Year, fun.aggregate=length) 
} 

DT_raw <- function(DT) { 
    DT[ , list(TRAUMA = sum(PrimaryConditionGroup=="TRAUMA"), 
      PREGNANCY = sum(PrimaryConditionGroup=="PREGNANCY"), 
       SEIZURE = sum(PrimaryConditionGroup=="SEIZURE")), 
    by = list(PatientID, Year)] 
} 

# system.time(.) timed 3 times 
#   Method Time_rep1 Time_rep2 Time_rep3 
#  dcast_DT  0.393  0.399  0.396 
# reshape2_DT  3.784  3.457  3.605 
#   DT_raw  0.647  0.680  0.657 

dcast.data.table es aproximadamente 1,6 veces más rápido que la agregación normal usando data.table y 8.8x más rápido que reshape2:::dcast.

Cuestiones relacionadas