Как указать имена столбцов для x и y при объединении в dplyr?

89

У меня есть два фрейма данных, к которым я хочу присоединиться с помощью dplyr. Один - это фрейм данных, содержащий имена.

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

Другой фрейм данных содержит очищенную версию корпуса имен Кантровица с указанием пола. Вот минимальный пример:

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

По сути, я хочу найти пол имени из test_dataтаблицы, используя kantrowitzтаблицу. Поскольку я собираюсь преобразовать это в функцию encode_gender, я не буду знать имя столбца в наборе данных, который будет использоваться, и поэтому я не могу гарантировать, что это будет name, как в kantrowitz$name.

В базовом RI слияние будет выполнено следующим образом:

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

Это возвращает правильный результат:

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

Но я хочу сделать это в dplyr, потому что я использую этот пакет для всех остальных операций с данными. Параметр dplyr byдля различных *_joinфункций позволяет мне указать только одно имя столбца, но мне нужно указать два. Я ищу что-то вроде этого:

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

Как можно выполнить такое соединение с помощью dplyr?

(Неважно, что корпус Кантровица - плохой способ определить пол. Я работаю над лучшей реализацией, но сначала хочу, чтобы это работало.)

Линкольн Маллен
источник
3
В настоящее время вы не можете, но это в списке дел: github.com/hadley/dplyr/issues/177
hadley

Ответы:

148

Эта функция была добавлена ​​в dplyr v0.3. Теперь вы можете передать именованный вектор символов byаргументу в left_join(и другим функциям соединения), чтобы указать, какие столбцы следует присоединять в каждом фрейме данных. В примере, приведенном в исходном вопросе, код будет следующим:

left_join(test_data, kantrowitz, by = c("first_name" = "name"))
Линкольн Маллен
источник
13
edit Это работает и в общем случае left_join(data_a, data_b, by = c("a.first" = "b.first", "a.second" = "b.second", "a.third" = "b.third")):?
Давидски
by =Не является обязательным. Вы можете сделатьleft_join(test_data, kantrowitz, c("first_name" = "name"))
Праная Арьял
11
Это верно для любого аргумента функции. Но я обычно считаю, что в этом случае лучше быть явным, используя именованные аргументы, а не сопоставление позиций.
Линкольн Маллен
5

Это скорее обходной путь, чем реальное решение. Вы можете создать новый объект test_dataс другим именем столбца:

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>
Свен Хохенштейн
источник
Я думаю, что переименование вызывает копию, что может быть способом, которым dplyr избегает этого и заставляет вас делать это вместо этого.
joran
2
В версии 0.1.2 вы, по крайней мере, сможете это сделать, select(test_data, first_name = name)и это сделает только поверхностную копию.
Хэдли
1
Использовать data.table::setnames?
Хью
2
выбор решения (test_data, first_name = name) не работает по состоянию на июнь 2014 г.
userJT