1
df1 = data.frame(id=1,start=as.Date("2012-07-05"),end=as.Date("2012-07-15"))

df2 = data.frame(id=rep(1,1371),date = as.Date(as.Date("2012-05-06"):as.Date("2016-02-05")))


output = dplyr::inner_join(x=df1,y=df2,by="id") %>% filter(date>=start & date<= end)

我有两个数据框,每个数据框都有大约一百万行,我想通过 id 加入它们,然后过滤,以便对于每一行,列日期的值包含在 startdate 和 enddate 的值之间。

Andplyr::inner_join无法正常工作,因为它需要太多内存。对于每个id日期间隔df2都比 in大很多,df1这就是为什么 aninner_join %>% filter效率不高,是否可以同时进行?

4

1 回答 1

1

非 equi join from data.tableor sqldfpackages 可以比dplyr尝试一下快很多

df1 = data.frame(id = 1, start = as.Date("2012-07-05"), 
                 end = as.Date("2012-07-15"))
df1
#>   id      start        end
#> 1  1 2012-07-05 2012-07-15

df2 = data.frame(id = rep(1, 1371), 
                 date = seq(as.Date("2012-05-06"), as.Date("2016-02-05"), by = "1 day"))
head(df2)
#>      id       date
#> 1     1 2012-05-06
#> 2     1 2012-05-07
#> 3     1 2012-05-08
#> 4     1 2012-05-09
#> 5     1 2012-05-10
#> 6     1 2012-05-11

使用sqldf包:

library(sqldf)

sqldf("SELECT f1.id, start, end, date
      FROM df1 f1, df2 f2
      WHERE f1.id = f2.id AND
      f2.date >= f1.start AND 
      f2.date <= f1.end")

#>    id      start        end       date
#> 1   1 2012-07-05 2012-07-15 2012-07-05
#> 2   1 2012-07-05 2012-07-15 2012-07-06
#> 3   1 2012-07-05 2012-07-15 2012-07-07
#> 4   1 2012-07-05 2012-07-15 2012-07-08
#> 5   1 2012-07-05 2012-07-15 2012-07-09
#> 6   1 2012-07-05 2012-07-15 2012-07-10
#> 7   1 2012-07-05 2012-07-15 2012-07-11
#> 8   1 2012-07-05 2012-07-15 2012-07-12
#> 9   1 2012-07-05 2012-07-15 2012-07-13
#> 10  1 2012-07-05 2012-07-15 2012-07-14
#> 11  1 2012-07-05 2012-07-15 2012-07-15

使用包中的非 equi 连接data.table Benchmark | 视频

library(data.table)

## convert both data.frames to data.tables by reference
setDT(df1)
setDT(df2) 

# join by id and date within start & end limits
# "x." is used so we can refer to the column in df1 explicitly
df2[df1, .(id, date = x.date, start, end), 
  on = .(id, date >= start, date <= end)]

#>     id       date      start        end
#>  1:  1 2012-07-05 2012-07-05 2012-07-15
#>  2:  1 2012-07-06 2012-07-05 2012-07-15
#>  3:  1 2012-07-07 2012-07-05 2012-07-15
#>  4:  1 2012-07-08 2012-07-05 2012-07-15
#>  5:  1 2012-07-09 2012-07-05 2012-07-15
#>  6:  1 2012-07-10 2012-07-05 2012-07-15
#>  7:  1 2012-07-11 2012-07-05 2012-07-15
#>  8:  1 2012-07-12 2012-07-05 2012-07-15
#>  9:  1 2012-07-13 2012-07-05 2012-07-15
#> 10:  1 2012-07-14 2012-07-05 2012-07-15
#> 11:  1 2012-07-15 2012-07-05 2012-07-15

reprex 包(v0.2.0) 于 2018 年 3 月 28 日创建。

于 2018-03-28T09:42:36.013 回答