在dplyr中进行连接时如何指定x和y的列名?

122

我有两个数据框,想要使用dplyr进行合并。其中一个数据框包含名字。

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

另一个数据框包含经过清理的Kantrowitz姓名语料库,标识性别。以下是一个最简示例:

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 的函数,所以我不知道数据集中将要使用的列的名称,并且不能保证它会像 kantrowitz$name 中一样是 name

在基础 R 中,我会按照以下方式执行合并操作:

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执行这种类型的连接?

(不要在意Kantrowitz语料库是识别性别的不好方式。我正在开发更好的实现方法,但我想先使这个工作起来。)


3
目前还不能实现,但它已列入待办事项:https://github.com/hadley/dplyr/issues/177 - hadley
2个回答

214

此功能已添加到dplyr v0.3中。现在,您可以向left_join(和其他连接函数)的by参数传递一个命名的字符向量,以指定每个数据框中要加入哪些列。使用原始问题中提供的示例,代码如下:

left_join(test_data, kantrowitz, by = c("first_name" = "name"))

17
这个通常情况下也适用:left_join(data_a, data_b, by = c("a.first" = "b.first", "a.second" = "b.second", "a.third" = "b.third")) - davidski
1
by = 是可选的。您可以执行 left_join(test_data, kantrowitz, c("first_name" = "name")) - Pranay Aryal
16
对于任何函数的参数都是正确的。但在这种情况下,我通常发现使用命名参数而不是位置匹配更明确更好理解。 - Lincoln Mullen
1
一些用户可能建议更新语法以使用join_by()。 以下是等效的: left_join(test_data, kantrowitz, by = join_by(first_name == name)) - etrowbridge

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),这只会进行浅复制。 - hadley
1
使用 data.table::setnames 吗? - Hugh
2
截至2014年6月,解决方案select(test_data,first_name = name)无法正常工作。 - userJT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接