É esta nova forma de dados possível?
Pergunta
Eu tenho uma estrutura de dados que tem o seguinte aspecto:
groupA1 groupA2 groupB1 groupB2 date text
0 1 1 1 2013-01-01 the dog
Para cada groupB
variável, quero listar uma linha para cada coluna que tem um valor de 1.Eu preciso listar todas as combinações de groupA
e groupB
onde 1s estão presentes em uma linha, mas, em seguida, adicionar a data e texto para cada uma dessas combinações de colunas na linha.
Dados transformados apareceria como:
var_groupB var_groupA date text
groupB1 groupA2 2013-01-01 the dog
groupB2 groupA2 2013-01-01 the dog
Eu tentei combinações de melt
e ddply
mas estou sempre deixou sem uma das variáveis que eu preciso.
Uma coisa que eu tentei foi melt(x, id.vars=c("text", "date"))
mas então eu perder todas as informações sobre as relações entre groupA
e groupB
.
Eu poderia fazer isso usando um bagunçado loop, mas não tinha a certeza se um reshape
utilitário existe que eu desconheço e poderia fazer o trabalho.
Solução
Você poderia melt
duas vezes, uma 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")
Que dê a você uma linha para cada combinação de A e 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
Em seguida, você pode subconjunto esta e remover as colunas de valor:
y <- y[y$val_groupA == 1 & y$val_groupB==1, ]
y <- y[, c("var_groupA", "var_groupB", "date", "text")]
O que dá a você o que você deseja:
var_groupA var_groupB date text
2 groupA2 groupB1 2013-01-01 the dog
4 groupA2 groupB2 2013-01-01 the dog
É claro que, se o conjunto de dados é mais complexa do que no seu exemplo, você pode fazer a esta solução mais elegante, fazendo a fusão e a subdivisão de uma forma mais automatizada moda, por exemplo, detectar o grupo de colunas e o preenchimento measure.vars
, variable.name
, e value.name
automaticamente, talvez, para qualquer número de grupos.
Outras dicas
As 2 primeiras declarações substituir cada 0 no primeiro 4 colunas com "" e cada 1 com o nome da coluna dando dd2
.As próximas duas declarações de gerar todas as combinações de groupA
e groupB
para cada linha usando expand.grid
com o resultado sendo dd3
.Finalmente subset
que essas linhas sem ""
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 != "")
Isso dá:
groupA groupB x.date x.text
1.2 groupA2 groupB1 2013-01-01 the dog
1.4 groupA2 groupB2 2013-01-01 the dog