2017-04-08 3 views
2

Ich möchte zwei separate Gruppen von Spalten in zwei Schlüssel-Wert-Paare sammeln. Hier einige Beispieldaten:Mit Gather(), um zwei (oder mehr) Gruppen von Spalten in zwei (oder mehr) Schlüssel-Wert-Paare zu sammeln

library(dplyr) 
library(tidyr) 
ID = c(1:5) 
measure1 = c(1:5) 
measure2 = c(6:10) 
letter1 = c("a", "b", "c", "d", "e") 
letter2 = c("f", "g", "h", "i", "j") 

df = data.frame(ID, measure1, measure2, letter1, letter2) 
df = tbl_df(df) 
df$letter1 <- as.character(df$letter1) 
df$letter2 <- as.character(df$letter2) 

Ich möchte die Werte der zwei Messsäulen (measure1 und measure2) mit einem Schlüssel-Spalte in einer Spalte sein neben ihm (der Schlüssel-Wert-Paar). Ich möchte auch das gleiche für letter1 und letter2. Ich dachte, dass ich wählen verwenden könnte() zwei verschiedene Datensätze zu erstellen, verwenden Sie sammeln separat auf beiden Datensätze und dann kommen (dies funktioniert):

df_measure = df %>% 
    select(ID, measure1, measure2) %>% 
    gather(measure_time, measure, -ID) %>% 
    mutate(id.extra = c(1:10)) 
df_letter = df %>% 
    select(ID, letter1, letter2) %>% 
    gather(letter_time, letter, -ID) %>% 
    mutate(id.extra = c(1:10)) 
df_long = df_measure %>% 
    left_join(df_letter, by = "id.extra") 

Also das funktioniert perfekt (in diesem Fall), aber ich denke, das könnte eleganter gemacht werden (ohne Zeug wie das Teilen oder Erstellen von "id.extra"). Also bitte etwas Licht darauf!

Antwort

3

Sie können etwas wie folgt verwenden. Ich bin mir nicht sicher, ob es sich bei Ihrer aktuellen Vorgehensweise um die von Ihnen gewünschte Ausgabe handelt oder nicht, da sie viele redundante Informationen enthält.

df %>% 
    gather(val, var, -ID) %>% 
    extract(val, c("value", "time"), regex = "([a-z]+)([0-9]+)") %>% 
    spread(value, var) 
# # A tibble: 10 × 4 
#  ID time letter measure 
# * <int> <chr> <chr> <chr> 
# 1  1  1  a  1 
# 2  1  2  f  6 
# 3  2  1  b  2 
# 4  2  2  g  7 
# 5  3  1  c  3 
# 6  3  2  h  8 
# 7  4  1  d  4 
# 8  4  2  i  9 
# 9  5  1  e  5 
# 10  5  2  j  10 

So viel mehr ist leicht getan mit melt + patterns von "data.table":

library(data.table) 
melt(as.data.table(df), measure.vars = patterns("measure", "letter")) 

Oder Sie können die alte Schule sein und verwenden nur reshape von der Basis R. Beachten Sie jedoch, dass Base reshape "tibbles" nicht mag, also müssen Sie es mit as.data.frame konvertieren).

reshape(as.data.frame(df), direction = "long", idvar = "ID", 
     varying = 2:ncol(df), sep = "") 
+0

die gather mehr nehmen kann() Funktion kann das nicht tun? –

+1

@BenjaminTelkamp, ​​Kann was nicht tun? Ich habe bei meinem ersten Ansatz die Funktion "Sammeln" verwendet. Aber, Sie müssen * alle * Spalten sammeln und sie dann ausbreiten. – A5C1D2H2I1M1N2O1R2T1

1

Wir melt von data.table verwenden, die measurepatterns

library(data.table) 
melt(setDT(df), measure = patterns("^measure", "^letter"), 
      value.name = c("measure", "letter")) 
#  ID variable measure letter 
# 1: 1  1  1  a 
# 2: 2  1  2  b 
# 3: 3  1  3  c 
# 4: 4  1  4  d 
# 5: 5  1  5  e 
# 6: 1  2  6  f 
# 7: 2  2  7  g 
# 8: 3  2  8  h 
# 9: 4  2  9  i 
#10: 5  2  10  j 
+0

Das sieht gut aus, aber was mache ich, wenn ich explizit Spalten- oder Variablennamen in meinem Code verwenden möchte? und ich möchte auch mit ZWEI Schlüssel-Wert-Paaren enden? –

+1

@ BenjaminTelkamp, ​​duplizieren Sie einfach die Spalte "Variable" .... Warum würden Sie aber doppelte Daten wollen? – A5C1D2H2I1M1N2O1R2T1

+0

In diesem Fall habe ich zwei Beobachtungen für Maß und Buchstaben, aber was ist, wenn ich drei Beobachtungen für eine Gruppe habe? –

Verwandte Themen