Tengo dos marcos de datos que quiero unir usando dplyr. Uno es un marco de datos que contiene nombres.
test_data <- data.frame(first_name = c("john", "bill", "madison", "abby", "zzz"),
stringsAsFactors = FALSE)
El otro marco de datos contiene una versión limpia del corpus de nombres de Kantrowitz, identificando el género. Aquí hay un ejemplo mínimo:
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"))
Básicamente, quiero buscar el género del nombre de la test_data
tabla usando la kantrowitz
tabla. Como voy a abstraer esto en una función encode_gender
, no sabré el nombre de la columna en el conjunto de datos que se usará, por lo que no puedo garantizar que así sea name
, como en kantrowitz$name
.
En base, RI realizaría la fusión de esta manera:
merge(test_data, kantrowitz, by.x = "first_names", by.y = "name", all.x = TRUE)
Eso devuelve la salida correcta:
first_name gender
1 abby either
2 bill either
3 john M
4 madison M
5 zzz <NA>
Pero quiero hacer esto en dplyr porque estoy usando ese paquete para todas mis otras manipulaciones de datos. La by
opción dplyr para las diversas *_join
funciones solo me permite especificar un nombre de columna, pero necesito especificar dos. Estoy buscando algo como esto:
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"))
¿Cuál es la forma de realizar este tipo de unión utilizando dplyr?
(No importa que el corpus de Kantrowitz sea una mala manera de identificar el género. Estoy trabajando en una mejor implementación, pero primero quiero que esto funcione).
Respuestas:
Esta función se ha agregado en dplyr v0.3. Ahora puede pasar un vector de caracteres con nombre al
by
argumento enleft_join
(y otras funciones de unión) para especificar en qué columnas unirse en cada marco de datos. Con el ejemplo dado en la pregunta original, el código sería:left_join(test_data, kantrowitz, by = c("first_name" = "name"))
fuente
left_join(data_a, data_b, by = c("a.first" = "b.first", "a.second" = "b.second", "a.third" = "b.third"))
:?by =
es opcional. Puedes hacerloleft_join(test_data, kantrowitz, c("first_name" = "name"))
Esto es más una solución temporal que una solución real. Puede crear un nuevo objeto
test_data
con otro nombre de columna: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>
fuente
select(test_data, first_name = name)
y eso solo hará una copia superficial.data.table::setnames
?