r 中比 sqldf 更快的任何其他进程

Any other process faster than sqldf in r

我有 2 个数据框

df1 有 700,000 个数据点

示例数据:

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 个数据点

我想创建一个新变量,标记为 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

将您提供的数据和类似的数据用于第二个数据框,您可以使用 %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

如果您想坚持使用 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,这可能是我们所能做的。