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.