r - 如何在非等连接 X[Y, ..] 中使用从 X 和 Y 指定和提取变量?

  • 本文关键字:变量 提取 连接 r data.table
  • 更新时间 :
  • 英文 :


这个问题给出了一个示例,说明如何将基Rmerge中的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 连接,这样我只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没有相似之处。

为了防止混淆,我建议重命名两个 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_joingrp1的等联接 .rowwise()指定我希望以下语句按行出现。filter()将按条件筛选行。条件使用between,询问是time.x >= time_fromtime.x <= time_to。最后,按行ungroup,以防您想要正常data.frame.

最新更新