我在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
答案 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