【问题标题】:Evaluating expressions inside lists passed as arguments评估作为参数传递的列表中的表达式
【发布时间】:2023-06-09 19:40:01
【问题描述】:

假设我想从涉及另一个表中的列的表达式创建一个新表。这很简单:

library(rlang)
library(purrr)

from_exprs = function(tb, ...) {
  quos(...) %>% 
    map_dfc(~ eval_tidy(., tb)) 
}

例子:

> tb = data.frame(year = 2001:2005, month = 1, names = letters[1:5])
> tb
  year month names
1 2001     1     a
2 2002     1     b
3 2003     1     c
4 2004     1     d
5 2005     1     e
> from_exprs(tb, year + month, toupper(names))
# A tibble: 5 x 2
     V1 V2   
  <dbl> <chr>
1  2002 A    
2  2003 B    
3  2004 C    
4  2005 D    
5  2006 E  

现在我需要评估不是来自... 而是来自列表的表达式。我想要一个新函数,from_exprs2(),这样的调用就像

from_exprs2(tb, 
  Y = list(year + month, year - month), 
  Z = list(toupper(names), tolower(names))
)

返回两个表,每个表对应一个表达式列表。以前的策略不起作用:

> from_exprs2 = function(tb, Y, Z) {
+     tb_y = quos(Y) %>% 
+         map_dfc(~ eval_tidy(., tb)) 
+     tb_z = quos(Z) %>% 
+         map_dfc(~ eval_tidy(., tb))
+     list(tb_y, tb_z)
+ }
> from_exprs(tb, Y = list(year + month, year - month), Z = list(toupper(names), tolower(names)))
 Show Traceback

 Rerun with Debug
 Error in cbind_all(x) : Not compatible with STRSXP: [type=NULL]. 

【问题讨论】:

    标签: r dplyr tidyverse rlang


    【解决方案1】:

    比我想象的要容易。使用enquo() 捕获表达式并使用eval_tidy() 作为列表进行评估。之后,只需将其转换为数据框即可。

    from_exprs2 = function(tb, Y, Z) {
        tb_y = enquo(Y) %>%
            eval_tidy(tb) %>%
            as.data.frame
    
        tb_z = enquo(Z) %>%
            eval_tidy(tb) %>%
            as.data.frame
    
        list(tb_y, tb_z)
    }
    
    from_exprs2(tb, 
                Y = list(year + month, year - month), 
                Z = list(toupper(names), tolower(names)))
    

    输出:

    [[1]]
      c.2002..2003..2004..2005..2006. c.2000..2001..2002..2003..2004.
    1                            2002                            2000
    2                            2003                            2001
    3                            2004                            2002
    4                            2005                            2003
    5                            2006                            2004
    
    [[2]]
      c..A....B....C....D....E.. c..a....b....c....d....e..
    1                          A                          a
    2                          B                          b
    3                          C                          c
    4                          D                          d
    5                          E                          e
    

    【讨论】:

      最近更新 更多