【问题标题】:eval formula objects in data.table评估 data.table 中的公式对象
【发布时间】:2021-03-17 15:35:33
【问题描述】:

根据这个answer,可以在data.table中使用文本公式

set.seed(1)
foo = data.table(var1=sample(1:3,1000,r=T), var2=rnorm(1000),  var3=sample(letters[1:5],1000,replace = T))
var_i="var1"
var_j="var1+0.02*exp(var2)"
var_by="var3"
eval_text_formula <- function(s, env) eval(parse(text=s), envir = env, enclos = parent.frame())
foo[var1 == 1, sum(eval_text_formula(var_j, .SD)), by = var3]


   var3       V1
1:    d 72.74060
2:    e 77.10872
3:    c 69.48776
4:    b 84.22668
5:    a 58.53409

我想扩展这个回答如果我传递一个公式对象会发生什么

var_j=as.formula("~var1+0.02*exp(var2)")

> foo[var1 == 1, sum(eval_text_formula(var_j, .SD)), by = var3]
Error in sum(eval_text_formula(var_j, .SD)) : 
  'type' (language) de argumento no válido

我发现的草率和粗略的解决方案是将公式重新转换为字符串var_j=as.character(var_j)

> var_j=as.formula("~var1+0.02*exp(var2)")
> var_j=as.character(var_j)
> var_j
[1] "~"                       "var1 + 0.02 * exp(var2)"
> var_j=var_j[2]
> foo[var1 == 1, sum(eval_text_formula(var_j, .SD)), by = var3]
   var3       V1
1:    d 72.74060
2:    e 77.10872
3:    c 69.48776
4:    b 84.22668
5:    a 58.53409

我觉得我缺少一个概念。

【问题讨论】:

    标签: r data.table rlang


    【解决方案1】:

    似乎更安全地抓住公式的 RHS 方面使用

    var_j2 <- tail(as.character(f), 1)
    

    尽管我们再次强制转换公式对象。

    【讨论】:

      【解决方案2】:

      一个选项是转换为字符并删除~

      var_j2 <- sub("~", "", deparse(var_j))
      foo[var1 == 1, sum(eval_text_formula(var_j2, .SD)), by = var3]
      #   var3       V1
      #1:    d 72.74060
      #2:    e 77.10872
      #3:    c 69.48776
      #4:    b 84.22668
      #5:    a 58.53409
      

      或将公式拆分为listas.list 并选择第二个组件,转换为characterdeparse

      foo[var1 == 1, sum(eval_text_formula(deparse(as.list(var_j)[[2]]), .SD)), by = var3]
      #   var3       V1
      #1:    d 72.74060
      #2:    e 77.10872
      #3:    c 69.48776
      #4:    b 84.22668
      #5:    a 58.53409
      

      使用tidyverse,可以将公式转换为as_quosure(来自rlang)的quosure并进行评估(!!

      library(rlang)
      library(dplyr)
      foo %>% 
         filter(var1 == 1) %>%
         group_by(var3) %>%
         summarise(val = sum(!! as_quosure(var_j)))
      # A tibble: 5 x 2
      #   var3    val
      #* <chr> <dbl>
      #1 a      58.5
      #2 b      84.2
      #3 c      69.5
      #4 d      72.7
      #5 e      77.1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-09
        • 2022-01-20
        • 1970-01-01
        • 2012-11-12
        • 1970-01-01
        • 2023-01-12
        相关资源
        最近更新 更多