我正在寻找以下内容的可扩展版本。
给定:
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
在算术运算中转换为1
,FALSE
转换为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