2015-12-17 4 views
11

Ich möchte left_join mehrere Datenrahmen:Wie man mehrere Datenrahmen mit dplyr verbinden?

dfs <- list(
    df1 = data.frame(a = 1:3, b = c("a", "b", "c")), 
    df2 = data.frame(c = 4:6, b = c("a", "c", "d")), 
    df3 = data.frame(d = 7:9, b = c("b", "c", "e")) 
) 
Reduce(left_join, dfs) 
# a b c d 
# 1 1 a 4 NA 
# 2 2 b NA 7 
# 3 3 c 5 8 

Dies funktioniert, weil sie alle die gleiche b Spalte, aber Reduce nicht lassen Sie mich zusätzliche Argumente angeben, die ich left_join passieren kann. Gibt es eine Arbeit für so etwas?

dfs <- list(
    df1 = data.frame(a = 1:3, b = c("a", "b", "c")), 
    df2 = data.frame(c = 4:6, d = c("a", "c", "d")), 
    df3 = data.frame(d = 7:9, b = c("b", "c", "e")) 
) 

aktualisieren

Diese Art der Arbeiten: Reduce(function(...) left_join(..., by = c("b" = "d")), dfs) aber wenn by mehr als ein Element ist gibt es diesen Fehler: Error: cannot join on columns 'b' x 'd': index out of bounds

+3

Kann nicht Sie 'Reduce (function (...) left_join (..., andere args hier), dfs)' ? –

+0

Daran hatte ich nicht gedacht. Ja, ich kann! Fühlen Sie sich frei, es als Ihre Antwort zu schreiben – nachocab

+0

Hmm, eigentlich, das bricht, wenn 'by' mehr als ein Element hat. Siehe Update – nachocab

Antwort

3

Es ist zu spät wurde ich weiß .... heute habe ich auf die offenen Fragen Abschnitt eingeführt. Entschuldige die Störung.

Mit left_join()

dfs <- list(
       df1 = data.frame(b = c("a", "b", "c"), a = 1:3), 
       df2 = data.frame(d = c("a", "c", "d"), c = 4:6), 
       df3 = data.frame(b = c("b", "c", "e"), d = 7:9) 
     ) 

func <- function(...){ 
    df1 = list(...)[[1]] 
    df2 = list(...)[[2]] 
    col1 = colnames(df1)[1] 
    col2 = colnames(df2)[1] 
    xxx = left_join(..., by = setNames(col2,col1)) 
    return(xxx) 
} 
Reduce(func, dfs) 
# b a c d 
#1 a 1 4 NA 
#2 b 2 NA 7 
#3 c 3 5 8 

Mit merge():

func <- function(...){ 
    df1 = list(...)[[1]] 
    df2 = list(...)[[2]] 
    col1 = colnames(df1)[1] 
    col2 = colnames(df2)[1] 
    xxx=merge(..., by.x = col1, by.y = col2, , all.x = T) 
    return(xxx) 
} 

Reduce(func, dfs) 
# b a c d 
#1 a 1 4 NA 
#2 b 2 NA 7 
#3 c 3 5 8 
+0

nur zu beachten: Ich musste die "Schlüssel" Variablen als erste Spalte, weil nach dem Zusammenführen sie automatisch die ersten Spalten im Datenrahmen zu halten –

4

Wäre das für Sie arbeiten?

jnd.tbl <- df1 %>% 
    left_join(df2, by='b') %>% 
    left_join(df3, by='d') 
+5

Verallgemeinert nicht sehr gut (was scheint der Punkt der Frage zu sein). – Gregor

+1

Dies scheint die beste Lösung zu sein. Es verallgemeinert sich recht gut: Wenn Sie einer anderen Tabelle beitreten möchten, fügen Sie einfach eine weitere Zeile zur Pipeline hinzu. Der Code würde schließlich nicht zu sehr von einer SQL-Abfrage mit mehreren Joins abweichen. –

+0

@HongOoi aber die Variable von = variiert, richtig? Bitte überprüfen Sie meine Antwort auf diese –