¿Es posible esta remodelación de los datos?
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.
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