tidyr::complete 的标准评估 - 由所有非数字列完成的函数
Standard evaluation for tidyr::complete - a function that completes by all non-numeric columns
我想创建一个函数,将 tidyr::complete 应用于 R data.frame 的所有非数字列。应将零值插入到新值行中。我知道这需要标准的评估解决方案,但到目前为止我还没有成功。
这是我目前的情况:
completeDf <- function(df){
vars <- names(df)
chVars <- vars[!(sapply(df, is.numeric))]
nmVars <- vars[!(vars %in% chVars)]
quoChVars <- quos(chVars)
nmList <- vector("list", length(nmVars))
nmList <- setNames(lapply(nmList, function(x) x <- 0), nmVars)
quoNmVars <- quos(nmList)
df <- df %>%
complete(!!!quoChVars, fill = !!!quoNmVars)
}
知道如何进行这项工作吗?
1) rlang/tidyreval 使用 !!!syms(notnum_names)
插入变量名称作为 complete
参数。 Fill
只是一个普通列表,不需要 rlang/tidyeval 计算。
library(dplyr)
library(tidyr)
library(rlang)
completeDF <- function(data) {
is_num <- sapply(data, is.numeric)
num_names <- names(data)[ is_num ]
notnum_names <- names(data)[ !is_num ]
fill <- Map(function(x) 0, num_names)
data %>% complete(!!!syms(notnum_names), fill = fill)
}
DF <- data.frame(a = c("A", "B", "B"), b = c("a", "a", "b"), c = 1:3) # test data
completeDF(DF)
给予:
# A tibble: 4 x 3
a b c
<fctr> <fctr> <dbl>
1 A a 1
2 A b 0
3 B a 2
4 B b 3
这是修改后的问题的原始代码,以使其工作。更改的行在每行末尾标有##。
completeDf <- function(df){
vars <- names(df)
chVars <- vars[!(sapply(df, is.numeric))]
nmVars <- vars[!(vars %in% chVars)]
symsChVars <- rlang::syms(chVars) ##
nmList <- vector("list", length(nmVars))
nmList <- setNames(lapply(nmList, function(x) 0), nmVars) ##
# quoNmVars <- quos(nmList ##
df %>% ##
complete(!!!symsChVars, fill = nmList) ##
}
completeDf(DF)
2) wrapr rlang/tidyeval 的替代方案是 wrapr 包。
此处的代码与 (1) 中的代码相同,只是我们使用 library(wrapr)
而不是 library(rlang)
并且 completeDF
的最后一行被替换为 let
给出 completeDF2
.
的语句
library(dplyr)
library(tidyr)
library(wrapr)
completeDF2 <- function(data) {
is_num <- sapply(data, is.numeric)
num_names <- names(data)[ is_num ]
notnum_names <- names(data)[ !is_num ]
fill <- Map(function(x) 0, num_names)
let(c(NOTNUM = toString(notnum_names)),
data %>% complete(NOTNUM, fill = fill),
strict = FALSE,
subsMethod = "stringsubs")
}
completeDF2(DF)
更新: 修复和改进。添加包装方法。
我想创建一个函数,将 tidyr::complete 应用于 R data.frame 的所有非数字列。应将零值插入到新值行中。我知道这需要标准的评估解决方案,但到目前为止我还没有成功。
这是我目前的情况:
completeDf <- function(df){
vars <- names(df)
chVars <- vars[!(sapply(df, is.numeric))]
nmVars <- vars[!(vars %in% chVars)]
quoChVars <- quos(chVars)
nmList <- vector("list", length(nmVars))
nmList <- setNames(lapply(nmList, function(x) x <- 0), nmVars)
quoNmVars <- quos(nmList)
df <- df %>%
complete(!!!quoChVars, fill = !!!quoNmVars)
}
知道如何进行这项工作吗?
1) rlang/tidyreval 使用 !!!syms(notnum_names)
插入变量名称作为 complete
参数。 Fill
只是一个普通列表,不需要 rlang/tidyeval 计算。
library(dplyr)
library(tidyr)
library(rlang)
completeDF <- function(data) {
is_num <- sapply(data, is.numeric)
num_names <- names(data)[ is_num ]
notnum_names <- names(data)[ !is_num ]
fill <- Map(function(x) 0, num_names)
data %>% complete(!!!syms(notnum_names), fill = fill)
}
DF <- data.frame(a = c("A", "B", "B"), b = c("a", "a", "b"), c = 1:3) # test data
completeDF(DF)
给予:
# A tibble: 4 x 3
a b c
<fctr> <fctr> <dbl>
1 A a 1
2 A b 0
3 B a 2
4 B b 3
这是修改后的问题的原始代码,以使其工作。更改的行在每行末尾标有##。
completeDf <- function(df){
vars <- names(df)
chVars <- vars[!(sapply(df, is.numeric))]
nmVars <- vars[!(vars %in% chVars)]
symsChVars <- rlang::syms(chVars) ##
nmList <- vector("list", length(nmVars))
nmList <- setNames(lapply(nmList, function(x) 0), nmVars) ##
# quoNmVars <- quos(nmList ##
df %>% ##
complete(!!!symsChVars, fill = nmList) ##
}
completeDf(DF)
2) wrapr rlang/tidyeval 的替代方案是 wrapr 包。
此处的代码与 (1) 中的代码相同,只是我们使用 library(wrapr)
而不是 library(rlang)
并且 completeDF
的最后一行被替换为 let
给出 completeDF2
.
library(dplyr)
library(tidyr)
library(wrapr)
completeDF2 <- function(data) {
is_num <- sapply(data, is.numeric)
num_names <- names(data)[ is_num ]
notnum_names <- names(data)[ !is_num ]
fill <- Map(function(x) 0, num_names)
let(c(NOTNUM = toString(notnum_names)),
data %>% complete(NOTNUM, fill = fill),
strict = FALSE,
subsMethod = "stringsubs")
}
completeDF2(DF)
更新: 修复和改进。添加包装方法。