从每行的字符串中评估不同的逻辑条件
Evaluate different logical conditions from string for each row
我有一个 data.frame
这样的:
value condition
1 0.46 value > 0.5
2 0.96 value == 0.79
3 0.45 value <= 0.65
4 0.68 value == 0.88
5 0.57 value < 0.9
6 0.10 value > 0.01
7 0.90 value >= 0.6
8 0.25 value < 0.91
9 0.04 value > 0.2
structure(list(value = c(0.46, 0.96, 0.45, 0.68, 0.57, 0.1, 0.9,
0.25, 0.04), condition = c("value > 0.5", "value == 0.79", "value <= 0.65",
"value == 0.88", "value < 0.9", "value > 0.01", "value >= 0.6",
"value < 0.91", "value > 0.2")), class = "data.frame", row.names = c(NA,
-9L))
我想为每一行计算 condition
列中的字符串。
所以结果应该是这样的。
value condition goal
1 0.46 value > 0.5 FALSE
2 0.96 value == 0.79 FALSE
3 0.45 value <= 0.65 TRUE
4 0.68 value == 0.88 FALSE
5 0.57 value < 0.9 TRUE
6 0.10 value > 0.01 TRUE
7 0.90 value >= 0.6 TRUE
8 0.25 value < 0.91 TRUE
9 0.04 value > 0.2 FALSE
我想 dplyr
框架内有一个方便的 NSE 解决方案。我已经尝试过 !!
和 expr()
以及其他。当尝试使用
按 condition
进行子集化时,我得到了一些有希望的结果
result <- df[0,]
for(i in 1:nrow(df)) {
result <- rbind(result, filter_(df[i,], bquote(.(df$condition[i]))))
}
但我不喜欢这个解决方案,这也不是我想要的。
希望有人能帮忙
更新:我试图避免eval(parse(..))
。
一个简单直接的解决方案是使用 eval(parse...
library(dplyr)
df %>%
rowwise() %>%
mutate(goal = eval(parse(text = condition)))
# A tibble: 9 x 3
# value condition goal
# <dbl> <chr> <lgl>
#1 0.46 value > 0.5 FALSE
#2 0.96 value == 0.79 FALSE
#3 0.45 value <= 0.65 TRUE
#4 0.68 value == 0.88 FALSE
#5 0.570 value < 0.9 TRUE
#6 0.1 value > 0.01 TRUE
#7 0.9 value >= 0.6 TRUE
#8 0.25 value < 0.91 TRUE
#9 0.04 value > 0.2 FALSE
不过,我建议在使用前阅读 some posts。
如果你想避免eval(parse...
你可以试试这个:
library(tidyverse)
df %>% mutate(bound = as.numeric(str_extract(condition, "[0-9 \.]*$")),
goal = case_when(grepl("==", condition) ~ value == bound,
grepl(">=", condition) ~ value >= bound,
grepl("<=", condition) ~ value <= bound,
grepl(">", condition) ~ value > bound,
grepl("<", condition) ~ value < bound,
T ~ NA))
value condition bound goal
1 0.46 value > 0.5 0.50 FALSE
2 0.96 value == 0.79 0.79 FALSE
3 0.45 value <= 0.65 0.65 TRUE
4 0.68 value == 0.88 0.88 FALSE
5 0.57 value < 0.9 0.90 TRUE
6 0.10 value > 0.01 0.01 TRUE
7 0.90 value >= 0.6 0.60 TRUE
8 0.25 value < 0.91 0.91 TRUE
9 0.04 value > 0.2 0.20 FALSE
不完全确定您是否正在寻找这样的东西,但是,您也可以使用 lazyeval
中的 lazy_eval()
:
df %>%
rowwise() %>%
mutate(res = lazy_eval(sub("value", value, condition)))
value condition res
<dbl> <chr> <lgl>
1 0.46 value > 0.5 FALSE
2 0.96 value == 0.79 FALSE
3 0.45 value <= 0.65 TRUE
4 0.68 value == 0.88 FALSE
5 0.570 value < 0.9 TRUE
6 0.1 value > 0.01 TRUE
7 0.9 value >= 0.6 TRUE
8 0.25 value < 0.91 TRUE
9 0.04 value > 0.2 FALSE
即使它非常接近 eval(parse(...))
,也有可能使用 rlang
中的 parse_expr()
:
df %>%
rowwise() %>%
mutate(res = eval(rlang::parse_expr(condition)))
使用match.fun:
# get function, and the value
myFun <- lapply(strsplit(df1$condition, " "), function(i){
list(f = match.fun(i[ 2 ]),
v = as.numeric(i[ 3 ]))
})
df1$goal <- mapply(function(x, y){
x[[ "f" ]](y, x[ "v" ])
}, x = myFun, y = df1$value)
# value condition goal
# 1 0.46 value > 0.5 FALSE
# 2 0.96 value == 0.79 FALSE
# 3 0.45 value <= 0.65 TRUE
# 4 0.68 value == 0.88 FALSE
# 5 0.57 value < 0.9 TRUE
# 6 0.10 value > 0.01 TRUE
# 7 0.90 value >= 0.6 TRUE
# 8 0.25 value < 0.91 TRUE
# 9 0.04 value > 0.2 FALSE
我有一个 data.frame
这样的:
value condition
1 0.46 value > 0.5
2 0.96 value == 0.79
3 0.45 value <= 0.65
4 0.68 value == 0.88
5 0.57 value < 0.9
6 0.10 value > 0.01
7 0.90 value >= 0.6
8 0.25 value < 0.91
9 0.04 value > 0.2
structure(list(value = c(0.46, 0.96, 0.45, 0.68, 0.57, 0.1, 0.9,
0.25, 0.04), condition = c("value > 0.5", "value == 0.79", "value <= 0.65",
"value == 0.88", "value < 0.9", "value > 0.01", "value >= 0.6",
"value < 0.91", "value > 0.2")), class = "data.frame", row.names = c(NA,
-9L))
我想为每一行计算 condition
列中的字符串。
所以结果应该是这样的。
value condition goal
1 0.46 value > 0.5 FALSE
2 0.96 value == 0.79 FALSE
3 0.45 value <= 0.65 TRUE
4 0.68 value == 0.88 FALSE
5 0.57 value < 0.9 TRUE
6 0.10 value > 0.01 TRUE
7 0.90 value >= 0.6 TRUE
8 0.25 value < 0.91 TRUE
9 0.04 value > 0.2 FALSE
我想 dplyr
框架内有一个方便的 NSE 解决方案。我已经尝试过 !!
和 expr()
以及其他。当尝试使用
condition
进行子集化时,我得到了一些有希望的结果
result <- df[0,]
for(i in 1:nrow(df)) {
result <- rbind(result, filter_(df[i,], bquote(.(df$condition[i]))))
}
但我不喜欢这个解决方案,这也不是我想要的。
希望有人能帮忙
更新:我试图避免eval(parse(..))
。
一个简单直接的解决方案是使用 eval(parse...
library(dplyr)
df %>%
rowwise() %>%
mutate(goal = eval(parse(text = condition)))
# A tibble: 9 x 3
# value condition goal
# <dbl> <chr> <lgl>
#1 0.46 value > 0.5 FALSE
#2 0.96 value == 0.79 FALSE
#3 0.45 value <= 0.65 TRUE
#4 0.68 value == 0.88 FALSE
#5 0.570 value < 0.9 TRUE
#6 0.1 value > 0.01 TRUE
#7 0.9 value >= 0.6 TRUE
#8 0.25 value < 0.91 TRUE
#9 0.04 value > 0.2 FALSE
不过,我建议在使用前阅读 some posts。
如果你想避免eval(parse...
你可以试试这个:
library(tidyverse)
df %>% mutate(bound = as.numeric(str_extract(condition, "[0-9 \.]*$")),
goal = case_when(grepl("==", condition) ~ value == bound,
grepl(">=", condition) ~ value >= bound,
grepl("<=", condition) ~ value <= bound,
grepl(">", condition) ~ value > bound,
grepl("<", condition) ~ value < bound,
T ~ NA))
value condition bound goal
1 0.46 value > 0.5 0.50 FALSE
2 0.96 value == 0.79 0.79 FALSE
3 0.45 value <= 0.65 0.65 TRUE
4 0.68 value == 0.88 0.88 FALSE
5 0.57 value < 0.9 0.90 TRUE
6 0.10 value > 0.01 0.01 TRUE
7 0.90 value >= 0.6 0.60 TRUE
8 0.25 value < 0.91 0.91 TRUE
9 0.04 value > 0.2 0.20 FALSE
不完全确定您是否正在寻找这样的东西,但是,您也可以使用 lazyeval
中的 lazy_eval()
:
df %>%
rowwise() %>%
mutate(res = lazy_eval(sub("value", value, condition)))
value condition res
<dbl> <chr> <lgl>
1 0.46 value > 0.5 FALSE
2 0.96 value == 0.79 FALSE
3 0.45 value <= 0.65 TRUE
4 0.68 value == 0.88 FALSE
5 0.570 value < 0.9 TRUE
6 0.1 value > 0.01 TRUE
7 0.9 value >= 0.6 TRUE
8 0.25 value < 0.91 TRUE
9 0.04 value > 0.2 FALSE
即使它非常接近 eval(parse(...))
,也有可能使用 rlang
中的 parse_expr()
:
df %>%
rowwise() %>%
mutate(res = eval(rlang::parse_expr(condition)))
使用match.fun:
# get function, and the value
myFun <- lapply(strsplit(df1$condition, " "), function(i){
list(f = match.fun(i[ 2 ]),
v = as.numeric(i[ 3 ]))
})
df1$goal <- mapply(function(x, y){
x[[ "f" ]](y, x[ "v" ])
}, x = myFun, y = df1$value)
# value condition goal
# 1 0.46 value > 0.5 FALSE
# 2 0.96 value == 0.79 FALSE
# 3 0.45 value <= 0.65 TRUE
# 4 0.68 value == 0.88 FALSE
# 5 0.57 value < 0.9 TRUE
# 6 0.10 value > 0.01 TRUE
# 7 0.90 value >= 0.6 TRUE
# 8 0.25 value < 0.91 TRUE
# 9 0.04 value > 0.2 FALSE