2016-07-21 28 views
1

Entschuldigung, wenn dies eine einfache Frage ist, aber ich habe nicht gefunden, eine einfache Lösung nach der Suche. Ich bin ziemlich neu in R und habe Probleme beim Konvertieren von Wide Format in Long Format mit den Funktionen zum Schmelzen (reshape2) oder zum Sammeln (tidyr). Der Datensatz, mit dem ich arbeite, enthält 22 verschiedene Zeitvariablen mit jeweils 3 Zeiträumen. Das Problem tritt auf, wenn ich versuche, all diese Dateien gleichzeitig vom Wide- zum Long-Format zu konvertieren. Ich hatte Erfolg darin, sie einzeln zu konvertieren, aber es ist sehr ineffizient und lang, also habe ich mich gefragt, ob jemand eine einfachere Lösung vorschlagen könnte. Im Folgenden wird ein Beispieldatensatz erstellt ich, dass in ähnlicher Weise wie der Datensatz mit arbeite ich formatiert ist:R: Konvertieren von Wide-Format in Long-Format mit mehreren 3 Zeitraum Variablen

Subject <- c(1, 2, 3) 
BlueTime1 <- c(2, 5, 6) 
BlueTime2 <- c(4, 6, 7) 
BlueTime3 <- c(1, 2, 3) 
RedTime1 <- c(2, 5, 6) 
RedTime2 <- c(4, 6, 7) 
RedTime3 <- c(1, 2, 3) 
GreenTime1 <- c(2, 5, 6) 
GreenTime2 <- c(4, 6, 7) 
GreenTime3 <- c(1, 2, 3) 

sample.df <- data.frame(Subject, BlueTime1, BlueTime2, BlueTime3, 
        RedTime1, RedTime2, RedTime3, 
        GreenTime1,GreenTime2, GreenTime3) 
Eine Lösung

die für mich gearbeitet hat, ist die sammeln Funktion von tidyr zu verwenden, nach Thema die Datenanordnungs (so dass die Daten jeder Person gruppiert sind) und dann nur das Subjekt, den Zeitraum und die Bewertung auswählen. Dies wurde für jede Variable (in meinem Fall 22) getan.

install.packages("dplyr") 
install.packages("tidyr") 
library(dplyr) 
library(tidyr) 

BlueGather <- gather(sample.df, Time_Blue, Rating_Blue, c(BlueTime1, 
                  BlueTime2, 
                  BlueTime3)) 
BlueSorted <- arrange(BlueGather, Subject) 

BlueSubtracted <- select(BlueSorted, Subject, Time_Blue, Rating_Blue) 

Nach diesem Code kombiniere ich alles in einem Datenrahmen. Das scheint mir sehr langsam und ineffizient zu sein, und ich hoffte, dass mir jemand helfen könnte, eine einfachere Lösung zu finden. Vielen Dank!

Antwort

1

Wenn Ihr Ziel ist es, die drei Farben zu lange konvertieren kann dies mit der Basis R reshape Funktion erreicht werden:

reshape(sample.df, idvar="subject", varying=2:length(sample.df), sep="", direction="long") 
    Subject time BlueTime RedTime GreenTime subject 
1.1  1 1  2  2   2  1 
2.1  2 1  5  5   5  2 
3.1  3 1  6  6   6  3 
1.2  1 2  4  4   4  1 
2.2  2 2  6  6   6  2 
3.2  3 2  7  7   7  3 
1.3  1 3  1  1   1  1 
2.3  2 3  2  2   2  2 
3.3  3 3  3  3   3  3 

Die Zeitvariable die 1,2,3 in den Namen der breiten Variablen erfasst . Das variierende Argument teilt reshape mit, welche Variablen in long konvertiert werden sollten. Das Argument sep teilt reshape mit, nach Zahlen am Ende der variierenden Variablen zu suchen, die nicht durch irgendwelche Zeichen getrennt sind, während das Argument direction die Funktion anweist, eine lange Konvertierung zu versuchen.

Ich füge die ID-Variable immer hinzu, auch wenn sie für zukünftige Referenz nicht benötigt wird.


Wenn Ihr data.frame nicht tatsächlich hat die Zahlen für die Zeitvariable hat, eine ziemlich einfache Lösung ist es, die Variablennamen zu ändern, so dass sie es tun. Zum Beispiel würde das Folgende "_Pre" durch "1" am Ende solcher Variablen ersetzen.

names(df)[grep("_Pre$", names(df))] <- gsub("_Pre$", "1", 
              names(df)[grep("_Pre$", names(df))]) 
+0

Danke für die schnelle Antwort! Ich habe ein paar Probleme damit, dies auf meinen echten Datensatz anzuwenden. Ich erhalte den folgenden Fehler: 'code' Fehler in [<-. Data.frame (* tmp *,, v.name [i], Wert = c (1.28571428571429,: Spaltenname" "kann keinem Spaltencode entsprechen) 'Als Referenz haben die Variablen in meinem Dataset tatsächlich keine Zahlen in ihnen für die Zeit. Ich hätte dies in den Mock-Daten klarstellen müssen. Jede Variable endet mit _Pre, _Post und _Final. – Eugene

+0

Ich poste a Empfohlene Methode, um dies zu beheben – lmo

1

Die Idee hier ist, um gather() alle Zeitvariablen (alle Variablen aber Subject), separate() auf key verwenden sie in eine label zu spalten und eine time und dann spread() die label und value Ihre gewünschte Ausgabe zu erhalten.

library(dplyr) 
library(tidyr) 

sample.df %>% 
    gather(key, value, -Subject) %>% 
    separate(key, into = c("label", "time"), "(?<=[a-z])(?=[0-9])") %>% 
    spread(label, value) 

Welche gibt:

# Subject time BlueTime GreenTime RedTime 
#1  1 1  2   2  2 
#2  1 2  4   4  4 
#3  1 3  1   1  1 
#4  2 1  5   5  5 
#5  2 2  6   6  6 
#6  2 3  2   2  2 
#7  3 1  6   6  6 
#8  3 2  7   7  7 
#9  3 3  3   3  3 

Hinweis

Hier haben wir die regex in separate() von diesen answer durch @RichardScriven verwenden, um die Spalte auf der ersten Ziffer angetroffen zu spalten.


bearbeiten

ich Ihre Kommentare zu verstehen, dass Ihre Daten-Set Spaltennamen sind tatsächlich in Form ColorTime_Pre, ColorTime_Post, ColorTime_Final. Wenn das der Fall ist, müssen Sie nicht einen regulären Ausdruck in separate() als Standard festlegen ein sep = "[^[:alnum:]]+" Ihre _ übereinstimmen und spaltete den Schlüssel in label und time entsprechend:

sample.df %>% 
    gather(key, value, -Subject) %>% 
    separate(key, into = c("label", "time")) %>% 
    spread(label, value) 

geben:

# Subject time BlueTime GreenTime RedTime 
#1  1 Final  1   1  1 
#2  1 Post  4   4  4 
#3  1 Pre  2   2  2 
#4  2 Final  2   2  2 
#5  2 Post  6   6  6 
#6  2 Pre  5   5  5 
#7  3 Final  3   3  3 
#8  3 Post  7   7  7 
#9  3 Pre  6   6  6 
+0

Danke! Könnten Sie ein bisschen mehr Details darüber, was der 'Code' (? <= [az]) (? = [0-9])' Code' tut? Ich nehme an die 0-9 ist für die Themen ... aber ich bin sonst etwas verwirrt .. – Eugene

+0

@Eugene siehe update –

3

Wir können melt von data.table verwenden, die mehrere measure Spalten als regex nehmen pattern

library(data.table) 
melt(setDT(sample.df), measure = patterns("^Blue", "^Red", "^Green"), 
    value.name = c("BlueTime", "RedTime", "GreenTime"), variable.name = "time") 
# Subject time BlueTime RedTime GreenTime 
#1:  1 1  2  2   2 
#2:  2 1  5  5   5 
#3:  3 1  6  6   6 
#4:  1 2  4  4   4 
#5:  2 2  6  6   6 
#6:  3 2  7  7   7 
#7:  1 3  1  1   1 
#8:  2 3  2  2   2 
#9:  3 3  3  3   3 

Oder wie @ StevenBeaupré in den Kommentaren erwähnt, wenn es viele Muster sind, wäre eine Option, die names des Datensatzes zu verwenden, nachdem die Teil als patterns Argument Extrahieren

melt(setDT(sample.df), measure = patterns(as.list(unique(sub("\\d+", "", 
     names(sample.df)[-1])))),value.name = c("BlueTime", "RedTime", 
      "GreenTime"), variable.name = "time") 
+1

OP sagt er hat * 22 verschiedene Zeitvariablen, die sind jeweils 3 Zeiträume * Ich denke wir sollten eine Lösung ohne bieten explizit auf die Farben bezogen –

+0

@ StevenBeaupré Diese Lösung basiert auf dem von ihm bereitgestellten Beispiel, da es nur 22 Variablen hat , die 'Muster' können es immer noch nehmen. – akrun

+0

Ja, ich weiß, und es ist eine sehr legitime Lösung für das Beispiel, das dafür +1 bereitgestellt wird. Aber da er klar erwähnt, dass sein tatsächlicher Anwendungsfall viele Zeitvariablen hat, sollten wir dies berücksichtigen, indem wir dem OP eine Antwort geben, die für seine reale Anwendung gut geeignet sein wird. –