【问题标题】:Avoid arithmetic overflow error when using dbplyr使用 dbplyr 时避免算术溢出错误
【发布时间】:2021-07-07 00:11:11
【问题描述】:

这个问题与this one 类似,但概括起来,所以发布的答案不太合适。数据是这样的,一行标识一个单位时间对:

large_sql_df
id   t   var1   var2
1    1    10     0
1    2    20     1
2    1    11     0

我想按var2 和时间t 汇总:

localdf <- large_sql_df %>%
     group_by(var, t) %>%
     summarise(count = n(), var1_mean = mean(var1))

这给出了错误:“将表达式转换为数据类型 int 的算术溢出错误。”我认为这是因为count 成为一个非常大的数字。有没有办法阻止这种情况发生,而不必在 SQL 中执行整个查询?

【问题讨论】:

    标签: r dbplyr


    【解决方案1】:

    算术溢出限制为 2,147,483,647(请参阅here),因此这可能不是由计数引起的。它更有可能是由mean(var1) 引起的,因为要计算平均值,计算机首先必须计算sum(var1)。如果您的 var1 列通常包含大于 40 的值,则可能会出现溢出错误 (40 * 350,000,000 > 2,147,483,647)。

    here 的解决方案也与您的问题相关:将 var1 显式转换为更合适的格式。类似于以下内容:

    localdf <- large_sql_df %>%
         mutate(var1 = CAST(var1 AS FLOAT)) %>% 
         group_by(var, t) %>%
         summarise(count = n(), var1_mean = mean(var1))
    

    根据您的 dbplyr 版本,您可能需要 mutate(var1 = sql("CAST(var1 AS FLOAT)")) 之类的内容。

    有关不同数据类型的讨论,请参阅this 问题。虽然 float 是一种不精确的数据类型,但它可以处理高达 10E38 的数字。如果您对如此大的总数取平均值,那么引入的印象不太可能很重要。

    【讨论】:

      【解决方案2】:

      这只是详细说明了@simon-s-a 答案的一些要素:

      library(dplyr, warn.conflicts = FALSE)
      
      df <- read.table(header = TRUE, text = "
      id   t   var1   var2
      1    1    10     0
      1    2    20     1
      2    1    11     0")
      
      large_sql_df <- dbplyr::tbl_memdb(df)
      
      localdf <- 
        large_sql_df %>%
        mutate(var1 = as.double(var1)) %>% 
        group_by(var2, t) %>%
        summarise(count = n(), var1_mean = mean(var1, na.rm = TRUE),
                  .groups = "drop")
      
      localdf
      #> # Source:   lazy query [?? x 4]
      #> # Database: sqlite 3.35.5 [:memory:]
      #>    var2     t count var1_mean
      #>   <int> <int> <int>     <dbl>
      #> 1     0     1     2      10.5
      #> 2     1     2     1      20
      
      localdf %>% show_query()
      #> <SQL>
      #> SELECT `var2`, `t`, COUNT(*) AS `count`, AVG(`var1`) AS `var1_mean`
      #> FROM (SELECT `id`, `t`, CAST(`var1` AS REAL) AS `var1`, `var2`
      #> FROM `df`)
      #> GROUP BY `var2`, `t`
      

      reprex package (v2.0.0) 于 2021-07-07 创建

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-23
        相关资源
        最近更新 更多