Cette refonte des données est-elle possible ?
Question
J'ai une structure de données qui ressemble à la suivante :
groupA1 groupA2 groupB1 groupB2 date text
0 1 1 1 2013-01-01 the dog
Pour chaque groupB
variable, je souhaite lister une ligne pour chaque colonne qui a une valeur de 1.Je dois lister toutes les combinaisons de groupA
et groupB
où les 1 sont présents dans une ligne, mais ajoutez également la date et le texte à chacune de ces combinaisons sous forme de colonnes dans cette ligne.
Les données transformées apparaîtront comme :
var_groupB var_groupA date text
groupB1 groupA2 2013-01-01 the dog
groupB2 groupA2 2013-01-01 the dog
J'ai essayé des combinaisons de melt
et ddply
mais je me retrouve toujours sans l'une des variables dont j'ai besoin.
Une chose que j'ai essayée était melt(x, id.vars=c("text", "date"))
mais ensuite je perds toutes les informations sur les relations entre groupA
et groupB
.
Je pouvais accomplir cela en utilisant une boucle désordonnée, mais je ne savais pas si un reshape
il existe un utilitaire que je ne connais pas et qui pourrait faire le travail.
La solution
Vous pourriez melt
deux fois, une fois pour chaque groupe :
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")
Cela vous donnerait une ligne pour chaque combinaison de A et 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
Ensuite, vous pouvez sous-ensembler ceci et supprimer les colonnes de valeurs :
y <- y[y$val_groupA == 1 & y$val_groupB==1, ]
y <- y[, c("var_groupA", "var_groupB", "date", "text")]
Ce qui te donne ce que tu veux :
var_groupA var_groupB date text
2 groupA2 groupB1 2013-01-01 the dog
4 groupA2 groupB2 2013-01-01 the dog
Bien sûr, si votre ensemble de données est plus complexe que dans votre exemple, vous pouvez rendre cette solution plus élégante en effectuant la fusion et le sous-ensemble de manière plus automatisée (par exemple, en détectant les colonnes du groupe et en les remplissant). measure.vars
, variable.name
, et value.name
automatiquement, peut-être pour n'importe quel nombre de groupes.
Autres conseils
Les 2 premières instructions remplacent chaque 0 dans les 4 premières colonnes par "" et chaque 1 par le nom de la colonne donnant dd2
.Les deux instructions suivantes génèrent toutes les combinaisons de groupA
et groupB
pour chaque ligne en utilisant expand.grid
avec le résultat étant dd3
.Enfin subset
qu'à ces rangées sans ""
entrées :
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 != "")
Cela donne:
groupA groupB x.date x.text
1.2 groupA2 groupB1 2013-01-01 the dog
1.4 groupA2 groupB2 2013-01-01 the dog