Оценка выражений внутри списков, переданных в качестве аргументов - PullRequest
0 голосов
/ 02 мая 2018

Предположим, я хочу создать новую таблицу из выражений, включающих столбцы из другой таблицы. Это довольно просто:

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]. 

1 Ответ

0 голосов
/ 03 мая 2018

Проще, чем я думал. Используйте 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
...