3

Suppose I want to create a new table from expressions involving columns from another table. That's pretty easy:

library(rlang)
library(purrr)

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

Example:

> 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  

Now I need to evaluate expressions coming not from ... but from lists. I want a new function, from_exprs2() such that a call like

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

returns two tables, one for each list of expressions. The previous strategy does not work:

> 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]. 
Luiz Rodrigo
  • 936
  • 1
  • 7
  • 19

1 Answers1

1

Easier than I thought. Use enquo()to capture the expression and eval_tidy() to evaluate as a list. After that, just convert it to a data frame.

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)))

Output:

[[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
Luiz Rodrigo
  • 936
  • 1
  • 7
  • 19