3

我在 R 中有两个数据框,我想有条件地将它们合并到id和上day。合并是right合并到变量的left变量尽可能新/新鲜/最近,但必须至少三天。

但是,如果没有匹配right到我的id-date对,left我仍然想保留它们。我的研究有两个部分,所以我不想仅仅因为它们不完整而放弃id-观察。day

我可以sqldf一步完成吗?我目前的方法需要一个额外的基础 R merge

left <- data.frame(id=rep(1:5, each=10),
                   day=rep(1:10, times=5),
                   x=rnorm(5*10))
right <- data.frame(id=rep(1:2, each=21),
                   day=rep(-10:10, times=2),
                   y=rnorm(2*21))
combined <- sqldf("SELECT L.id, L.day, L.x, R.y
                  FROM left L LEFT OUTER JOIN right R
                  ON (L.id = R.id)
                  WHERE ((L.day - R.day) >= 3)
                  GROUP BY L.id, L.day
                  HAVING (R.day = MAX(R.day))")
combined                  

combined.2 <- merge(left, combined, all=TRUE)
combined.2 
4

2 回答 2

5

尝试像这样嵌套 select 语句:

sqldf("SELECT * from left
       LEFT JOIN (SELECT id, L.day, L.x, R.y
                  FROM left L LEFT OUTER JOIN right R
                  USING (id)
                  WHERE ((L.day - R.day) >= 3)
                  GROUP BY L.id, L.day
                  HAVING (R.day = MAX(R.day))) 
       USING (id, day, x)")

这也可以如下进行。它使用的事实是,如果使用 max,则同一结果行上的其他值保证来自与 max 相同的原始行。这是 SQLite 提供的 SQL 扩展。

sqldf("select max(R.day) as maxRday, L.*, R.y
  from left L left outer join right R
  on L.id = R.id and L.day - R.day >= 3
  group by L.id, L.day")[-1]
于 2014-04-05T12:39:27.947 回答
1

使用 1.9.8 版(CRAN 2016 年 11 月 25 日),data.table获得了执行非 equi 连接的能力。当bartektartanus 承诺 发布data.table答案时,此功能在 2014 年不可用。

现在,在 2020 年,延迟了 6 年,这里有一个data.table答案:

library(data.table)
setDT(right)[, join_day := day + 3L][
  setDT(left), on = .(id, join_day <= day), .(x = last(x), y = last(y)), by = .EACHI][
    , setnames(.SD, "join_day", "day")]

返回

    id day  x  y
 1:  1   1  1  2
 2:  1   2  2  2
 3:  1   3  3  3
 4:  2   1  4  6
 5:  2   2  5  7
 6:  2   3  6  7
 7:  3   1  7 13
 8:  3   2  8 14
 9:  3   3  9 15
10:  4   1 10 NA
11:  4   2 11 NA
12:  4   3 12 NA

对于修改后的样本数据

left <- data.table(id = rep(1:4, each=3),
                   day = rep(1:3, times=4),
                   x = 1:(3*4))
right <- data.table(id = c(rep(1:2, each=5L), rep(3, 9L)),
                    day = c(seq(-4L, 4L, 2L), seq(-3L, 5L, 2L), -4:4))[, y := seq_along(id)]

在哪里

left
    id day  x
 1:  1   1  1
 2:  1   2  2
 3:  1   3  3
 4:  2   1  4
 5:  2   2  5
 6:  2   3  6
 7:  3   1  7
 8:  3   2  8
 9:  3   3  9
10:  4   1 10
11:  4   2 11
12:  4   3 12

right
    id day  y
 1:  1  -4  1
 2:  1  -2  2
 3:  1   0  3
 4:  1   2  4
 5:  1   4  5
 6:  2  -3  6
 7:  2  -1  7
 8:  2   1  8
 9:  2   3  9
10:  2   5 10
11:  3  -4 11
12:  3  -3 12
13:  3  -2 13
14:  3  -1 14
15:  3   0 15
16:  3   1 16
17:  3   2 17
18:  3   3 18
19:  3   4 19
于 2020-03-17T11:30:42.487 回答