从函数内将列名传递给 dplyr 过滤器函数
pass column name to dplyr filter function from within a function
我正在编写一个函数来向我正在构建的数据框添加一些额外的行。
我已经阅读了以前 OP 中的许多问题和答案。但是我在那里找到的所有答案、提示和技巧都不适合我。
对于这个问题,我有以下测试数据框:
tst <- data.frame("col 1" = c("a","a", "c"), "keyword test" = c("What", "Why", "how"), check.names = F)
> tst
col 1 keyword test
1 a What
2 a Why
3 c how
如您所见,我无法删除数据框中的空格,因为下一个工具需要列名中有空格(不要问我为什么!)。
例如,现在我想过滤所有以 "how" 开头的行,并将 "how" 替换为 "no_idea"。这发生在临时 DF 内部。以便稍后我可以将行 "c" "no_idea"
添加到原始数据框。
我为此编写的函数如下所示:
add_keyword <- function(df, filterColumn, filterValue,replacement){
library(plyr)
library(dplyr)
temp_df <- dplyr::filter_(df, filterColumn == filterValue)
temp_df$`Target keyword` <- gsub(as.character(filterValue), as.character(replacement), temp_df$`Target keyword`)
df_out <- rbind(df, temp_df)
return(df_out)
}
tst2 <- add_keyword(tst, "keyword test", "how", "no_idea")
当然,如果我 运行 函数内的行在函数外,它就完美无缺。
我希望在里面得到的结果 tst2
> tst2
col 1 keyword test
1 a What
2 a Why
3 c how
4 c no_idea
我们可以用 lazyeval
中的 interp
来做到这一点:
library(dplyr)
library(lazyeval)
add_keyword <- function(df, filterColumn, filterValue,replacement){
temp_df <- df %>%
filter_(interp(~ var == fval, var = as.name(filterColumn), fval = filterValue))
temp_df[[filterColumn]] <- gsub(filterValue, replacement = replacement, temp_df[[filterColumn]])
rbind(df, temp_df)
}
add_keyword(tst, "keyword test", "how", "no_idea")
# col 1 keyword test
# 1 a What
# 2 a Why
# 3 c how
# 4 c no_idea
如果我们不想创建额外的行,我们也可以尝试:
add_keyword <- function(df, filterColumn, filterValue, replacement){
df <- df %>%
mutate_(
.dots = setNames(
list(
interp(~ ifelse(startsWith(as.character(var), fval), rval, as.character(var)),
var = as.name(filterColumn), fval = filterValue, rval = replacement)),
filterColumn
)
)
df
}
add_keyword(tst, "keyword test", "how", "no_idea")
# col 1 keyword test
# 1 a What
# 2 a Why
# 3 c no_idea
我们可以使用dplyr
的devel版本(即将发布0.6.0)来利用quosure
s
add_keyword <- function(df, filterColumn, filterValue, replacement){
filterColumn <- enquo(filterColumn)
filtColumn <- quo_name(filterColumn)
filterValue <- quo_name(enquo(filterValue))
replacement <- quo_name(enquo(replacement))
df %>%
filter(UQ(filterColumn) == filterValue) %>%
mutate(!!filtColumn := gsub(filterValue, replacement, !!filterColumn)) %>%
bind_rows(df, .)
}
除了标准名称,不自然的列名可以用反引号传递。
add_keyword(tst, `keyword test`, how, no_idea)
# col 1 keyword test
#1 a What
#2 a Why
#3 c how
#4 c no_idea
在这里,enquo
的行为类似于 base R
中的 substitute
,通过获取输入参数并将其转换为 quosure
。我们使用 quo_name
将 quosure 转换为字符串,并通过取消引号(UQ
或 !!
)对值进行评估。
检查其他值
add_keyword(tst, `keyword test`, how, new_idea)
# col 1 keyword test
#1 a What
#2 a Why
#3 c how
#4 c new_idea
add_keyword(tst, `col 1`, a, z)
# col 1 keyword test
#1 a What
#2 a Why
#3 c how
#4 z What
#5 z Why
数据
tst <- data.frame("col 1" = c("a","a", "c"), "keyword test" = c("What", "Why", "how"),
check.names = FALSE, stringsAsFactors=FALSE)
一个简单的技巧,无法解释但写下下面的代码片段:
filter(df[, paste(filterColumn)] == filterValue)
这对我有用,希望对正在寻找解决方案的您有用:)
我正在编写一个函数来向我正在构建的数据框添加一些额外的行。
我已经阅读了以前 OP 中的许多问题和答案。但是我在那里找到的所有答案、提示和技巧都不适合我。
对于这个问题,我有以下测试数据框:
tst <- data.frame("col 1" = c("a","a", "c"), "keyword test" = c("What", "Why", "how"), check.names = F)
> tst
col 1 keyword test
1 a What
2 a Why
3 c how
如您所见,我无法删除数据框中的空格,因为下一个工具需要列名中有空格(不要问我为什么!)。
例如,现在我想过滤所有以 "how" 开头的行,并将 "how" 替换为 "no_idea"。这发生在临时 DF 内部。以便稍后我可以将行 "c" "no_idea"
添加到原始数据框。
我为此编写的函数如下所示:
add_keyword <- function(df, filterColumn, filterValue,replacement){
library(plyr)
library(dplyr)
temp_df <- dplyr::filter_(df, filterColumn == filterValue)
temp_df$`Target keyword` <- gsub(as.character(filterValue), as.character(replacement), temp_df$`Target keyword`)
df_out <- rbind(df, temp_df)
return(df_out)
}
tst2 <- add_keyword(tst, "keyword test", "how", "no_idea")
当然,如果我 运行 函数内的行在函数外,它就完美无缺。
我希望在里面得到的结果 tst2
> tst2
col 1 keyword test
1 a What
2 a Why
3 c how
4 c no_idea
我们可以用 lazyeval
中的 interp
来做到这一点:
library(dplyr)
library(lazyeval)
add_keyword <- function(df, filterColumn, filterValue,replacement){
temp_df <- df %>%
filter_(interp(~ var == fval, var = as.name(filterColumn), fval = filterValue))
temp_df[[filterColumn]] <- gsub(filterValue, replacement = replacement, temp_df[[filterColumn]])
rbind(df, temp_df)
}
add_keyword(tst, "keyword test", "how", "no_idea")
# col 1 keyword test
# 1 a What
# 2 a Why
# 3 c how
# 4 c no_idea
如果我们不想创建额外的行,我们也可以尝试:
add_keyword <- function(df, filterColumn, filterValue, replacement){
df <- df %>%
mutate_(
.dots = setNames(
list(
interp(~ ifelse(startsWith(as.character(var), fval), rval, as.character(var)),
var = as.name(filterColumn), fval = filterValue, rval = replacement)),
filterColumn
)
)
df
}
add_keyword(tst, "keyword test", "how", "no_idea")
# col 1 keyword test
# 1 a What
# 2 a Why
# 3 c no_idea
我们可以使用dplyr
的devel版本(即将发布0.6.0)来利用quosure
s
add_keyword <- function(df, filterColumn, filterValue, replacement){
filterColumn <- enquo(filterColumn)
filtColumn <- quo_name(filterColumn)
filterValue <- quo_name(enquo(filterValue))
replacement <- quo_name(enquo(replacement))
df %>%
filter(UQ(filterColumn) == filterValue) %>%
mutate(!!filtColumn := gsub(filterValue, replacement, !!filterColumn)) %>%
bind_rows(df, .)
}
除了标准名称,不自然的列名可以用反引号传递。
add_keyword(tst, `keyword test`, how, no_idea)
# col 1 keyword test
#1 a What
#2 a Why
#3 c how
#4 c no_idea
在这里,enquo
的行为类似于 base R
中的 substitute
,通过获取输入参数并将其转换为 quosure
。我们使用 quo_name
将 quosure 转换为字符串,并通过取消引号(UQ
或 !!
)对值进行评估。
检查其他值
add_keyword(tst, `keyword test`, how, new_idea)
# col 1 keyword test
#1 a What
#2 a Why
#3 c how
#4 c new_idea
add_keyword(tst, `col 1`, a, z)
# col 1 keyword test
#1 a What
#2 a Why
#3 c how
#4 z What
#5 z Why
数据
tst <- data.frame("col 1" = c("a","a", "c"), "keyword test" = c("What", "Why", "how"),
check.names = FALSE, stringsAsFactors=FALSE)
一个简单的技巧,无法解释但写下下面的代码片段:
filter(df[, paste(filterColumn)] == filterValue)
这对我有用,希望对正在寻找解决方案的您有用:)