使用mutate_at时在函数中使用变量名

时间:2019-04-23 20:26:18

标签: r dplyr mutate

我想创建一个函数,可以根据用户提供的输入变量和截止值列表以编程方式添加变量。

具体地说,我想定义一个函数

myfun <- function(df, varlist, cutofflist)

df中的每个变量返回一个额外的列varlist,其中包含每个变量是否最多为对应的截止值的逻辑。

例如,假设我们采用虹膜数据框,

df <- as_tibble(iris)
# A tibble: 150 x 1
   iris$Sepal.Length $Sepal.Width $Petal.Length $Petal.Width $Species
               <dbl>        <dbl>         <dbl>        <dbl> <fct>   
 1               5.1          3.5           1.4          0.2 setosa  
 2               4.9          3             1.4          0.2 setosa  
 3               4.7          3.2           1.3          0.2 setosa  
 4               4.6          3.1           1.5          0.2 setosa  
 5               5            3.6           1.4          0.2 setosa  
 6               5.4          3.9           1.7          0.4 setosa  
 7               4.6          3.4           1.4          0.3 setosa  
 8               5            3.4           1.5          0.2 setosa  
 9               4.4          2.9           1.4          0.2 setosa  
10               4.9          3.1           1.5          0.1 setosa  
# ... with 140 more rows

我想打个电话

myfun(df, c("Sepal.Length", "Petal.Length"), list(Sepal.Length = 5, Petal.Length = 1.5))

产生与

相同的结果
df %>%
   mutate(
      Sepal.Length_indicator = (Sepal.Length <= 5),
      Petal.Length_indicator = (Petal.Length <= 1.5)
   )

即这个:

# A tibble: 150 x 7
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_indicator Petal.Length_indicator
          <dbl>       <dbl>        <dbl>       <dbl> <fct>   <lgl>                  <lgl>                 
 1          5.1         3.5          1.4         0.2 setosa  FALSE                  TRUE                  
 2          4.9         3            1.4         0.2 setosa  TRUE                   TRUE                  
 3          4.7         3.2          1.3         0.2 setosa  TRUE                   TRUE                  
 4          4.6         3.1          1.5         0.2 setosa  TRUE                   TRUE                  
 5          5           3.6          1.4         0.2 setosa  TRUE                   TRUE                  
 6          5.4         3.9          1.7         0.4 setosa  FALSE                  FALSE                 
 7          4.6         3.4          1.4         0.3 setosa  TRUE                   TRUE                  
 8          5           3.4          1.5         0.2 setosa  TRUE                   TRUE                  
 9          4.4         2.9          1.4         0.2 setosa  TRUE                   TRUE                  
10          4.9         3.1          1.5         0.1 setosa  TRUE                   TRUE                  
# ... with 140 more rows

我在使用quosures和dplyr之类的东西时非常陌生。到目前为止,我正在尝试以下操作:

myfun <- function(df, varlist, cutofflist){
  df %>%
    mutate_at(.vars = varlist, .funs = list(indicator = function(x) x<= cutofflist[[?]]))
}

但是我不知道应该替换上面的?。如果所有变量的临界值都相同,则该解决方案有效,但如果临界值取决于变量,则解决方案无效。

预先感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

这里是map2transmute的一个选项

library(tidyverse)
myfun <- function(data, varVec, cutofflist) {
    map2_dfc(varVec, cutofflist[varVec], ~   

                     data %>% 
                        transmute( !! paste0(.x, "_indicator") := 
                               !! rlang::sym(.x) <= .y)) %>%
                 bind_cols(df, .)

     }


out2 <- myfun(df, c("Sepal.Length", "Petal.Length"), 
        list(Sepal.Length = 5, Petal.Length = 1.5))   

-通过在函数外部运行来检查输出

out1 <- df %>%
         mutate(
           Sepal.Length_indicator = (Sepal.Length <= 5),
           Petal.Length_indicator = (Petal.Length <= 1.5)
          )    

identical(out1, out2)
#[1] TRUE

或者也可以用map完成,因为'varVec'和'cutofflist'名称相同

myfun <- function(data, varVec, cutofflist) {
    map_dfc(varVec, ~   

                        data %>% 
                                  transmute( !! paste0(.x, "_indicator") := 
            !! rlang::sym(.x) <= cutofflist[[.x]])



                                 ) %>%
           bind_cols(df, .)

                                 }