J'ai des données provenant d'un sondage en ligne où les répondants parcourent une boucle de questions 1 à 3 fois. Le logiciel d'enquête (Qualtrics) enregistre ces données dans plusieurs colonnes qui est, Q3.2 dans l'enquête aura des colonnes Q3.2.1.
, Q3.2.2.
et Q3.2.3.
:
df <- data.frame(
id = 1:10,
time = as.Date('2009-01-01') + 0:9,
Q3.2.1. = rnorm(10, 0, 1),
Q3.2.2. = rnorm(10, 0, 1),
Q3.2.3. = rnorm(10, 0, 1),
Q3.3.1. = rnorm(10, 0, 1),
Q3.3.2. = rnorm(10, 0, 1),
Q3.3.3. = rnorm(10, 0, 1)
)
# Sample data
id time Q3.2.1. Q3.2.2. Q3.2.3. Q3.3.1. Q3.3.2. Q3.3.3.
1 1 2009-01-01 -0.2059165 -0.29177677 -0.7107192 1.52718069 -0.4484351 -1.21550600
2 2 2009-01-02 -0.1981136 -1.19813815 1.1750200 -0.40380049 -1.8376094 1.03588482
3 3 2009-01-03 0.3514795 -0.27425539 1.1171712 -1.02641801 -2.0646661 -0.35353058
...
Je veux combiner toutes les colonnes QN.N * dans des colonnes QN.N individuelles bien rangées, pour finalement aboutir à quelque chose comme ceci:
id time loop_number Q3.2 Q3.3
1 1 2009-01-01 1 -0.20591649 1.52718069
2 2 2009-01-02 1 -0.19811357 -0.40380049
3 3 2009-01-03 1 0.35147949 -1.02641801
...
11 1 2009-01-01 2 -0.29177677 -0.4484351
12 2 2009-01-02 2 -1.19813815 -1.8376094
13 3 2009-01-03 2 -0.27425539 -2.0646661
...
21 1 2009-01-01 3 -0.71071921 -1.21550600
22 2 2009-01-02 3 1.17501999 1.03588482
23 3 2009-01-03 3 1.11717121 -0.35353058
...
La tidyr
bibliothèque a la gather()
fonction, qui fonctionne très bien pour combiner un ensemble de colonnes:
library(dplyr)
library(tidyr)
library(stringr)
df %>% gather(loop_number, Q3.2, starts_with("Q3.2")) %>%
mutate(loop_number = str_sub(loop_number,-2,-2)) %>%
select(id, time, loop_number, Q3.2)
id time loop_number Q3.2
1 1 2009-01-01 1 -0.20591649
2 2 2009-01-02 1 -0.19811357
3 3 2009-01-03 1 0.35147949
...
29 9 2009-01-09 3 -0.58581232
30 10 2009-01-10 3 -2.33393981
La base de données résultante a 30 lignes, comme prévu (10 individus, 3 boucles chacun). Cependant, la collecte d'un deuxième ensemble de colonnes ne fonctionne pas correctement - cela réussit à créer les deux colonnes combinées Q3.2
et Q3.3
, mais finit avec 90 lignes au lieu de 30 (toutes les combinaisons de 10 individus, 3 boucles de Q3.2 et 3 boucles de Q3 .3; les combinaisons augmenteront considérablement pour chaque groupe de colonnes dans les données réelles):
df %>% gather(loop_number, Q3.2, starts_with("Q3.2")) %>%
gather(loop_number, Q3.3, starts_with("Q3.3")) %>%
mutate(loop_number = str_sub(loop_number,-2,-2))
id time loop_number Q3.2 Q3.3
1 1 2009-01-01 1 -0.20591649 1.52718069
2 2 2009-01-02 1 -0.19811357 -0.40380049
3 3 2009-01-03 1 0.35147949 -1.02641801
...
89 9 2009-01-09 3 -0.58581232 -0.13187024
90 10 2009-01-10 3 -2.33393981 -0.48502131
Existe-t-il un moyen d'utiliser plusieurs appels pour gather()
aimer ceci, en combinant de petits sous-ensembles de colonnes comme celui-ci tout en conservant le nombre correct de lignes?
df %>% gather(loop_number, Q3.2, starts_with("Q3."))
seperate()
j'incluais ensuite une sorte d'appel pour diviser les valeurs Q3.3 (et au-delà) dans leurs propres colonnes. Mais cela semble toujours être une solution de piratage vraiment détournée ...spread
je travaille sur une solution maintenant: pdf %>% gather(question_number, Q3.2, starts_with("Q3.")) %>% mutate(loop_number = str_sub(question_number,-2,-2), question_number = str_sub(question_number,1,4)) %>% select(id, time, loop_number, question_number, Q3.2) %>% spread(key = question_number, value = Q3.2)
spread()
. Bien que plusieurs appels semblent inévitables de toute façon, que ce soit un groupe degenerate()
s qui fonctionnent ou imbriquésspread()
…Réponses:
Cette approche me semble assez naturelle:
Rassemblez d'abord toutes les colonnes de questions, utilisez
extract()
pour les séparer enquestion
etloop_number
, puisspread()
questionnez de nouveau dans les colonnes.la source
Cela pourrait être fait en utilisant
reshape
. C'est possible avecdplyr
cependant.Ou en utilisant
dplyr
Mettre à jour
Avec
tidyr_0.8.3.9000
, nous pouvons utiliserpivot_longer
pour remodeler plusieurs colonnes. (En utilisant les noms de colonne modifiésgsub
ci-dessus)REMARQUE: les valeurs sont différentes car il n'y avait pas de valeur de départ définie lors de la création du jeu de données d'entrée
la source
mutate(loop_number = as.numeric(L2))
avant de tomberL2
, et c'est parfait.reshape
méthode pour son code compact, bien qu'elledplyr
puisse être plus rapide pour les grands ensembles de données.reshape()
fonction, voir ma solution pour ce qui me semble être une implémentation tidyr assez propre.Avec la récente mise à jour de
melt.data.table
, nous pouvons désormais fondre plusieurs colonnes. Avec cela, nous pouvons faire:Vous pouvez obtenir la version de développement à partir d' ici .
la source
Ce n'est pas du tout lié à "tidyr" et "dplyr", mais voici une autre option à considérer: à
merged.stack
partir de mon package "splitstackshape" , V1.4.0 et supérieur.la source
Si vous êtes comme moi et que vous ne parvenez pas à utiliser une expression régulière avec des groupes de capture
extract
, le code suivant réplique laextract(...)
ligne dans la réponse de Hadleys:Le problème ici est que le regroupement initial forme une colonne clé qui est en fait une combinaison de deux clés. J'ai choisi d'utiliser
mutate
dans ma solution d'origine dans les commentaires pour diviser cette colonne en deux colonnes avec des informations équivalentes, uneloop_number
colonne et unequestion_number
colonne.spread
peuvent ensuite être utilisées pour transformer les données de forme longue, qui sont des paires de valeurs clés,(question_number, value)
en données de forme large.la source