从命名向量 -rlang 问题将数据集和列参数添加到函数中
Adding dataset and column arguments into a function from a named vector -rlang question
我有一系列函数可以制作一些 ggplot2 图表。
我有一个新数据集,我想在上面使用这些函数来制作图表。
这个新数据集对函数需要的列有自己唯一的名称。
我也有可能在未来获得额外的新数据集(具有自己不同的列名)。
我正在考虑创建一个命名向量,在其中指定要使用的新数据集的列名(以及新数据集对象本身的名称),我可以将这个命名向量的值赋予每个函数。
这是我正在谈论的一个最小可重现的例子。
我知道它会涉及 !!、enquo、sym 的某种组合...但我已经尝试过 heaps,看起来我被打败了。
此外,我想在不改变函数的情况下执行此操作(即我仍然希望通过直接输入数据集/列对象名称来使用这些函数)。
library(tidyverse)
library(rlang)
# make a dataset
dif_data_name <- tibble(dif_col_name = 1:50)
# a function that only utilises a dataset
test_function_only_data <- function(dataset) {
dataset %>%
pull() %>%
sum()
}
# a function that utilises the dataset and a specific column
test_function_with_col <- function(dataset, only_column) {
only_column <- enquo(only_column)
dataset %>%
pull(!! only_column) %>%
sum()
}
# If I specify the datset object, this works
test_function_only_data(dif_data_name)
# so does this (with the column name as well)
test_function_with_col(dif_data_name, dif_col_name)
# But I was hoping to use a named vector for the dataset and column arguments
function_arguments <- c("dataset" = "dif_data_name",
"only_column" = "dif_col_name")
# These (below) do not work. But I would like to figure out how to make them work.
# first function test
test_function_only_data(
function_arguments[["dataset"]]
)
# second function test
test_function_with_col(function_arguments[["dataset"]],
function_arguments[["only_column"]])
更新(根据 OP 评论)
这是一个完整的示例,使用了此评论线程中要点中发布的数据。
set.seed(123)
new_table <- tibble(
Date = seq.Date(as.Date("2016-01-01"), as.Date("2019-12-31"), 1)
) %>%
mutate(total_sales = rnorm(n()))
new_yearly_lines_fn <- function(sales_table, date_col, money_col) {
date_col <- sym(date_col)
money_col <- sym(money_col)
sales_table <- eval(sym(sales_table))
sales_table %>%
group_by(year_month = floor_date({{date_col}}, "months"),
year = year({{date_col}})) %>%
summarise(total_sales = sum({{money_col}})) %>%
ungroup() %>%
ggplot() +
aes(year_month, total_sales, col = factor(year)) +
geom_line(stat = "identity", size = 2) +
geom_point(stat = "identity", size = 2, col = "black")
}
function_arguments <- c("the_dataset" = "new_table",
"the_date_col" = "Date",
"the_money_col" = "total_sales")
new_yearly_lines_fn(function_arguments[["the_dataset"]],
function_arguments[["the_date_col"]],
function_arguments[["the_money_col"]])
FWIW,有更简单的方法可以将您想要的信息传递到具有整洁评估的函数中。但是这里是你如何用你的命名向量来做的:
f <- function(named) {
df_str <- named[["dataset"]]
col_str <- named[["only_column"]]
dataset <- eval(sym(df_str))
dataset %>%
pull({{col_str}}) %>%
sum()
}
f(function_arguments)
# 1275
传入 function_arguments
的各个组件的变体也将起作用:
f2 <- function(df_str, col_str) {
col <- sym(col_str)
dataset <- eval(sym(df_str))
dataset %>%
pull({{col_str}}) %>%
sum()
}
f2(function_arguments[["dataset"]], function_arguments[["only_column"]])
# 1275
请注意,从 rlang
. 0.4.0 开始,!!
符号现在已替换为 {{ }}
符号。
我有一系列函数可以制作一些 ggplot2 图表。
我有一个新数据集,我想在上面使用这些函数来制作图表。
这个新数据集对函数需要的列有自己唯一的名称。
我也有可能在未来获得额外的新数据集(具有自己不同的列名)。
我正在考虑创建一个命名向量,在其中指定要使用的新数据集的列名(以及新数据集对象本身的名称),我可以将这个命名向量的值赋予每个函数。
这是我正在谈论的一个最小可重现的例子。
我知道它会涉及 !!、enquo、sym 的某种组合...但我已经尝试过 heaps,看起来我被打败了。
此外,我想在不改变函数的情况下执行此操作(即我仍然希望通过直接输入数据集/列对象名称来使用这些函数)。
library(tidyverse)
library(rlang)
# make a dataset
dif_data_name <- tibble(dif_col_name = 1:50)
# a function that only utilises a dataset
test_function_only_data <- function(dataset) {
dataset %>%
pull() %>%
sum()
}
# a function that utilises the dataset and a specific column
test_function_with_col <- function(dataset, only_column) {
only_column <- enquo(only_column)
dataset %>%
pull(!! only_column) %>%
sum()
}
# If I specify the datset object, this works
test_function_only_data(dif_data_name)
# so does this (with the column name as well)
test_function_with_col(dif_data_name, dif_col_name)
# But I was hoping to use a named vector for the dataset and column arguments
function_arguments <- c("dataset" = "dif_data_name",
"only_column" = "dif_col_name")
# These (below) do not work. But I would like to figure out how to make them work.
# first function test
test_function_only_data(
function_arguments[["dataset"]]
)
# second function test
test_function_with_col(function_arguments[["dataset"]],
function_arguments[["only_column"]])
更新(根据 OP 评论)
这是一个完整的示例,使用了此评论线程中要点中发布的数据。
set.seed(123)
new_table <- tibble(
Date = seq.Date(as.Date("2016-01-01"), as.Date("2019-12-31"), 1)
) %>%
mutate(total_sales = rnorm(n()))
new_yearly_lines_fn <- function(sales_table, date_col, money_col) {
date_col <- sym(date_col)
money_col <- sym(money_col)
sales_table <- eval(sym(sales_table))
sales_table %>%
group_by(year_month = floor_date({{date_col}}, "months"),
year = year({{date_col}})) %>%
summarise(total_sales = sum({{money_col}})) %>%
ungroup() %>%
ggplot() +
aes(year_month, total_sales, col = factor(year)) +
geom_line(stat = "identity", size = 2) +
geom_point(stat = "identity", size = 2, col = "black")
}
function_arguments <- c("the_dataset" = "new_table",
"the_date_col" = "Date",
"the_money_col" = "total_sales")
new_yearly_lines_fn(function_arguments[["the_dataset"]],
function_arguments[["the_date_col"]],
function_arguments[["the_money_col"]])
FWIW,有更简单的方法可以将您想要的信息传递到具有整洁评估的函数中。但是这里是你如何用你的命名向量来做的:
f <- function(named) {
df_str <- named[["dataset"]]
col_str <- named[["only_column"]]
dataset <- eval(sym(df_str))
dataset %>%
pull({{col_str}}) %>%
sum()
}
f(function_arguments)
# 1275
传入 function_arguments
的各个组件的变体也将起作用:
f2 <- function(df_str, col_str) {
col <- sym(col_str)
dataset <- eval(sym(df_str))
dataset %>%
pull({{col_str}}) %>%
sum()
}
f2(function_arguments[["dataset"]], function_arguments[["only_column"]])
# 1275
请注意,从 rlang
. 0.4.0 开始,!!
符号现在已替换为 {{ }}
符号。