Я могу сделать функцию, которая принимает имена объектов в качестве аргументов (это просто нормальная функция).
Теперь я также могу сделать функцию, которая получает свои данные и аргументы столбца через именованный вектор (используя dataset <- eval(sym(dataset))
и date_col <- sym(date_col)
).
Однако я хотел бы функцию, которая может обрабатывать оба типа входов.
Шаг первый - определить класс входа.
Для аргумента набора данных это (ниже) прекрасно работает как для именованного вектора, так и для фактического имени объекта.
if (is.character(dataset)) {
dataset <- eval(sym(dataset)) }
Я не могу найти подходящий способ обработки Аргументы столбцов, однако.
Когда я использую для них элементы именованных векторов, процесс (ниже) работает нормально.
if (is.character(date_col)) {
date_col <- sym(date_col) }
Но я не уверен, как обращаться с фактическим именем столбца (ie путем добавления компонента else
, выше). По сути, я хочу превратить его в sym, чтобы я все еще мог использовать {{}} (или !!) в шагах функции.
Вот минимальный воспроизводимый пример того, что я хочу. Как вы увидите, работает именованная векторная версия, но не фактический набор данных и имена столбцов.
Возможно ли то, что я хочу после? Может ли функция быть динамической c таким образом, или мне нужно сделать две отдельные функции?
[отредактировано: сделал более простой пример, согласно комментарию]
library(dplyr)
library(rlang)
new_table <- tibble(
Date = seq.Date(as.Date("2016-01-01"), as.Date("2019-12-31"), 1)) %>%
mutate(total_sales = rnorm(n()))
f_arguments <- c("dataset" = "new_table",
"date_col" = "Date",
"sales_col" = "total_sales")
f <- function(data, x, envir = parent.frame()) {
if (is.character(data)) {
data <- get(data, envir)}
if (is.character(x)) {
x <- sym(x) }
data %>%
mutate(year_month = lubridate::floor_date(!!ensym(x), "months"),
year = lubridate::year(!!ensym(x)))
}
# this (below) works per the above code, but not if I comment out
# the if (is.character(x)) line
f(f_arguments[["dataset"]],
f_arguments[["date_col"]])
# this (below) does not work with the above code, but it will work if I comment out
# the if (is.character(x)) line
f(new_table, Date)