【发布时间】:2016-05-13 05:15:47
【问题描述】:
在两个数据表(dt1,dt2)上进行左外连接的最简单方法是什么桌子?
一个常见的答案,例如在 this thread 中,是使用 dplyr::left_join 或 data.table::merge 或 data.table 的 dt2[dt1] 键控列括号语法进行左外连接,然后简单地执行第二步将连接数据表中的所有 NA 值替换为 0。例如:
library(data.table);
dt1 <- data.table(x=c('a', 'b', 'c', 'd', 'e'), y=c(NA, 'w', NA, 'y', 'z'));
dt2 <- data.table(x=c('a', 'b', 'c'), new_col=c(1,2,3));
setkey(dt1, x);
setkey(dt2, x);
merged_tables <- dt2[dt1];
merged_tables[is.na(merged_tables)] <- 0;
这种方法必然假定dt1 中没有需要保留的有效NA 值。然而,正如您在上面的示例中看到的,结果是:
x new_col y
1: a 1 0
2: b 2 w
3: c 3 0
4: d 0 y
5: e 0 z
但期望的结果是:
x new_col y
1: a 1 NA
2: b 2 w
3: c 3 NA
4: d 0 y
5: e 0 z
在这种微不足道的情况下,可以替换new_col 中的所有元素替换语法,而不是使用data.table 的所有元素替换语法:
library(dplyr);
merged_tables <- mutate(merged_tables, new_col = ifelse(is.na(new_col), 0, new_col));
但是,这种方法对于合并了数十或数百个新列(有时具有动态创建的列名)的非常大的数据集并不实用。即使列名都是提前知道的,列出所有新列并在每个列上进行 mutate-style 替换也是非常难看的。
一定有更好的方法吗?如果dplyr::left_join、data.table::merge 或data.table 括号中的任何一个的语法很容易允许用户指定除NA 之外的fill 值,则该问题将得到简单解决。比如:
merged_tables <- data.table::merge(dt1, dt2, by="x", all.x=TRUE, fill=0);
data.table 的dcast 函数允许用户指定fill 值,所以我认为必须有一种更简单的方法来做到这一点,而我只是没有想到。
建议?
编辑:@jangorecki 在 cmets 中指出,当前在 data.table GitHug page 上打开了一个功能请求,以执行我刚才提到的操作,更新 nomatch=0 语法。应该在data.table的下一个版本中。
【问题讨论】:
-
在
merge的末尾或使用[..., nomatch=NA]链式data.table 查询merge()[is.na(col), col := 0]进行外部连接。有一个开放的FR,所以nomatcharg 可以处理任意值,目前对于外连接它只能使用NA。 -
很抱歉,我无法理解您的回答。
col来自哪里?很高兴听到有一个开放的功能请求。我会为它添加我的 +1。 -
col只是一个正在连接的列 -
在哪个连接上进行?在这种情况下,
x不是关键吗?如果将col指定为添加的新列的名称(在本例中为new_col),则您的建议有效,但除非我误解,否则您仍然必须为手动添加的每个新列链接此替换,很多就像我的示例中的dplyr::mutate一样,这对于合并的数百个新列是不切实际的。我是不是误会了?
标签: r merge left-join data.table dplyr