如何通过在用户定义的函数中将字符串作为列名传递来进行过滤?
How do you filter by passing a string as a column name in a user-defined function?
我正在编写一个函数,用户可以在其中指定他们想要过滤的列以及他们想要的截止值。在这个例子中,我想过滤掉任何低于 2 的预测试分数。这是一个示例数据集:
library(dplyr)
test <- tibble(name = c("Corey", "Justin", "Sibley", "Kate"),
pretest_score = c(1:4),
posttest_score = c(5:8),
final_score = c(9:12))
filter_function <- function(data, test_type = c(pretest, posttest, final), value) {
test_character <- deparse(substitute(test_type))
test_score <- paste0(test_character, "_score")
data %>%
filter({{test_score}} > value)
}
filter_function(test, test_type = pretest, value = 2)
我也试过 !!test_score、test_score(周围什么都没有)和来自 rlang
的 ensym(test_score),都无济于事.
注意:我知道在 this 示例中,我可以指定 pretest_score、posttest_score 等作为测试类型,但在我的真实数据集中,我有这些测试的许多维度,用户可以确定(pretest_score、pretest_date、pretest_location 等)的截止值,因此 重要的是我将列前缀与函数本身的后缀(此处为 _score)合并。
感谢您的帮助!
将字符转换为 sym
bol 并用 !!
求值
filter_function <- function(data, test_type = c(pretest, posttest,
final), value) {
test_character <- deparse(substitute(test_type))
test_score <- paste0(test_character, "_score")
data %>%
filter(!! rlang::sym(test_score) > value)
}
-测试
> filter_function(test, test_type = pretest, value = 2)
# A tibble: 2 × 4
name pretest_score posttest_score final_score
<chr> <int> <int> <int>
1 Sibley 3 7 11
2 Kate 4 8 12
几点:
通常,当在 R 中使用一组选项时,通常使用字符向量,而不是未计算的表达式。 R专门为此提供了match.arg
。这也实现了第一个选项的默认值,因此如果我们使用 match.arg
调用函数的调用可以省略 type_test = "pretest"
,因为这是默认值。
.[[test_score]]
可以用来指定指定的列
因此我们有
filter_function <- function(data, test_type = c("pretest", "posttest", "final"),
value) {
test_type <- match.arg(test_type)
test_score <- paste0(test_type, "_score")
data %>%
filter(.[[test_score]] > value)
}
filter_function(test, test_type = "pretest", value = 2)
# A tibble: 2 x 4
name pretest_score posttest_score final_score
<chr> <int> <int> <int>
1 Sibley 3 7 11
2 Kate 4 8 12
# pretest is the default
filter_function(test, value = 2)
# A tibble: 2 x 4
name pretest_score posttest_score final_score
<chr> <int> <int> <int>
1 Sibley 3 7 11
2 Kate 4 8 12
另请注意,我们可以像这样指定函数。用户仍然可以指定“pretest”,因为 match.arg
将匹配前导子字符串。事实上,他们甚至可以指定“pre”或“post”。
filter_function2 <- function(data,
test_type = c("pretest_score", "posttest_score", "final_score"),
value) {
test_type <- match.arg(test_type)
data %>%
filter(.[[test_type]] > value)
}
filter_function2(test, test_type = "pretest", value = 2)
基础 R
这也可以在没有像这样的任何包的情况下完成:
filter_function3 <- function(data, test_type = c("pretest", "posttest", "final"),
value) {
test_type <- match.arg(test_type)
test_score <- paste0(test_type, "_score")
data[data[[test_score]] > value, ]
}
filter_function3(test, test_type = "pretest", value = 2)
我正在编写一个函数,用户可以在其中指定他们想要过滤的列以及他们想要的截止值。在这个例子中,我想过滤掉任何低于 2 的预测试分数。这是一个示例数据集:
library(dplyr)
test <- tibble(name = c("Corey", "Justin", "Sibley", "Kate"),
pretest_score = c(1:4),
posttest_score = c(5:8),
final_score = c(9:12))
filter_function <- function(data, test_type = c(pretest, posttest, final), value) {
test_character <- deparse(substitute(test_type))
test_score <- paste0(test_character, "_score")
data %>%
filter({{test_score}} > value)
}
filter_function(test, test_type = pretest, value = 2)
我也试过 !!test_score、test_score(周围什么都没有)和来自 rlang
的 ensym(test_score),都无济于事.
注意:我知道在 this 示例中,我可以指定 pretest_score、posttest_score 等作为测试类型,但在我的真实数据集中,我有这些测试的许多维度,用户可以确定(pretest_score、pretest_date、pretest_location 等)的截止值,因此 重要的是我将列前缀与函数本身的后缀(此处为 _score)合并。
感谢您的帮助!
将字符转换为 sym
bol 并用 !!
filter_function <- function(data, test_type = c(pretest, posttest,
final), value) {
test_character <- deparse(substitute(test_type))
test_score <- paste0(test_character, "_score")
data %>%
filter(!! rlang::sym(test_score) > value)
}
-测试
> filter_function(test, test_type = pretest, value = 2)
# A tibble: 2 × 4
name pretest_score posttest_score final_score
<chr> <int> <int> <int>
1 Sibley 3 7 11
2 Kate 4 8 12
几点:
通常,当在 R 中使用一组选项时,通常使用字符向量,而不是未计算的表达式。 R专门为此提供了
match.arg
。这也实现了第一个选项的默认值,因此如果我们使用match.arg
调用函数的调用可以省略type_test = "pretest"
,因为这是默认值。.[[test_score]]
可以用来指定指定的列
因此我们有
filter_function <- function(data, test_type = c("pretest", "posttest", "final"),
value) {
test_type <- match.arg(test_type)
test_score <- paste0(test_type, "_score")
data %>%
filter(.[[test_score]] > value)
}
filter_function(test, test_type = "pretest", value = 2)
# A tibble: 2 x 4
name pretest_score posttest_score final_score
<chr> <int> <int> <int>
1 Sibley 3 7 11
2 Kate 4 8 12
# pretest is the default
filter_function(test, value = 2)
# A tibble: 2 x 4
name pretest_score posttest_score final_score
<chr> <int> <int> <int>
1 Sibley 3 7 11
2 Kate 4 8 12
另请注意,我们可以像这样指定函数。用户仍然可以指定“pretest”,因为 match.arg
将匹配前导子字符串。事实上,他们甚至可以指定“pre”或“post”。
filter_function2 <- function(data,
test_type = c("pretest_score", "posttest_score", "final_score"),
value) {
test_type <- match.arg(test_type)
data %>%
filter(.[[test_type]] > value)
}
filter_function2(test, test_type = "pretest", value = 2)
基础 R
这也可以在没有像这样的任何包的情况下完成:
filter_function3 <- function(data, test_type = c("pretest", "posttest", "final"),
value) {
test_type <- match.arg(test_type)
test_score <- paste0(test_type, "_score")
data[data[[test_score]] > value, ]
}
filter_function3(test, test_type = "pretest", value = 2)