这个问题给出了一个示例,说明如何将基R
merge
中的by.x =
和by.y =
参数转换为data.table
语法,以指定不同名称的列作为连接键:
数据表按多列合并
但是,我无法弄清楚如何对非 equi 连接执行相同的操作,并且我对输出感到非常困惑。
示例数据:
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
等连接两个表,然后是非 equi 连接,这样我只time
tmp_dt1
它落在time_to
和time_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
没有相似之处。
为了防止混淆,我建议重命名两个 data.tables 中具有相同名称的列,并创建非 equi 连接列列的副本。
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 在非 equi 连接中弄乱的所有临时列。
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
...
我认为你想要这样的东西,使用dplyr
:
library(dplyr)
merged <- inner_join(tmp_dt1, tmp_dt2, by="grp") %>%
rowwise() %>%
filter(between(time.x, time_from, time_to)) %>%
ungroup()
inner_join
grp1
的等联接 .rowwise()
指定我希望以下语句按行出现。filter()
将按条件筛选行。条件使用between
,询问是time.x >= time_from
和time.x <= time_to
。最后,按行ungroup
,以防您想要正常data.frame
.