2017-06-20 40 views
0

这个问题给出了如何在by.x =by.y =参数转换的基础Rmergedata.table语法,连接键指定不同的名称列的例子:如何使用指定和提取X和Y中的非平衡连接X [Y,...]中的变量?

data.table merge by multiple columns

但是,我不能工作不知道如何为非等效连接做同样的事情,而且我对输出非常困惑。

示例数据:

set.seed(0) 
tmp_dt1<- data.table(grp = c(1,2), time = runif(100)) 
tmp_dt2 <- data.table(grp = c(1,2), time = c(0.1, 0.5)) 
tmp_dt2 <- tmp_dt2[, time_to := time + 0.2] 
tmp_dt2 <- tmp_dt2[, time_from := time] # for clarity, rename time variable 

我想通过grp以相等联接两个表,然后由非球菌加盟,使我只保留timetmp_dt1它属于time_totime_from之间。从我可以告诉tmp_dt1[tmp_dt2, , on = c("grp", "time>=time", "time<=time_to")]做什么,我想:

> tmp_dt1[tmp_dt2, , on = c("grp", "time>=time", "time<=time_to")] 
    grp time time.1 time_from 
1: 1 0.1 0.3  0.1 
2: 1 0.1 0.3  0.1 
3: 1 0.1 0.3  0.1 
4: 1 0.1 0.3  0.1 
5: 1 0.1 0.3  0.1 
6: 1 0.1 0.3  0.1 
7: 1 0.1 0.3  0.1 
... 

什么让我困惑的是,x.time缺失,产生的列名都非常混乱。例如,为什么有一列叫做time.1?我想澄清的语法让tmp_dt1[tmp_dt2, , on = c("grp", "time>=y.time", "time<=y.time_to")]生产:

grp y.time y.time_to time_from 
1: 1 0.1 0.3  0.1 
2: 1 0.1 0.3  0.1 
3: 1 0.1 0.3  0.1 
4: 1 0.1 0.3  0.1 
5: 1 0.1 0.3  0.1 
6: 1 0.1 0.3  0.1 
7: 1 0.1 0.3  0.1 
... 

有的怎么也解列x.time,除了所有列在y。不幸的是这个失败,出现错误:

> tmp_dt1[tmp_dt2, , on = c("grp", "time>=y.time", "time<=y.time_to")] 
Error in `[.data.table`(tmp_dt1, tmp_dt2, , on = c("grp", "time>=y.time", : 
    Column(s) [y.time,y.time_to] not found in i 

尝试以下也不会产生我所期望的,而不是我得到:

> tmp_dt1[tmp_dt2, .(grp, time, time_from = i.time, time_to = i.time_to), on = c("grp", "time>=time", "time<=time_to")] 
    grp time time_from time_to 
1: 1 0.1  0.1  0.3 
2: 1 0.1  0.1  0.3 
3: 1 0.1  0.1  0.3 
4: 1 0.1  0.1  0.3 
5: 1 0.1  0.1  0.3 
6: 1 0.1  0.1  0.3 
7: 1 0.1  0.1  0.3 

其中time列不承担任何相似之处tmp_dt1$time

+0

确定,据我所知,如果使用'提供了'on'条件的连接密钥匹配以下规则适用。()'或'C()'在'X [Y]'中。如果每个元素包含一个变量,则在两个表中查找该变量。如果变量在方程的任一侧提供,则在'X'表中查找LHS变量,在'Y'表中查找RHS变量。变量提取和最终列名对我来说仍然是一个谜。 – Alex

+1

最后的列名始终来自Y.每个条目在'on ='中有一个连接列。 – Frank

+0

您可能想澄清预期的结果。这是一个相当合理的事情:'tmp_dt1 [tmp_dt1 [tmp_dt2,on =。(grp,time> = time_from,time <= time_to),which = TRUE]]'将第一个表格子集化。我怀疑作为重复的价值观挂在下限和上限上是否有很多意义。 – Frank

回答

1

为了避免混淆,我建议重命名两个data.tables中具有相同名称的列,并创建非等连接列的副本。

setnames(tmp_dt2, "time", "time_dt2") tmp_dt2[, c("time_from_join", "time_to_join"):=list(time_from, time_to)] tmp_dt1[ , time_join := time]

然后,我们可以加入,然后扔掉所有data.table混乱与非球菌加入临时列。

tmp_dt1[tmp_dt2, on=.(grp==grp, time_join >= time_from_join, time_join <= time_to_join)][ , c("grp", "time", "time_from", "time_to", "time_dt2")]

grp time time_from time_to time_dt2 1: 1 0.1079436 0.1 0.3 0.1 2: 1 0.1216919 0.1 0.3 0.1 3: 1 0.1255551 0.1 0.3 0.1 4: 1 0.1433044 0.1 0.3 0.1 ...

1

我想你想是这样的,使用dplyr:由grp1

library(dplyr) 
merged <- inner_join(tmp_dt1, tmp_dt2, by="grp") %>% 
      rowwise() %>% 
      filter(between(time.x, time_from, time_to)) %>% 
      ungroup() 

inner_join相等联接。 rowwise()指定我希望以下语句按行发生。 filter()将按条件过滤行。条件使用between,询问是time.x >= time_fromtime.x <= time_to。最后,ungroup按行,万一你想要正常data.frame

+0

谢谢你,不幸的是我很确定这个非Equi加入使用dplyr需要更多内存比data.table版本。 – Alex

+0

为什么不使用data.table连接,然后管道到dplyr过滤器? – CPak

+0

data.table连接(非等分部分)已经完成了过滤。无论如何,我的问题是控制连接的输入和输出。 – Alex