Простой пример аккуратного вычисления формул

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

У меня есть следующая функция

add_predictions <- function(data, model_exp){
  enquo_model_exp <- enquo(model_exp)
  fit <- data %>% as_tibble()  %>% !!enquo_model_exp
  data[[preds]] <- stats::predict(fit, data)
}

Вышеупомянутая функция включает следующие шаги

  1. enquo формула

  2. соответствовать модели с данными и отменять формулу с помощью !!

  3. прогнозировать, используя подобранную модель на данных

Пример использования этой функции будет примерно таким.

cars %>% 
  as_tibble() %>% 
  add_predictions(lm(speed ~ dist, data = .))

person Alex    schedule 13.07.2018    source источник


Ответы (1)


Передавать формулы в качестве аргументов просто, и я бы не рекомендовал для этого аккуратную оценку. Я бы сделал это следующим образом (используя немного tidyeval для нового имени столбца):

library(tidyverse)

add_predictions <- function(.data, formula,
                            .fun = lm, col = pred) {
  col <- enquo(col)
  col <- quo_name(col)
  mod <- .fun(formula = formula, data = .data)
  mutate(.data, !! col := predict(mod))
}

cars %>% 
  add_predictions(speed ~ dist, col = speed_pred) 

#    speed dist speed_pred
# 1      4    2   8.615041
# 2      4   10   9.939581
# 3      7    4   8.946176
# 4      7   22  11.926392
# 5      8   16  10.932987
# 6      9   10   9.939581
# 7     10   18  11.264122
# 8     10   26  12.588663
# 9     10   34  13.913203
# 10    11   17  11.098554
# ...

Теперь я понимаю, что вы хотите использовать аккуратную оценку в качестве упражнения. Используя желаемую подпись функции:

add_predictions_2 <- function(.data, model_exp, col = pred) {
  col <- enquo(col)
  col <- quo_name(col)
  model_exp <- enquo(model_exp)
  mod <- rlang::eval_tidy(model_exp, data = list(. = .data))
  mutate(.data, !! col := predict(mod))
}

cars %>% 
  as_tibble() %>% 
  add_predictions_2(lm(speed ~ dist, data = .))

# # A tibble: 50 x 3
#    speed  dist  pred
#    <dbl> <dbl> <dbl>
#  1     4     2  8.62
#  2     4    10  9.94
#  3     7     4  8.95
#  4     7    22 11.9 
#  5     8    16 10.9 
#  6     9    10  9.94
#  7    10    18 11.3 
#  8    10    26 12.6 
#  9    10    34 13.9 
# 10    11    17 11.1 
# # ... with 40 more rows
person Aurèle    schedule 16.07.2018
comment
Функция := для меня нова. Не могли бы вы объяснить, как это работает? Кроме того, как узнать, что должно быть перед знаком .. Если .s представляют переменные, которые передаются в функцию, то не будут ли все переменные разделены точками (.data, .model_exp, .col)? - person Alex; 16.07.2018
comment
Аурель, вероятно, сможет объяснить более полно, но .data - это особое местоимение в rlang. Нет общего . оператора. И := - это обходной путь для того факта, что вы не можете убрать кавычки с !! перед знаком = в R, поэтому вы просто вставляете :=, когда хотите это сделать. - person Calum You; 17.07.2018
comment
@CalumВы правы. Имена с префиксом точки в R не имеют особого значения или свойств (за исключением того, что они скрыты по умолчанию, например, когда вы делаете ls()). Использование префикса . - это произвольный выбор, сделанный путем имитации того, что кажется нормой в тидиверсе. := - это именно то, что описывает @CalumYou, и обоснование представлено здесь cran.r-project.org/web/packages/dplyr/vignettes/, подробнее см. rlang.r-lib.org/reference/quasiquotation.html - person Aurèle; 18.07.2018