Как создать новый столбец с помощью изменения в пользовательской функции - PullRequest
0 голосов
/ 16 июня 2020

Я пытаюсь создать функцию, которая преобразует существующий столбец, используя case_when в функции mutate. Конечная цель - иметь возможность ввести имя таблицы и имя столбца, а затем добавить строку к имени существующего столбца, чтобы функция изменения создавала новый столбец. Спасибо!

my_function <- function(table_name, col_name) {
  table_name %>%
    mutate(paste("new_",col_name) = case_when(as.numeric(col_name) <=4 ~ -1,
                                as.numeric(col_name) > 4 & as.numeric(col_name) <= 8 ~ 0,
                                as.numeric(col_name) > 8 ~ 1))
  }

1 Ответ

0 голосов
/ 16 июня 2020

Вы погружаетесь в чудесный мир tidy-Assessment, где вам нужно ensym или enquo имена столбцов:

my_function <- function(table_name, col_name) {
    .col = ensym(col_name)
    table_name %>%
        mutate(!!paste0("new_", col_name) := case_when(as.numeric(!!.col) <=4 ~ -1,
                                                  as.numeric(!!.col) > 4 & as.numeric(!!.col) <= 8 ~ 0,
                                                  as.numeric(!!.col) > 8 ~ 1))
}

df = tibble(x=1:10)
my_function(df, "x")
# A tibble: 10 x 2
       x new_x
   <int> <dbl>
 1     1    -1
 2     2    -1
 3     3    -1
 4     4    -1
 5     5     0
 6     6     0
 7     7     0
 8     8     0
 9     9     1
10    10     1

Подробнее об этом можно узнать (включая операторы !! и :=) на Программирование с помощью dplyr виньетка.

В моем примере использовалось ensym и аргумент принимался как строка, чтобы придерживаться вашей функции. Однако чаще используется enquo и аргумент в качестве имени столбца:

my_function2 <- function(table_name, col_name) {
    .col = enquo(col_name)
    table_name %>%
        mutate(!!paste0("new_", quo_name(.col)) := case_when(as.numeric(!!.col) <=4 ~ -1,
                                                       as.numeric(!!.col) > 4 & as.numeric(!!.col) <= 8 ~ 0,
                                                       as.numeric(!!.col) > 8 ~ 1))
}
my_function2(df, x) #no quotes on the x!
# A tibble: 10 x 2
       x new_x
   <int> <dbl>
 1     1    -1
 2     2    -1
 3     3    -1
 4     4    -1
 5     5     0
 6     6     0
 7     7     0
 8     8     0
 9     9     1
10    10     1

Тем не менее, не следует ли вам лучше создать функцию, которая принимает число c и использовать его внутри mutate? Вот пример с dplyr v1.0.0:

my_function3 = function(x){
    case_when(as.numeric(x) <=4 ~ -1,
              as.numeric(x) > 4 & as.numeric(x) <= 8 ~ 0,
              as.numeric(x) > 8 ~ 1)
}
df %>% mutate(across(x, my_function3, .names="new_{col}"))
...