Bagaimana cara menentukan nama kolom untuk x dan y saat bergabung dalam dplyr?

91

Saya memiliki dua bingkai data yang ingin saya gabungkan menggunakan dplyr. Salah satunya adalah bingkai data yang berisi nama depan.

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

Kerangka data lainnya berisi versi korpus nama Kantrowitz yang telah dibersihkan, mengidentifikasi jenis kelamin. Berikut adalah contoh minimalnya:

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

Saya pada dasarnya ingin mencari jenis kelamin nama dari test_datatabel menggunakan kantrowitztabel. Karena saya akan mengabstraksi ini menjadi sebuah fungsi encode_gender, saya tidak akan tahu nama kolom dalam kumpulan data yang akan digunakan, jadi saya tidak dapat menjamin bahwa itu akan name, seperti pada kantrowitz$name.

Di basis RI akan melakukan penggabungan dengan cara ini:

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

Itu mengembalikan keluaran yang benar:

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

Tetapi saya ingin melakukan ini di dplyr karena saya menggunakan paket itu untuk semua manipulasi data saya yang lain. byOpsi dplyr ke berbagai *_joinfungsi hanya memungkinkan saya menentukan satu nama kolom, tetapi saya perlu menentukan dua. Saya mencari sesuatu seperti ini:

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

Bagaimana cara melakukan jenis join ini menggunakan dplyr?

(Tidak peduli bahwa korpus Kantrowitz adalah cara yang buruk untuk mengidentifikasi gender. Saya sedang mengerjakan implementasi yang lebih baik, tapi saya ingin ini berfungsi terlebih dahulu.)

Lincoln Mullen
sumber
3
Saat ini Anda tidak bisa, tetapi itu ada di daftar tugas
hadley

Jawaban:

153

Fitur ini telah ditambahkan di dplyr v0.3. Anda sekarang dapat meneruskan vektor karakter bernama ke byargumen di left_join(dan fungsi penggabungan lainnya) untuk menentukan kolom mana yang akan digabungkan di setiap bingkai data. Dengan contoh yang diberikan pada pertanyaan awal, kodenya adalah:

left_join(test_data, kantrowitz, by = c("first_name" = "name"))
Lincoln Mullen
sumber
13
sunting Ini bekerja dalam kasus umum juga left_join(data_a, data_b, by = c("a.first" = "b.first", "a.second" = "b.second", "a.third" = "b.third")):?
davidski
Ini by =opsional. Anda dapat melakukannyaleft_join(test_data, kantrowitz, c("first_name" = "name"))
Pranay Aryal
11
Itu benar untuk argumen apa pun untuk suatu fungsi. Tapi saya biasanya merasa lebih baik untuk eksplisit dengan menggunakan argumen bernama daripada pencocokan posisi dalam kasus ini.
Lincoln Mullen
5

Ini lebih merupakan solusi daripada solusi nyata. Anda dapat membuat objek baru test_datadengan nama kolom lain:

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>
Sven Hohenstein
sumber
Mengganti nama menginduksi salinan, saya pikir, yang mungkin cara dplyr menghindarinya dan membuat Anda melakukannya sebagai gantinya.
joran
2
Dalam 0.1.2 Anda setidaknya dapat melakukannya select(test_data, first_name = name)dan itu hanya akan membuat salinan yang dangkal.
hadley
1
Gunakan data.table::setnames?
Hugh
2
pemilihan solusi (test_data, first_name = name) tidak berfungsi pada Juni 2014
userJT