dplyr 0.7 tidy eval:将字符变量转换为因子
dplyr 0.7 tidy eval: convert character variables to factors
我有一个包含很多变量的数据集,其中一些是字符变量,我想将其转换为因子。由于有许多变量要转换,我想使用 dplyr_0.7
中新的 tidy eval 功能来完成此操作。这是我的数据中的一个最小示例:
data <- data.frame(factor1 = c("K", "V"),
factor2 = c("E", "K"),
other_var = 1:2,
stringsAsFactors = FALSE)
我有一个命名列表,其中包含我要转换的每个变量的 data.frame
。列表中的这些 data.frame
都具有相同的结构,可以在这个例子中看到:
codelist_list <- list(factor1 = data.frame(Code = c("K", "V"),
Bezeichnung = c("Kauf", "Verkauf"),
stringsAsFactors = FALSE),
factor2 = data.frame(Code = c("E", "K"),
Bezeichnung = c("Eigengeschaeft", "Kundengeschaeft"),
stringsAsFactors = FALSE))
我不是想做的是为每个变量定义这样的因子:
mutate(df, factor1 = factor(factor1,
levels = codelist_list[["factor1"]][["Code"]],
labels = codelist_list[["factor1"]][["Bezeichnung"]]))
到目前为止我尝试过的是:
convert_factors <- function(variable, df) {
factor_variable <- enquo(variable)
df %>%
mutate(!!quo_name(factor_variable) := factor(!!quo_name(factor_variable),
levels = codelist_list[[variable]][["Code"]],
labels = codelist_list[[variable]][["Bezeichnung"]]))
}
第一步,我想通过调用 convert_factors("factor1", data)
来检查我的函数 convert_factors()
是否正常工作,其中 returns
factor1 factor2 other_var
1 <NA> E 1
2 <NA> K 2
变量不显示值标签,而是替换为 NA
。
最终目标是 map
我要转换的所有变量。在这里,我尝试了 map(c("factor1", "factor2"), convert_factors, df = data)
,它返回了
Error in (function (x, strict = TRUE) : the argument has already been evaluated
我试图按照 http://dplyr.tidyverse.org/articles/programming.html 的说明进行操作,但这就是我想出的全部。
有谁知道问题出在哪里(并希望向我解释我的错误)。
我认为你混淆了 quosures 和字符串:
在你的函数中,variable
是一个字符串,不是表达式。所以你应该把它转换成 rlang::sym
,而不是 enquo
.
quo_name
用于将表达式转换为字符串。由于 variable
已经是一个字符串,您可以直接在 mutate
.
中的 rhs(右侧)上执行 !!variable
at lhs in mutate
你需要用 !!
取消引用 factor_variable
而不是试图用 quo_name
将它转换成字符串。
更正上述错误后,您的功能将正常工作:
convert_factors <- function(variable, df) {
factor_variable <- rlang::sym(variable)
df %>%
mutate(!!variable := factor(
!!factor_variable,
levels = codelist_list[[variable]][["Code"]],
labels = codelist_list[[variable]][["Bezeichnung"]]))
}
# > convert_factors('factor1', data)
# factor1 factor2 other_var
# 1 Kauf E 1
# 2 Verkauf K 2
这是我的尝试:
params <- lapply(codelist_list, setNames, nm = c('levels', 'labels'))
convert_factors <- function(variable, df) {
factor_variable <- rlang::sym(variable)
factor_param <- c(list(factor_variable), params[[variable]])
df %>% mutate(!!variable := do.call(factor, factor_param))
}
convert_factors('factor1', data)
# factor1 factor2 other_var
# 1 Kauf E 1
# 2 Verkauf K 2
使用 tidy eval 和 dplyr 的 mt1022 的很好的解决方案。然而,这个任务可以只使用 base-R 来完成:
data[,names(codelist_list)] <- lapply(names(codelist_list), function(x)
data[,x] <- factor(data[,x],
levels = codelist_list[[x]][["Code"]],
labels = codelist_list[[x]][["Bezeichnung"]]))
您可以使用 mutate_at
来解决这个问题,使用 funs
中的 .
编码一次将函数应用于多个列。
这种方法仍然涉及使用 tidyeval
从 codelist_list
中提取正确的列表,同时通过 .
.
引用变量
mutate_at(data, c("factor1", "factor2"),
funs( factor(., levels = codelist_list[[quo_name(quo(.))]][["Code"]],
labels = codelist_list[[quo_name(quo(.))]][["Bezeichnung"]]) ) )
factor1 factor2 other_var
1 Kauf Eigengeschaeft 1
2 Verkauf Kundengeschaeft 2
如果您想创建一个函数传递给 mutate_at
,您可以这样做,只需稍作改动即可。
convert_factors = function(variable) {
var2 = enquo(variable)
factor(variable, levels = codelist_list[[quo_name(var2)]][["Code"]],
labels = codelist_list[[quo_name(var2)]][["Bezeichnung"]])
}
mutate_at(data, c("factor1", "factor2"), convert_factors)
factor1 factor2 other_var
1 Kauf Eigengeschaeft 1
2 Verkauf Kundengeschaeft 2
由于您只使用字符串和 SE 函数(因子构造函数),因此不需要表达式或 quosures。只需将 name-unquoting 与 :=
一起使用
convert_factors <- function(variable, df) {
factor <- factor(variable,
levels = codelist_list[[variable]][["Code"]],
labels = codelist_list[[variable]][["Bezeichnung"]]
)
mutate(df, !! variable := factor)
}
map(c("factor1", "factor2"), convert_factors, df = data)
我有一个包含很多变量的数据集,其中一些是字符变量,我想将其转换为因子。由于有许多变量要转换,我想使用 dplyr_0.7
中新的 tidy eval 功能来完成此操作。这是我的数据中的一个最小示例:
data <- data.frame(factor1 = c("K", "V"),
factor2 = c("E", "K"),
other_var = 1:2,
stringsAsFactors = FALSE)
我有一个命名列表,其中包含我要转换的每个变量的 data.frame
。列表中的这些 data.frame
都具有相同的结构,可以在这个例子中看到:
codelist_list <- list(factor1 = data.frame(Code = c("K", "V"),
Bezeichnung = c("Kauf", "Verkauf"),
stringsAsFactors = FALSE),
factor2 = data.frame(Code = c("E", "K"),
Bezeichnung = c("Eigengeschaeft", "Kundengeschaeft"),
stringsAsFactors = FALSE))
我不是想做的是为每个变量定义这样的因子:
mutate(df, factor1 = factor(factor1,
levels = codelist_list[["factor1"]][["Code"]],
labels = codelist_list[["factor1"]][["Bezeichnung"]]))
到目前为止我尝试过的是:
convert_factors <- function(variable, df) {
factor_variable <- enquo(variable)
df %>%
mutate(!!quo_name(factor_variable) := factor(!!quo_name(factor_variable),
levels = codelist_list[[variable]][["Code"]],
labels = codelist_list[[variable]][["Bezeichnung"]]))
}
第一步,我想通过调用 convert_factors("factor1", data)
来检查我的函数 convert_factors()
是否正常工作,其中 returns
factor1 factor2 other_var
1 <NA> E 1
2 <NA> K 2
变量不显示值标签,而是替换为 NA
。
最终目标是 map
我要转换的所有变量。在这里,我尝试了 map(c("factor1", "factor2"), convert_factors, df = data)
,它返回了
Error in (function (x, strict = TRUE) : the argument has already been evaluated
我试图按照 http://dplyr.tidyverse.org/articles/programming.html 的说明进行操作,但这就是我想出的全部。
有谁知道问题出在哪里(并希望向我解释我的错误)。
我认为你混淆了 quosures 和字符串:
在你的函数中,
variable
是一个字符串,不是表达式。所以你应该把它转换成rlang::sym
,而不是enquo
.quo_name
用于将表达式转换为字符串。由于variable
已经是一个字符串,您可以直接在mutate
. 中的 rhs(右侧)上执行 at lhs in
mutate
你需要用!!
取消引用factor_variable
而不是试图用quo_name
将它转换成字符串。
!!variable
更正上述错误后,您的功能将正常工作:
convert_factors <- function(variable, df) {
factor_variable <- rlang::sym(variable)
df %>%
mutate(!!variable := factor(
!!factor_variable,
levels = codelist_list[[variable]][["Code"]],
labels = codelist_list[[variable]][["Bezeichnung"]]))
}
# > convert_factors('factor1', data)
# factor1 factor2 other_var
# 1 Kauf E 1
# 2 Verkauf K 2
这是我的尝试:
params <- lapply(codelist_list, setNames, nm = c('levels', 'labels'))
convert_factors <- function(variable, df) {
factor_variable <- rlang::sym(variable)
factor_param <- c(list(factor_variable), params[[variable]])
df %>% mutate(!!variable := do.call(factor, factor_param))
}
convert_factors('factor1', data)
# factor1 factor2 other_var
# 1 Kauf E 1
# 2 Verkauf K 2
使用 tidy eval 和 dplyr 的 mt1022 的很好的解决方案。然而,这个任务可以只使用 base-R 来完成:
data[,names(codelist_list)] <- lapply(names(codelist_list), function(x)
data[,x] <- factor(data[,x],
levels = codelist_list[[x]][["Code"]],
labels = codelist_list[[x]][["Bezeichnung"]]))
您可以使用 mutate_at
来解决这个问题,使用 funs
中的 .
编码一次将函数应用于多个列。
这种方法仍然涉及使用 tidyeval
从 codelist_list
中提取正确的列表,同时通过 .
.
mutate_at(data, c("factor1", "factor2"),
funs( factor(., levels = codelist_list[[quo_name(quo(.))]][["Code"]],
labels = codelist_list[[quo_name(quo(.))]][["Bezeichnung"]]) ) )
factor1 factor2 other_var
1 Kauf Eigengeschaeft 1
2 Verkauf Kundengeschaeft 2
如果您想创建一个函数传递给 mutate_at
,您可以这样做,只需稍作改动即可。
convert_factors = function(variable) {
var2 = enquo(variable)
factor(variable, levels = codelist_list[[quo_name(var2)]][["Code"]],
labels = codelist_list[[quo_name(var2)]][["Bezeichnung"]])
}
mutate_at(data, c("factor1", "factor2"), convert_factors)
factor1 factor2 other_var
1 Kauf Eigengeschaeft 1
2 Verkauf Kundengeschaeft 2
由于您只使用字符串和 SE 函数(因子构造函数),因此不需要表达式或 quosures。只需将 name-unquoting 与 :=
convert_factors <- function(variable, df) {
factor <- factor(variable,
levels = codelist_list[[variable]][["Code"]],
labels = codelist_list[[variable]][["Bezeichnung"]]
)
mutate(df, !! variable := factor)
}
map(c("factor1", "factor2"), convert_factors, df = data)