2015-12-17 28 views
11

Voglio left_join più frame di dati:Come unire più frame di dati usando dplyr?

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 

Questo funziona perché tutti hanno la stessa b colonna, ma Reduce non mi permette di specificare gli argomenti aggiuntivi che posso passare a left_join. C'è un lavoro in giro per qualcosa di simile?

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")) 
) 

Aggiornamento

Questo tipo di opere: Reduce(function(...) left_join(..., by = c("b" = "d")), dfs) ma quando by è più di un elemento che dà questo errore: Error: cannot join on columns 'b' x 'd': index out of bounds

+3

Non puoi fare 'Ridurre (function (...) left_join (..., altri args qui), DFS)' ? –

+0

Non ci avevo pensato. Sì posso! Sentiti libero di scriverlo come risposta – nachocab

+0

Hmm, in realtà, questo si interrompe se 'by' ha più di un elemento. Vedi aggiornamento – nachocab

risposta

3

È stato troppo tardi, lo so .... oggi mi sono presentato alla sezione domande senza risposta. Dispiace disturbarla.

Utilizzando 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 

Utilizzando 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

solo per notare: ho dovuto mantenere le variabili "chiave" come prima colonna, perché dopo l'unione diventano automaticamente le prime colonne nel dataframe –

4

Sarebbe questo lavoro per te?

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

Non generalizza molto bene (che sembra essere il punto della domanda). – Gregor

+1

Questa sembra essere la soluzione migliore. Si generalizza abbastanza bene, infatti: se vuoi unirti a un altro tavolo, aggiungi un'altra linea alla pipeline. Il codice risulterebbe non troppo diverso da una query SQL-join multiplo. –

+0

@HongOoi ma la variabile = = varia a destra? si prega di controllare la mia risposta su questo –

Problemi correlati