Come specificare i nomi delle colonne per xey quando ci si unisce in dplyr?


91

Ho due frame di dati che voglio unire usando dplyr. Uno è un frame di dati contenente i nomi.

test_data <- data.frame(first_name = c("john", "bill", "madison", "abby", "zzz"),
                        stringsAsFactors = FALSE)

L'altro data frame contiene una versione pulita del corpus dei nomi Kantrowitz, che identifica il sesso. Ecco un esempio minimo:

kantrowitz <- structure(list(name = c("john", "bill", "madison", "abby", "thomas"), gender = c("M", "either", "M", "either", "M")), .Names = c("name", "gender"), row.names = c(NA, 5L), class = c("tbl_df", "tbl", "data.frame"))

In sostanza voglio cercare il sesso del nome dalla test_datatabella utilizzando la kantrowitztabella. Poiché lo astraggerò in una funzione encode_gender, non conoscerò il nome della colonna nel set di dati che verrà utilizzato, quindi non posso garantire che lo sarà name, come in kantrowitz$name.

In base RI eseguirà l'unione in questo modo:

merge(test_data, kantrowitz, by.x = "first_names", by.y = "name", all.x = TRUE)

Ciò restituisce l'output corretto:

  first_name gender
1       abby either
2       bill either
3       john      M
4    madison      M
5        zzz   <NA>

Ma voglio farlo in dplyr perché sto usando quel pacchetto per tutte le mie altre manipolazioni dei dati. L' byopzione dplyr per le varie *_joinfunzioni mi consente di specificare solo un nome di colonna, ma devo specificarne due. Sto cercando qualcosa del genere:

library(dplyr)
# either
left_join(test_data, kantrowitz, by.x = "first_name", by.y = "name")
# or
left_join(test_data, kantrowitz, by = c("first_name", "name"))

Qual è il modo per eseguire questo tipo di join utilizzando dplyr?

(Non importa che il corpus di Kantrowitz sia un cattivo modo per identificare il genere. Sto lavorando a un'implementazione migliore, ma prima voglio che funzioni.)


3
Al momento non puoi, ma è nella lista delle cose da fare: github.com/hadley/dplyr/issues/177
hadley

Risposte:


153

Questa funzione è stata aggiunta in dplyr v0.3. È ora possibile passare un vettore di caratteri con nome byall'argomento in left_join(e altre funzioni di unione) per specificare su quali colonne unire in ciascun frame di dati. Con l'esempio fornito nella domanda originale, il codice sarebbe:

left_join(test_data, kantrowitz, by = c("first_name" = "name"))

13
modificare questo funziona nel caso generale, così: left_join(data_a, data_b, by = c("a.first" = "b.first", "a.second" = "b.second", "a.third" = "b.third"))?
davidski

Il by =è opzionale. Puoi fareleft_join(test_data, kantrowitz, c("first_name" = "name"))
Pranay Aryal

11
Questo è vero per qualsiasi argomento di una funzione. Ma in genere trovo che sia meglio essere espliciti utilizzando argomenti con nome piuttosto che la corrispondenza della posizione in questo caso.
Lincoln Mullen

5

Questa è più una soluzione alternativa che una soluzione reale. Puoi creare un nuovo oggetto test_datacon un altro nome di colonna:

left_join("names<-"(test_data, "name"), kantrowitz, by = "name")

     name gender
1    john      M
2    bill either
3 madison      M
4    abby either
5     zzz   <NA>

Rinominare induce una copia, penso, il che potrebbe essere il modo in cui dplyr lo evita e ti fa invece farlo.
joran

2
In 0.1.2 sarai almeno in grado di farlo select(test_data, first_name = name)e questo farà solo una copia superficiale.
Hadley

1
Utilizzare data.table::setnames?
Hugh

2
la selezione della soluzione (test_data, first_name = name) non funziona a partire da giugno 2014
userJT
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.