【问题标题】:Any other process faster than sqldf in rr中比sqldf更快的任何其他进程
【发布时间】:2018-12-11 10:34:26
【问题描述】:

我有 2 个数据框

df1 有 700,000 个数据点

  • ID1:分类变量有 400 多个类别
  • 日期 1:1 年数据
  • MST1:2 级变量 1/2
  • 确认号:唯一标识符

样本数据:

ID1 ExtractDate1    MktSeg1 ConfirmationNo
145  3/7/2017          2    29083253
145  3/7/2017          1    29085100
145  3/7/2017          1    29085102
145  3/7/2017          1    29085106
145  3/7/2017          1    29084895
145  3/7/2017          1    29084953

df2 有 100,000 个数据点

  • ID2:分类变量有 400 多个类别
  • 日期 2:1 年数据
  • MST2:2 级变量 1/2
  • Conf No:唯一标识符

我想创建一个新变量,标记为 df1,当 df1 和 df2 中存在确认号时标记为 1,否则为 0

我通过以下方式实现了这一点:

combi1 <- sqldf("SELECT Distinct ID1,
            ExtractDate1,
            MktSeg1,
            ConfirmationNo,
            CASE
            WHEN confno IS NOT NULL
            THEN 1
            ELSE 0
            END AS 'Flag'
            FROM df1 
            LEFT JOIN df2  ON ID1 = ID2
            AND ExtractDate2 >= ExtractDate1
            AND ConfirmationNo = confno", drv = "SQLite")

要20-30多分钟才能出结果,有没有更好的办法?

我试过了

combi3 <- left_join(tbl_df(df1),tbl_df(df2),
                by = c("ID1" = "ID2" , "ExtractDate1" <= "ExtractDate2", "ConfirmationNo" = "ConfNo")) %>%
      select(distinct(ID1, ExtractDate1, MktSeg1, ConfirmationNo))

它抛出以下错误:

`by` can't contain join column `TRUE` which is missing from LHS

【问题讨论】:

  • 转换为 data.table setDT,然后设置 ID 列 setkey 的键,然后使用 %in%,如下面 MHammer 的帖子中所建议的那样。

标签: r dplyr data-manipulation sqldf


【解决方案1】:

将您提供的数据和与之类似的数据用于第二个数据框,您可以使用%in% 运算符:

df1 <- read.table(text = "ID1 ExtractDate1    MktSeg1 ConfirmationNo
145  3/7/2017          2    29083253
                  145  3/7/2017          1    29085100
                  145  3/7/2017          1    29085102
                  145  3/7/2017          1    29085106
                  145  3/7/2017          1    29084895
                  145  3/7/2017          1    29084953", header = TRUE)

df2 <- read.table(text = "ID1 ExtractDate1    MktSeg1 ConfirmationNo
145  3/7/2017          2    29083253
                  145  3/7/2017          1    29085106
                  145  3/7/2017          1    29084895
                  145  3/7/2017          1    29084953
                  145  3/7/2017          1    29084899
                  145  3/7/2017          1    29084959", header = TRUE)

df1$conf_flag <- as.numeric(df1$ConfirmationNo %in% df2$ConfirmationNo)
df1

【讨论】:

  • 这对我有用,它也很快。非常感谢。
【解决方案2】:

如果您想坚持使用sqldf,这可能不是最快的选择,那么您可以尝试重写您的查询以使用EXISTS

combi1 <- sqldf("SELECT ID1,
            ExtractDate1,
            MktSeg1,
            ConfirmationNo,
            CASE WHERE EXISTS (SELECT 1 FROM df2
                WHERE ID1 = ID2
                AND ExtractDate2 >= ExtractDate1
                AND ConfirmationNo = confno)
            THEN 1
            ELSE 0
            END AS Flag
            FROM df1", drv = "SQLite")

切换到EXISTS 意味着我们不必再使用DISTINCT。它还可以让我们取消左连接,因为逻辑可以在第一次匹配后停止扫描。

请注意,我们可以对实际数据库进行更多调整。对于sqldf,这可能是我们能做的。

【讨论】:

  • 我也试过了,但仍然需要更多时间。它也完成任务。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2016-07-28
  • 2014-04-23
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多