Использование использования имен переменных в функциях при использовании mutate_at - PullRequest
4 голосов
/ 23 апреля 2019

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

В частности, я хочу определить функцию

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

Я довольно новичок в использовании кавычек и тому подобного с dplyr. До сих пор я пробовал следующее:

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

но я не знаю, что должно заменить ? выше. Решение работает, если отсечка одинакова для всех переменных, но не в том случае, если отсечка зависит от переменной.

Заранее благодарю за помощь.

1 Ответ

1 голос
/ 24 апреля 2019

Вот один вариант с map2 и transmute

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

                                 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...