Pregunta

Tengo una estructura de datos que se parece a la siguiente:

 groupA1    groupA2    groupB1    groupB2    date        text
     0         1          1          1      2013-01-01   the dog

Para cada groupB variable, quiero enumerar una fila para cada columna que tenga un valor de 1.Necesito enumerar todas las combinaciones de groupA y groupB donde los 1 están presentes en una fila, pero luego también agregan la fecha y el texto a cada una de esas combinaciones como columnas en esa fila.

Los datos transformados aparecerían como:

var_groupB  var_groupA  date         text
 groupB1    groupA2     2013-01-01    the dog
 groupB2    groupA2     2013-01-01    the dog

He probado combinaciones de melt y ddply pero siempre me quedo sin una de las variables que necesito.

Una cosa que intenté fue melt(x, id.vars=c("text", "date")) pero luego pierdo toda la información sobre las relaciones entre groupA y groupB.

Podría lograr esto usando un bucle desordenado, pero no estaba seguro si un reshape Existe una utilidad que desconozco y que podría hacer el trabajo.

¿Fue útil?

Solución

Tú podrías melt dos veces, una para cada grupo:

y <- melt(x, measure.vars=c("groupA1", "groupA2"),
          variable.name="var_groupA", value.name="val_groupA")
y <- melt(y, measure.vars=c("groupB1", "groupB2"),
          variable.name="var_groupB", value.name="val_groupB")

Eso te daría una fila para cada combinación de A y B:

        date    text var_groupA val_groupA var_groupB val_groupB
1 2013-01-01 the dog    groupA1          0    groupB1          1
2 2013-01-01 the dog    groupA2          1    groupB1          1
3 2013-01-01 the dog    groupA1          0    groupB2          1
4 2013-01-01 the dog    groupA2          1    groupB2          1

Luego podrías crear un subconjunto de esto y eliminar las columnas de valores:

y <- y[y$val_groupA == 1 & y$val_groupB==1, ]
y <- y[, c("var_groupA", "var_groupB", "date", "text")]

Que te da lo que quieres:

  var_groupA var_groupB       date    text
2    groupA2    groupB1 2013-01-01 the dog
4    groupA2    groupB2 2013-01-01 the dog

Por supuesto, si su conjunto de datos es más complejo que en su ejemplo, puede hacer que esta solución sea más elegante fusionando y subconjuntos de una manera más automatizada, por ejemplo, detectando las columnas del grupo y completando measure.vars, variable.name, y value.name automáticamente, quizás para cualquier número de grupos.

Otros consejos

Las primeras 2 declaraciones reemplazan cada 0 en las primeras 4 columnas con "" y cada 1 con el nombre de la columna que proporciona dd2.Las siguientes dos declaraciones generan todas las combinaciones de groupA y groupB para cada fila usando expand.grid siendo el resultado dd3.Finalmente subset eso a esas filas sin "" entradas:

newvals <- function(nm) ifelse(dd[[nm]] == 0, "", nm)
dd2 <- replace(dd, 1:4, lapply(names(dd)[1:4], newvals))

combo <- function(x) data.frame(expand.grid(groupA=c(x[1:2]), groupB=c(x[3:4])), 
             x$date, x$text)
dd3 <- do.call("rbind", by(dd2, 1:nrow(dd2), combo)) 

subset(dd3, groupA != "" & groupB != "")

Esto da:

     groupA  groupB     x.date  x.text
1.2 groupA2 groupB1 2013-01-01 the dog
1.4 groupA2 groupB2 2013-01-01 the dog
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top