我知道这个问题很可能是重复的。我试图用谷歌搜索这个问题,但是我找不到我想要的东西。
我想做的是根据用户指定的条件过滤数据集。例如:
df <-
data.frame(type = c("a", "a", "b", "b"),
value = c(1,5,7,2), stringsAsFactors = F) %>%
as_tibble()
cond <- ">"
val <- 2
df %>% filter(value, cond, val)
(即与df %>% filter(value>2)
相同)
如果可能的话,我将可以在函数的内部和外部使用此设置。
编辑:
当我问我的问题时,我有点着急。我真正想要的是根据用户指定的条件mutate
,而不是过滤。罗纳克·沙阿(Ronak Shahs)的答案解决了filter
问题,我对mutate
问题做了一些小的改动。我认为没有必要发布新的问题,因为这两个问题密切相关。因此,我只发布有关mutate
问题的答案(也可以回答Tjebo的评论)。
答案 0 :(得分:4)
另一种方法是使用match.fun
来匹配要应用的函数,并使用NSE将其应用于列。
library(dplyr)
library(rlang)
apply_fun <- function(df, col, fun, val) {
fun1 <- match.fun(fun)
df %>% filter(fun1({{col}}, val))
}
df %>% apply_fun(value, cond, val)
# type value
# <chr> <dbl>
#1 a 5
#2 b 7
df %>% apply_fun(value, cond, 1)
# A tibble: 3 x 2
# type value
# <chr> <dbl>
#1 a 5
#2 b 7
#3 b 2
答案 1 :(得分:2)
一种方法是使用eval(parse(text = ...))
,即
df %>%
filter(eval(parse(text = paste('value', cond, val))))
# A tibble: 2 x 2
# type value
# <chr> <dbl>
#1 a 5
#2 b 7
答案 2 :(得分:1)
另一个选择是:
library(tidyverse)
library(rlang)
df %>%
filter_at("value", ~ eval(sym(cond))(.x, val))
答案 3 :(得分:0)
请查看我的修改。
df <-
data.frame(type = c("a", "a", "b", "b"),
value = c(1,5,7,2), stringsAsFactors = F) %>%
as_tibble() %>%
mutate(cond = case_when(type == "a" ~ "==",
type == "b" ~ ">="),
val1 = case_when(type == "a" ~ 1,
type == "b" ~ 3),
val2 = case_when(type == "a" ~ 6,
type == "b" ~ 7),
val3 = case_when(type == "a" ~ 9,
type == "b" ~ 0))
基于Ronak Shahs解决方案
apply_fun <- function(df, col, fun, val, colname = "a") {
fun1 <- match.fun(fun)
df <- df %>% mutate(!!colname := fun1({{col}}, val))
df[, ncol(df)]
}
可能有一个更好的最终解决方案,但这就是我想出的。
lst <- list()
for (i in 1:nrow(df)) {
lst[[i]] <-
bind_cols(
apply_fun(df[i,], df[i,]$value, df[i,]$cond, df[i,]$val1, "type1"),
apply_fun(df[i,], df[i,]$value, df[i,]$cond, df[i,]$val2, "type2"),
apply_fun(df[i,], df[i,]$value, df[i,]$cond, df[i,]$val3, "type3")
)
}
df %>% bind_cols(., bind_rows(lst))
# A tibble: 4 x 9
type value cond val1 val2 val3 type1 type2 type3
<chr> <dbl> <chr> <dbl> <dbl> <dbl> <lgl> <lgl> <lgl>
1 a 1 == 1 6 9 TRUE FALSE FALSE
2 a 5 == 1 6 9 FALSE FALSE FALSE
3 b 7 >= 3 7 0 TRUE TRUE TRUE
4 b 2 >= 3 7 0 FALSE FALSE TRUE