Ich habe Daten aus einer Online-Umfrage, bei der die Befragten 1-3 Mal eine Reihe von Fragen durchlaufen. Die Umfrage - Software (Qualtrics) diese Daten in mehreren Spalten-das notiert , ist, F3.2 in der Umfrage werden Spalten haben Q3.2.1.
, Q3.2.2.
und 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
...
Ich möchte alle QN.N * -Spalten zu ordentlichen einzelnen QN.N-Spalten kombinieren und am Ende so etwas erhalten:
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
...
Die tidyr
Bibliothek verfügt über die gather()
Funktion, die sich hervorragend zum Kombinieren eines Satzes von Spalten eignet:
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
Der resultierende Datenrahmen hat erwartungsgemäß 30 Zeilen (10 Personen, jeweils 3 Schleifen). Das Sammeln eines zweiten Satzes von Spalten funktioniert jedoch nicht richtig - es werden die beiden kombinierten Spalten erfolgreich erstellt Q3.2
und Q3.3
es werden 90 statt 30 Zeilen angezeigt (alle Kombinationen von 10 Personen, 3 Schleifen von Q3.2 und 3 Schleifen von Q3 .3; die Kombinationen werden für jede Gruppe von Spalten in den tatsächlichen Daten erheblich zunehmen):
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
Gibt es eine Möglichkeit, mehrere Aufrufe zu verwenden, um gather()
dies zu mögen, indem kleine Teilmengen von Spalten wie diese kombiniert werden, während die richtige Anzahl von Zeilen beibehalten wird?
df %>% gather(loop_number, Q3.2, starts_with("Q3."))
seperate()
einfügen würde, um die Q3.3-Werte (und darüber hinaus) in ihre eigenen Spalten aufzuteilen. Aber das scheint immer noch eine wirklich umständliche Hacky-Lösung zu sein ...spread
ich an einer Lösung arbeite jetzt: 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()
. Obwohl mehrere Anrufe ohnehin unvermeidlich erscheinen, egal ob es sich um ein paargenerate()
funktionierende oder verschachteltespread()
s handelt ...Antworten:
Dieser Ansatz erscheint mir ziemlich natürlich:
Sammeln Sie zuerst alle Fragenspalten,
extract()
trennen Sie sie inquestion
undloop_number
dannspread()
wieder in die Spalten.quelle
Dies könnte mit erfolgen
reshape
. Es ist aber möglich mitdplyr
.Oder mit
dplyr
Aktualisieren
Mit
tidyr_0.8.3.9000
können wirpivot_longer
mehrere Spalten umformen. (Verwenden der geänderten Spaltennamen vongsub
oben)HINWEIS: Die Werte sind unterschiedlich, da beim Erstellen des Eingabedatensatzes kein festgelegter Startwert vorhanden war
quelle
mutate(loop_number = as.numeric(L2))
vor dem AblegenL2
, und es ist perfekt.reshape
Methode wegen ihres kompakten Codes, obwohldplyr
sie für große Datenmengen möglicherweise schneller ist.reshape()
Funktion zu verstehen , meine Lösung für eine meiner Meinung nach ziemlich saubere Tidyr-Implementierung zu sehen.Mit dem letzten Update auf
melt.data.table
können wir jetzt mehrere Spalten schmelzen. Damit können wir tun:Die Entwicklungsversion erhalten Sie hier .
quelle
Es hat überhaupt nichts mit "tidyr" und "dplyr" zu tun, aber hier ist eine weitere Option, die Sie berücksichtigen sollten:
merged.stack
aus meinem "splitstackshape" -Paket , V1.4.0 und höher.quelle
Wenn Sie wie ich sind und nicht herausfinden können, wie "regulärer Ausdruck mit Erfassungsgruppen" verwendet werden soll
extract
, repliziert der folgende Code dieextract(...)
Zeile in Hadleys Antwort:Das Problem hierbei ist, dass die anfängliche Erfassung eine Schlüsselspalte bildet, die tatsächlich eine Kombination aus zwei Schlüsseln ist. Ich habe mich für die Verwendung
mutate
in meiner ursprünglichen Lösung in den Kommentaren entschieden, um diese Spalte in zwei Spalten mit entsprechenden Informationen, eineloop_number
Spalte und einequestion_number
Spalte , aufzuteilen .spread
kann dann verwendet werden, um die langen Formulardaten, die Schlüsselwertpaare sind,(question_number, value)
in breite Formulardaten umzuwandeln .quelle