【问题标题】:Alternatives to apply same condition to multiple variables inside case_when function将相同条件应用于 case_when 函数内的多个变量的替代方法
【发布时间】:2019-05-20 01:09:10
【问题描述】:

我正在尝试为case_when 函数中的多重调节找到更有效或更优雅的解决方案。

我正在创建一个基于跨数据框特定列的多个条件的虚拟列。在很多情况下,我对许多列使用相同的 is.na()。我得到了正确的结果,但我尝试了 applyreduceanyNa 的其他方法,但没有成功。

假设这个数据框看起来像我正在处理的数据:

set.seed(12)
dframe <- data.frame(
  x1 = sample(letters[1:2], 10, replace = TRUE),
  x2 = sample(0:1, 10, replace = TRUE),
  x3 = sample(0:2, 10, replace = TRUE),
  x4 = sample(0:2, 10, replace = TRUE),
  x5 = sample(0:2, 10, replace = TRUE),
  x6 = sample(0:2, 10, replace = TRUE)
) %>% 
  mutate_if(is.numeric, list(~na_if(., 2)))

它看起来像这样:

   x1 x2 x3 x4 x5 x6
1   b  1 NA  0  0  0
2   b  0  0  0 NA NA
3   b  1  0  0  0  1
4   a  0 NA  1 NA  0
5   a  1  1 NA NA NA
6   b  0 NA  1  1  1
7   a  1  1 NA NA  0
8   a  1  0  1 NA  0
9   b  1 NA NA  0  0
10  b  1  1  0 NA NA

然后,我根据以下条件创建列x7

dframe %>% 
  mutate(
    x7 = case_when(
      x2 == 1 & 
      (!is.na(x3) | !is.na(x4) | !is.na(x5)) & 
      !is.na(x6) ~ 1,
      x2 == 1 ~ 0,
      TRUE ~ NA_real_
    )
  )

导致:

   x1 x2 x3 x4 x5 x6 x7
1   b  1 NA  0  0  0  1
2   b  0  0  0 NA NA NA
3   b  1  0  0  0  1  1
4   a  0 NA  1 NA  0 NA
5   a  1  1 NA NA NA  0
6   b  0 NA  1  1  1 NA
7   a  1  1 NA NA  0  1
8   a  1  0  1 NA  0  1
9   b  1 NA NA  0  0  1
10  b  1  1  0 NA NA  0

但是,我想找到一个替代方法来编写(!is.na(x3) | !is.na(x4) | !is.na(x5)),因为在我的真实脚本中,我必须为 11 列输入这个。

我尝试使用complete.cases(x3, x4, x5),但它不符合我在代码中使用的逻辑。

使用anyNA(x3, x4, x5) 抛出Error in anyNA(x3, x4, x5) : anyNA takes 1 or 2 arguments

也尝试了similar problem的答案,但由于我没有使用它进行过滤,所以没有成功。

也许我想多了,但我正在寻找的是无需使用 (!is.na(x3) | !is.na(x4) | !is.na(x5)) 的东西。

【问题讨论】:

    标签: r


    【解决方案1】:

    我们可以使用rowSums 并按名称指定列

    library(dplyr)
    
    dframe %>% 
      mutate(x7 = case_when(
                   x2 == 1 & 
                   rowSums(!is.na(.[c("x3","x4","x5")])) > 0 &
                   !is.na(x6) ~ 1,
                   x2 == 1 ~ 0,
                   TRUE ~ NA_real_
                  )
              )
    

    或按位置

    rowSums(!is.na(.[3:5])) > 0
    

    我们也可以使用反转逻辑来做到这一点。

    rowSums(is.na(.[c("x3","x4","x5")])) != 3
    

    或者

    rowSums(is.na(.[3:5])) != 3
    

    我们在这里使用 3,因为在给定的示例中有 3 列要检查(x3x4x5),您可以根据您的实际列数 (11) 更改数字。

    【讨论】:

    • 就是这样!我更喜欢命名列,但每个选项都可以创造奇迹。现在看来如此明显。感谢您的帮助!
    猜你喜欢
    • 2018-12-31
    • 1970-01-01
    • 2023-02-23
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-15
    相关资源
    最近更新 更多