Jak określić nazwy kolumn dla x i y podczas łączenia w dplyr?


89

Mam dwie ramki danych, które chcę połączyć za pomocą dplyr. Jedna to ramka danych zawierająca imiona.

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

Druga ramka danych zawiera uporządkowaną wersję korpusu nazw Kantrowitza, identyfikującą płeć. Oto minimalny przykład:

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

Zasadniczo chcę sprawdzić płeć nazwiska z test_datatabeli za pomocą kantrowitztabeli. Ponieważ zamierzam przekształcić to w funkcję encode_gender, nie będę znać nazwy kolumny w zestawie danych, który będzie używany, więc nie mogę zagwarantować, że tak będzie name, jak w kantrowitz$name.

W bazowym RI scaliłbym w ten sposób:

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

To zwraca poprawne dane wyjściowe:

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

Ale chcę to zrobić w dplyr, ponieważ używam tego pakietu do wszystkich innych operacji na danych. Opcja dplyr bydla różnych *_joinfunkcji pozwala mi określić tylko jedną nazwę kolumny, ale muszę określić dwie. Szukam czegoś takiego:

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

Jaki jest sposób wykonania tego rodzaju złączenia za pomocą dplyr?

(Nieważne, że korpus Kantrowitza to zły sposób na identyfikację płci. Pracuję nad lepszą implementacją, ale najpierw chcę, żeby to zadziałało).


3
Obecnie nie możesz, ale jest na liście rzeczy do zrobienia: github.com/hadley/dplyr/issues/177
hadley

Odpowiedzi:


148

Ta funkcja została dodana w dplyr v0.3. Możesz teraz przekazać nazwany wektor znakowy do byargumentu in left_join(i innych funkcji łączących), aby określić, które kolumny mają być połączone w każdej ramce danych. W przykładzie podanym w pierwotnym pytaniu kod wyglądałby tak:

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

13
edytować w ogólnym przypadku to działa jak dobrze: left_join(data_a, data_b, by = c("a.first" = "b.first", "a.second" = "b.second", "a.third" = "b.third"))?
davidski

To by =jest opcjonalne. Możesz to zrobićleft_join(test_data, kantrowitz, c("first_name" = "name"))
Pranay Aryal

11
Dotyczy to każdego argumentu funkcji. Ale generalnie uważam, że lepiej jest być wyraźnym, używając nazwanych argumentów, zamiast dopasowywania pozycji w tym przypadku.
Lincoln Mullen

5

To bardziej obejście niż prawdziwe rozwiązanie. Możesz utworzyć nowy obiekt test_dataz inną nazwą kolumny:

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>

Myślę, że zmiana nazwy wywołuje kopię, co może być sposobem, w jaki dplyr tego unika i sprawia, że ​​robisz to.
joran

2
W 0.1.2 przynajmniej będziesz w stanie to zrobić, select(test_data, first_name = name)a to będzie tylko płytką kopię.
hadley

1
Użyj data.table::setnames?
Hugh,

2
wybór rozwiązania (test_data, first_name = name) nie działa od czerwca 2014
userJT
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.