2012-02-18 8 views
5

Las funciones de fusión/fundido en el paquete de remodelación son geniales, pero no estoy seguro de si hay una forma sencilla de aplicarlas cuando las variables medidas son de diferentes tipos. Por ejemplo, aquí es un fragmento de datos donde cada MD proporciona el sexo y el peso de los tres pacientes:Alternativas a stats :: reshape

ID PT1 WT1 PT2 WT2 PT3 WT3 
1 "M" 170 "M" 175 "F" 145 
... 

donde el objetivo es remodelar de manera que cada fila es un paciente:

ID PTNUM GENDER WEIGHT 
1 1  "M" 170 
1 2  "M" 175 
1 3  "F" 145 
... 

Utilizando el La función de remodelación en el paquete de estadísticas es una opción de la que tengo conocimiento, pero la estoy publicando aquí con la esperanza de que los usuarios de R con más experiencia que yo publiquen otros métodos, con suerte mejores. ¡Muchas gracias!

-

@Vincent Zoonekynd:

me gusta tu ejemplo mucho, por lo que la generalizó a múltiples variables.

# Sample data 
n <- 5 
d <- data.frame(
    id = 1:n, 
    p1 = sample(c("M","F"),n,replace=TRUE), 
    q1 = sample(c("Alpha","Beta"),n,replace=TRUE), 
    w1 = round(runif(n,100,200)), 
    y1 = round(runif(n,100,200)), 
    p2 = sample(c("M","F"),n,replace=TRUE), 
    q2 = sample(c("Alpha","Beta"),n,replace=TRUE), 
    w2 = round(runif(n,100,200)), 
    y2 = round(runif(n,100,200)), 
    p3 = sample(c("M","F"),n,replace=TRUE), 
    q3 = sample(c("Alpha","Beta"),n,replace=TRUE), 
    w3 = round(runif(n,100,200)), 
    y3 = round(runif(n,100,200)) 
) 
# Reshape the data.frame, one variable at a time 
library(reshape) 
d1 <- melt(d, id.vars="id", measure.vars=c("p1","p2","p3","q1","q2","q3")) 
d2 <- melt(d, id.vars="id", measure.vars=c("w1","w2","w3","y1","y2","y3")) 
d1 = cbind(d1,colsplit(d1$variable,names=c("var","ptnum"))) 
d2 = cbind(d2,colsplit(d2$variable,names=c("var","ptnum"))) 
d1$variable = NULL 
d2$variable = NULL 
d1c = cast(d1,...~var) 
d2c = cast(d2,...~var) 
# Join the two data.frames 
d3 = merge(d1c, d2c, by=c("id","ptnum"), all=TRUE) 

-

Consideraciones finales: Mi motivación para esta pregunta fue conocer alternativas al paquete de cambio de forma distinta las estadísticas :: función de formar de nuevo. Por el momento, he llegado a las siguientes conclusiones:

  • Adhiérase a las estadísticas :: remodele cuando pueda. Siempre que recuerde usar una lista en lugar de un vector simple para el argumento "variable", se mantendrá alejado de problemas. Para conjuntos de datos más pequeños: unos pocos miles de casos de pacientes con menos de 200 variables en total es lo que estaba tratando esta vez, la velocidad más baja de esta función vale la simplicidad del código.

  • Para usar el enfoque fundido/fundido en el paquete de remodelación (o reshape2) de Hadley Wickham, debe dividir las variables en dos conjuntos, uno compuesto por variables numéricas y otro de variables de caracteres. Cuando tu conjunto de datos es lo suficientemente grande como para que encuentres stats :: remodelar insoportable, imagino que el paso adicional de dividir tus variables en dos conjuntos no parecerá tan malo.

+3

¿Mejor en qué sentido? remodelar está diseñado para tareas como esta, ¿por qué no usarlo? – Fojtasek

+0

Reshape funciona bien siempre que se recuerde usar la forma canónica del argumento variable (una lista): [link] (http://www.mail-archive.com/[email protected]/msg160715 .html) Con R, estoy constantemente sorprendido por la existencia de alternativas que no conocía, así que pensé que alguien publicaría otros enfoques. Un ejemplo de la definición de "mejor" sería la velocidad: en mi experiencia subjetivamente reconocida, el lanzamiento/fusión parece más rápido que la configuración incorporada. –

+0

No me di cuenta de esto, gracias. Ahora he cambiado la biblioteca de reshape2 a remodelar.Todavía puede usar reshape2 si lo desea: tendrá que agregar el argumento de patrón con un valor de "" a la llamada colsplit(). –

Respuesta

3

Puede procesar cada variable por separado, y unirse a los dos data.frames resultantes.

# Sample data 
n <- 5 
d <- data.frame(
    id = 1:n, 
    pt1 = sample(c("M","F"),n,replace=TRUE), 
    wt1 = round(runif(n,100,200)), 
    pt2 = sample(c("M","F"),n,replace=TRUE), 
    wt2 = round(runif(n,100,200)), 
    pt3 = sample(c("M","F"),n,replace=TRUE), 
    wt3 = round(runif(n,100,200)) 
) 
# Reshape the data.frame, one variable at a time 
library(reshape2) 
d1 <- melt(d, 
    id.vars="id", measure.vars=c("pt1","pt2","pt3"), 
    variable.name="patient", value.name="gender" 
) 
d2 <- melt(d, 
    id.vars="id", measure.vars=c("wt1","wt2","wt3"), 
    variable.name="patient", value.name="weight" 
) 
d1$patient <- as.numeric(gsub("pt", "", d1$patient)) 
d2$patient <- as.numeric(gsub("wt", "", d1$patient)) 
# Join the two data.frames 
merge(d1, d2, by=c("id","patient"), all=TRUE) 
+0

Gracias, esto tiene sentido. El código es más largo que el requerido para stats :: remodele, pero probablemente valga la eficiencia que se gana cuando hay muchas variables, que a menudo es el caso para mí. –

2

Creo que la función reshape en el paquete de estadísticas es la más simple. Aquí hay un ejemplo simple, ¿hace esto lo que quieres?

> tmp 
    id val val2 cat 
1 1 1 14 a 
2 1 2 13 b 
3 2 3 12 b 
4 2 4 11 a 
> tmp2 <- tmp 
> tmp2$t <- ave(tmp2$val, tmp2$id, FUN=seq_along) 
> tmp2 
    id val val2 cat t 
1 1 1 14 a 1 
2 1 2 13 b 2 
3 2 3 12 b 1 
4 2 4 11 a 2 
> reshape(tmp2, idvar='id', timevar='t', direction='wide') 
    id val.1 val2.1 cat.1 val.2 val2.2 cat.2 
1 1  1  14  a  2  13  b 
3 2  3  12  b  4  11  a 

pacientes Esperemos que su sexo no está cambiando cada cita, pero que podría haber otras variables categóricas que cambia entre las visitas

+0

Lo que tenía en mente eran múltiples pacientes por médico de cabecera, no el mismo paciente medido en múltiples ocasiones. Pero estoy de acuerdo en que el código con stats :: reshape es definitivamente más compacto, siempre y cuando uno esté al tanto de los posibles errores: [ver enlace] (http://www.mail-archive.com/[email protected] .org/msg160715.html) –

+0

Por lo tanto, en mi ejemplo, use id como identificación del médico y los valores múltiples representan a los pacientes. –