首先确定您在 R 中编程的环境很重要。您使用的是dplyr还是 base R?如果在dplyr中,请参考使用dplyr、rlang、glue和这个 stackoverflow 答案进行编程的文档。如果在基础 R 中,请参考有关 non-standard evaluation 的文档,尤其是将引用的列as.character(substitute())
包装在eval(substitute())
.
需要注意的是,上述两种方法都涉及非标准评估。另一种方法是使用标准评估(或标准评估和非标准评估的某种“组合”)。例如,请参阅此链接中提出的问题。
这个问题的原因至少部分来自环境混乱。以下是reprex 中的一些不同方法。
数据
my_df <-
data.frame(
matrix(
c(
"V9G","Blue",
NA,"Red",
"J4C","White",
NA,"Brown",
"F7B","Orange",
"G3V","Green"
),
nrow = 6,
ncol = 2,
byrow = TRUE,
dimnames = list(NULL,
c("color_code", "color"))
),
stringsAsFactors = FALSE
)
套餐
library(collapse)
library(dplyr)
library(stringr)
library(glue)
基础 R 中的函数式编程(非标准评估)
,带有引用的列名:
my_func <- function(df, col) {
col_char_ref <- as.character(substitute(col)) #Use as.character(substitute()) to refer to a quoted column name
df %>%
collapse::na_omit(cols = col_char_ref)
}
my_func(my_df, color_code)
#Should generate output below
my_df %>%
collapse::na_omit(cols = "color_code")
并使用未引用的列名:
my_func <- my_func <- function(df, col){
df <- df # This makes sure "df" is available inside the function environment where we evaluate the ftransform expression
eval(substitute(collapse::ftransform(df, count = stringr::str_length(col)))) # Wrap the function to be evaluated in eval(substitute())
}
my_func(my_df, color)
#Should generate output below
my_df %>%
collapse::ftransform(count = stringr::str_length(color))
使用胶水和dplyr函数在 dplyr(非标准评估)
中使用带引号的列名进行函数式编程 :
my_func <- function(df, col1, col2) {
df %>%
mutate(description := glue("color code: {pull(., {{col1}})}; color: {pull(., {{col2}})}"))
}
my_func(my_df, color_code, color)
#Should generate output below
my_df %>%
mutate(description = glue("color code: {color_code}; color: {color}"))
或使用 C 语言包装函数使用带引号的列名:
my_func <- function(df, col1, col2) {
df %>%
mutate(description := sprintf("color code: %s; color: %s", {{col1}}, {{col2}}))
}
my_func(my_df, color_code, color)
#Should generate output below
my_df %>%
mutate(description = glue("color code: {color_code}; color: {color}"))
并使用未引用的列名:
my_func <- function(df, col){
df %>%
dplyr::mutate(count = stringr::str_length({{ col }}))
}
my_func(my_df, color)
#Should generate output below
my_df %>%
dplyr::mutate(count = stringr::str_length(color))
更正产生错误的代码
以下产生错误的代码为以下两个示例提供了动机:
my_func <- function(df, col){
df <- df
df %>%
collapse::na_omit(cols = as.character(substitute(col))) %>%
eval(substitute(collapse::ftransform(description = stringr::str_length(col))))
}
my_func(my_df, color_code)
#Error in ckmatch(cols, nam) : Unknown columns: col
下面的示例是不会产生错误的替代方案。
基本 R 中的函数式编程(标准评估 - 要求列作为字符串在函数中传递)
library(pkgcond)
my_func <- function(df, col) {
if (!is.character(substitute(col)))
pkgcond::pkg_error("col must be a quoted string") #if users aren't used to quoted strings as inputs to a function
df <- na_omit(df, cols = col)
df$count <- stringr::str_length(.subset2(df, col))
df
}
my_func(my_df, "color_code")
#Should generate output below
my_df %>%
na_omit(cols = "color_code") %>%
ftransform(description = stringr::str_length("color_code"))
基础 R 中的函数式编程(标准评估和非标准评估的“组合”)
my_func <- function(df, col){
df <- df
df <- collapse::na_omit(df, cols = as.character(substitute(col))) # Unlike the code with the error, the function is not piped (using %>%)
eval(substitute(collapse::ftransform(df, description = stringr::str_length(col))))
}
my_func(my_df, color_code)
#Should generate output below
my_df %>%
na_omit(cols = "color_code") %>%
ftransform(description = stringr::str_length("color_code"))
可以在此链接中引用使用collapse包的更复杂的示例。