【问题标题】:Join big dataframe in r and filter in the same time在 r 中加入大数据框并同时过滤
【发布时间】:2018-09-04 10:28:36
【问题描述】:
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 的值之间。

dplyr::inner_join 无法正常工作,因为它需要太多内存。 对于每个iddf2 中的日期间隔比df1 中的大很多,这就是为什么 inner_join %&gt;% filter 效率不高,是否可以同时进行?

【问题讨论】:

  • 您能否举一个预期输出的示例。
  • This 可能暗示在 合并 数据帧之后使用 sqldf

标签: r dataframe dplyr data.table non-equi-join


【解决方案1】:

来自data.tablesqldf 包的非equi 连接可能比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

使用来自data.table 包的非相等连接: Benchmark | Video

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 package (v0.2.0) 于 2018 年 3 月 28 日创建。

【讨论】:

  • 谢谢!在这种情况下,sqldf 的方法效率不高(它分配了太多内存),但非 equi-join 方法有效,而且速度非常快
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-12
  • 2017-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多