【问题标题】:R dbplyr mysql column conversionR dbplyr mysql 列转换
【发布时间】:2021-08-27 14:05:33
【问题描述】:

我在 mySQL 中有一个如下所示的表:

tbl<-tibble(
   Result=c("0.1","<0.0001","1.1"),
   Unit=c("mg/L","ug/L","mg/L"),
   Pref_Unit=c("mg/L","mg/L","mg/L"),
   Conversion=c(1,1000,1)
)

我想使用dbplyrpoolRMariaDB 做的是使用表中的转换因子将Result 列转换为首选单位,同时保留“numeric 分数和 censored 指示 Result 是否包含“

对于普通的dplyr,我会做这样的事情:

tbl<-tbl %>%
    mutate(numb_Result=as.numeric(gsub("<","",Result)),
           cen_Result=grepl("<",Result)) %>%
    mutate(new_Result=ifelse(cen_Result,paste0("<",numb_Result*Conversion),paste0(numb_Result*Conversion)))

但这不适用于数据库表。任何帮助将不胜感激。

【问题讨论】:

    标签: mysql r dplyr dbplyr


    【解决方案1】:

    这个挑战很可能是因为 dbplyr 没有为 gsubgrepl 定义翻译。您可以在下面测试几种可能性:

    library(dplyr)
    library(dbplyr)
    
    tbl<-tibble(
      Result=c("0.1","<0.0001","1.1"),
      Unit=c("mg/L","ug/L","mg/L"),
      Pref_Unit=c("mg/L","mg/L","mg/L"),
      Conversion=c(1,1000,1)
    )
    
    remote_table = tbl_lazy(tbl, con = simulate_mssql())
    
    remote_table %>%
      mutate(has_sign = ifelse(substr(Result, 1, 1) == "<", 1, 0)) %>%
      mutate(removed_sign = ifelse(has_sign == 1, substr(Result, 2, nchar(Result)), Result)) %>%
      mutate(num_value = as.numeric(removed_sign)) %>%
      mutate(converted = as.character(1.0 * num_value * Conversion)) %>%
      mutate(new_Result = ifelse(has_sign, paste0("<",converted), converted))
    

    ifelsesubstrncharas.numericas.characterpaste0 的 dbplyr 翻译。所以我希望这能奏效。但是,我不断收到错误,因为翻译器需要 substrstartstop 参数是常量,因此它不喜欢我将 nchar(Results) 作为参数传递。但这可能会在更新版本的软件包中得到修复。

    我的第二次尝试:

    remote_table %>%
      mutate(has_sign = ifelse(substr(Result, 1, 1) == "<", 1, 0),
             character_length = nchar(Result),
             remove_first = sql(REPLACE(Result, "<", ""))) %>%
      mutate(removed_sign = ifelse(has_sign == 1, remove_first, Result)) %>%
      mutate(num_value = as.numeric(removed_sign)) %>%
      mutate(converted = as.character(1.0 * num_value * Conversion)) %>%
      mutate(new_Result = ifelse(has_sign, paste0("<",converted), converted))
    

    这会产生预期的 SQL 转换。但是由于我使用的是模拟数据库连接,所以我无法测试它是否返回预期的输出。这种方法的缺点是它直接使用了 SQL 函数REPLACE(它将未翻译的内容传递到 SQL 代码中),这不如完全翻译的解决方案优雅。

    可能有更优雅的方法可以做到这一点。但希望您能在这两者之间找到合适的解决方案。

    【讨论】:

      【解决方案2】:

      谢谢西蒙!

      我找到了一个类似的解决方案,它确实适用于实际的 SQL 数据库环境(请注意,我还必须将列名作为变量 result_col 传递,因此使用 !!sym()):

      tbl %>%
      mutate(numb_res = REGEXP_REPLACE(!!sym(result_col),"<",""), 
             cen_res = !!sym(result_col) %like% "<%") %>%
            mutate(numb_res=numb_res*Conversion) %>%
            mutate(!!result_col:=case_when(
              cen_res==1 ~ paste0("<",numb_res),
              T ~ paste0(numb_res)
            ))
      

      您似乎是正确的,as.character()as.numeric() 没有 SQL 翻译,但只需对字符向量进行乘法就足以使其成为数字,同样,用“

      我认为这对我有用,但我也会调查你的答案。

      【讨论】:

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