使用WHERE和HAVING子句在sqldf中进行LEFT OUTER JOIN

时间:2014-04-05 10:31:35

标签: r sqldf

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

但是,如果right中的id - dateleft中没有匹配,我仍然希望保留它们。我的研究分为两部分,所以我不想放弃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 

2 个答案:

答案 0 :(得分:3)

尝试嵌套这样的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)")

答案 1 :(得分:1)

使用1.9.8版(于2016年11月25日在CRAN上发布),data.table获得了执行非等额联接的能力。 2014年bartektartanus promised发布data.table答案时,此功能不可用。

现在,到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