r-scalable case_when case组合任意两种情况



我正在寻找以下内容的可扩展版本。

给定:

library(tidyverse)
df <- data.frame(a = c(1, 2, 3, 4, 5, 3, 1),
b = c(6, 7, 8, 9, 10, 8, 9),
c = c(15, 12, 9, 2, 13, 9, 10))
df
#   a  b  c
# 1 1  6 15
# 2 2  7 12
# 3 3  8  9
# 4 4  9  2
# 5 5 10 13
# 6 3  8  9
# 7 1  9 10

如果以下条件的任意两个组合有效,我想创建一个指标变量:

a>3、b>8、c>10

手动执行此操作的一个选项是使用case_when:

df %>% 
mutate(indicator_variable = case_when(
a > 3 & b > 8 ~ 1,
a > 3 & c > 10 ~ 1,
b > 8 & c > 10 ~ 1,
TRUE ~ 0
))
#   a  b  c indicator_variable
# 1 1  6 15                  0
# 2 2  7 12                  0
# 3 3  8  9                  0
# 4 4  9  2                  1
# 5 5 10 13                  1
# 6 3  8  9                  0
# 7 1  9 10                  0

这是可行的,但显然会变得更棘手,考虑的变量越多(choose(4, 2)(,将标准更改为四个变量中的任意两个:

a>3、b>8、c>10,d>=5

df2 <- data.frame(a = c(1, 2, 3, 4, 5, 3, 1),
b = c(6, 7, 8, 9, 10, 8, 9),
c = c(15, 12, 9, 2, 13, 9, 10),
d = c(1, 2, 3, 4, 5, 6, 5))
df2
#   a  b  c d
# 1 1  6 15 1
# 2 2  7 12 2
# 3 3  8  9 3
# 4 4  9  2 4
# 5 5 10 13 5
# 6 3  8  9 6
# 7 1  9 10 5
df2 %>% 
mutate(indicator_variable = case_when(
a > 3 & b > 8 ~ 1,
a > 3 & c > 10 ~ 1,
a > 3 & d >= 5 ~ 1,
b > 8 & c > 10 ~ 1,
b > 8 & d >= 5 ~ 1,
c > 10 & d >= 5 ~ 1,
TRUE ~ 0
))
#   a  b  c d indicator_variable
# 1 1  6 15 1                  0
# 2 2  7 12 2                  0
# 3 3  8  9 3                  0
# 4 4  9  2 4                  1
# 5 5 10 13 5                  1
# 6 3  8  9 6                  0
# 7 1  9 10 5                  1

等等。

最佳方法?不必涉及case_when,也许可以使用combn

感谢

这里不需要使用case_when,只需要利用TRUE在算术运算中转换为1FALSE转换为0的事实。

library(dplyr)
df <- tibble(a = c(1, 2, 3, 4, 5, 3, 1),
b = c(6, 7, 8, 9, 10, 8, 9),
c = c(15, 12, 9, 2, 13, 9, 10))
df %>%
mutate(indicator = as.numeric(((a > 3) + (b > 8) + (c > 10)) >= 2))
#> # A tibble: 7 × 4
#>       a     b     c indicator
#>   <dbl> <dbl> <dbl>     <dbl>
#> 1     1     6    15         0
#> 2     2     7    12         0
#> 3     3     8     9         0
#> 4     4     9     2         1
#> 5     5    10    13         1
#> 6     3     8     9         0
#> 7     1     9    10         0

创建一个接受运算符、值和数据集输入的函数

f1 <- function(dat, val, op) op(dat, val)

然后,创建两个具有值和运算符的list(如果运算符相同,则我们不需要(

lst1 <- list(a = 3, b = 8, c = 10, d = 5)
lst2 <- list(a = `>`, b = `>`, c = `>`, d = `>=`)

现在,我们用Reduce(使用第二个数据"df2"(进行combn

df2$indicator_variable <- +(Reduce(`|`, combn(lst1, 2, function(x) 
Reduce(`&`, Map(f1, dat = df2[names(x)], val = lst1[names(x)], 
op = lst2[names(x)])), simplify = FALSE)))

-输出

> df2
a  b  c d indicator_variable
1 1  6 15 1                  0
2 2  7 12 2                  0
3 3  8  9 3                  0
4 4  9  2 4                  1
5 5 10 13 5                  1
6 3  8  9 6                  0
7 1  9 10 5                  1

或者如果我们想更新第一个数据

lst1 <- list(a = 3, b = 8, c = 10)
lst2 <- list(a = `>`, b = `>`, c = `>`)
df$indicator_variable <- +(Reduce(`|`, combn(lst1, 2, function(x) 
Reduce(`&`, Map(f1, dat = df[names(x)], val = lst1[names(x)], 
op = lst2[names(x)])), simplify = FALSE)))
> df
a  b  c indicator_variable
1 1  6 15                  0
2 2  7 12                  0
3 3  8  9                  0
4 4  9  2                  1
5 5 10 13                  1
6 3  8  9                  0
7 1  9 10                  0

最新更新