在聚合时按照最接近的前一个日期合并两个数据帧

时间:2016-12-07 21:23:56

标签: r data.table

我试图按组最近的前一个日期匹配两个数据集。 因此,在一个组中,我想将第二个数据集(d2)的变量添加到第一个数据集(d1)的变量,当第一个数据集的日期是第二个数据集中的日期或之前的最近日期。如果第二个数据集中的两行与第一个数据集中的一行匹配,我想添加更大的值。 (d1中至少有一个日期比d2中的日期少,按组分列)

这是一个例子,希望能让它更清晰

 d1 = data.frame(id=c(1,1,1,2,2), 
                 ref=as.Date(c("2013-12-07", "2014-12-07", "2015-12-07", "2013-11-07", "2014-11-07" )))
 d1
#   id        ref
# 1  1 2013-12-07
# 2  1 2014-12-07
# 3  1 2015-12-07
# 4  2 2013-11-07
# 5  2 2014-11-07

 d2 = data.frame(id=c(1,1,2),                
                 date=as.Date(c("2014-05-07","2014-12-05", "2015-11-05")),
                 x1 = factor(c(1,2,2), ordered = TRUE), 
                 x2 = factor(c(2, NA ,2), ordered=TRUE))
 d2
#   id    date x1   x2
# 1  1 2014-05-07  1    2
# 2  1 2014-12-05  2 <NA>
# 3  2 2015-11-05  2    2

预期结果

 output = data.frame(id=c(1,1,1,2,2),
                     ref=as.Date(c("2013-12-07", "2014-12-07", "2015-12-07", "2013-11-07", "2014-11-07" )),
                     x1 = c(2, NA, NA, NA, 2),
                     x2 = c(2, NA, NA, NA, 2))
 output
#   id        ref x1 x2
# 1  1 2013-12-07  2  2
# 2  1 2014-12-07 NA NA
# 3  1 2015-12-07 NA NA
# 4  2 2013-11-07 NA NA
# 5  2 2014-11-07  2  2

因此,例如,d2,id = 1,日期"2014-05-07","2014-12-05"的前两个观察值与d1中的早期日期"2013-12-07"匹配。由于在d1中有两行匹配一行, 然后选择最高级别。

我可以通过循环以下计算在基数R中执行此操作 每个小组,但我希望有更高效的东西。 我很想看到一个data.table方法(但我仅限于R v3.1和data.table v1.9.4)。感谢

真实数据集:
 d1:行1M / 100K组
 d2:行11K / 4K组

# for one group
x = d1[d1$id==1, ]
y = d2[d2$id==1, ]
id = apply(outer(x$ref, y$date, "-"), 2, which.min)
temp = cbind(y, ref=x$ref[id])
# aggregate variables by ref
temp = merge(aggregate(x1 ~ ref, data=temp, max),
aggregate(x2 ~ ref, data=temp, max)
)
merge(x, temp, all=T)

ps:我看过How to match by nearest date from two data frames?Join data.table on exact date or if not the case on the nearest less than date但没有成功。

1 个答案:

答案 0 :(得分:2)

您可以使用dplyr

执行此操作
d2$ind <- 0
library(dplyr)
out <- d1 %>% full_join(d2,by=c("id","ref"="date")) %>%
              arrange(id,ref) %>%
              mutate(ind=cumsum(ifelse(is.na(ind),1,ind))) %>%
              group_by(ind) %>% 
              summarise(ref=min(ref),x1=max(x1,na.rm=TRUE),x2=max(x2,na.rm=TRUE))
### A tibble: 5 x 4
##    ind        ref     x1     x2
##  <dbl>     <date> <fctr> <fctr>
##1     1 2013-12-07      2      2
##2     2 2014-12-07     NA     NA
##3     3 2015-12-07     NA     NA
##4     4 2013-11-07     NA     NA
##5     5 2014-11-07      2      2

我们首先向d2添加一列指标并将其设置为零。然后,我们在d1d2之间执行完全外部联接。 d1中的这些行将ind NA。我们按idref(即日期)排序,我们将NA的{​​{1}}条目替换为ind并执行1 }。这导致:

cumsum

通过此,我们可以很容易地看到,我们可以按 id ref x1 x2 ind 1 1 2013-12-07 <NA> <NA> 1 2 1 2014-05-07 1 2 1 3 1 2014-12-05 2 <NA> 1 4 1 2014-12-07 <NA> <NA> 2 5 1 2015-12-07 <NA> <NA> 3 6 2 2013-11-07 <NA> <NA> 4 7 2 2014-11-07 <NA> <NA> 5 8 2 2015-11-05 2 2 5 ind进行相应分组,以获得结果。