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_data
tabeli za pomocą kantrowitz
tabeli. 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 by
dla różnych *_join
funkcji 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).
Odpowiedzi:
Ta funkcja została dodana w dplyr v0.3. Możesz teraz przekazać nazwany wektor znakowy do
by
argumentu inleft_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"))
źródło
left_join(data_a, data_b, by = c("a.first" = "b.first", "a.second" = "b.second", "a.third" = "b.third"))
?by =
jest opcjonalne. Możesz to zrobićleft_join(test_data, kantrowitz, c("first_name" = "name"))
To bardziej obejście niż prawdziwe rozwiązanie. Możesz utworzyć nowy obiekt
test_data
z 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>
źródło
select(test_data, first_name = name)
a to będzie tylko płytką kopię.data.table::setnames
?