J'ai deux trames de données que je veux joindre en utilisant dplyr. L'un est un bloc de données contenant les prénoms.
test_data <- data.frame(first_name = c("john", "bill", "madison", "abby", "zzz"),
stringsAsFactors = FALSE)
L'autre bloc de données contient une version nettoyée du corpus des noms de Kantrowitz, identifiant le sexe. Voici un exemple minimal:
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"))
Je veux essentiellement rechercher le sexe du nom de la test_data
table en utilisant la kantrowitz
table. Parce que je vais résumer cela dans une fonction encode_gender
, je ne connais pas le nom de la colonne dans l'ensemble de données qui va être utilisé, et donc je ne peux pas garantir qu'elle le sera name
, comme dans kantrowitz$name
.
Dans la base, RI effectuerait la fusion de cette façon:
merge(test_data, kantrowitz, by.x = "first_names", by.y = "name", all.x = TRUE)
Cela renvoie la sortie correcte:
first_name gender
1 abby either
2 bill either
3 john M
4 madison M
5 zzz <NA>
Mais je veux faire cela dans dplyr parce que j'utilise ce package pour toutes mes autres manipulations de données. L' by
option dplyr pour les différentes *_join
fonctions ne me permet de spécifier qu'un seul nom de colonne, mais je dois en spécifier deux. Je cherche quelque chose comme ça:
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"))
Comment effectuer ce type de jointure en utilisant dplyr?
(Peu importe que le corpus Kantrowitz soit un mauvais moyen d'identifier le genre. Je travaille sur une meilleure implémentation, mais je veux que cela fonctionne en premier.)
Réponses:
Cette fonctionnalité a été ajoutée dans dplyr v0.3. Vous pouvez maintenant passer un vecteur de caractère nommé à l'
by
argument dansleft_join
(et à d'autres fonctions de jointure) pour spécifier les colonnes à joindre dans chaque bloc de données. Avec l'exemple donné dans la question initiale, le code serait:left_join(test_data, kantrowitz, by = c("first_name" = "name"))
la source
left_join(data_a, data_b, by = c("a.first" = "b.first", "a.second" = "b.second", "a.third" = "b.third"))
?by =
est facultatif. Vous pouvez faireleft_join(test_data, kantrowitz, c("first_name" = "name"))
C'est plus une solution de contournement qu'une vraie solution. Vous pouvez créer un nouvel objet
test_data
avec un autre nom de colonne: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>
la source
select(test_data, first_name = name)
et cela ne fera qu'une copie superficielle.data.table::setnames
?