首页 > 解决方案 > 您如何评估一组条件并根据列列表创建新列?

问题描述

我想在数据框中列出(或过滤)一组类似命名的列,为每一行评估这些列的值,然后用结果创建一个新列。

现在我正在使用case_when,但我不知道提供一些通配符或已定义列的列表的方法。

我想列一个列表或创建一个过滤器,因为我想评估数据框中的几列,而不仅仅是少数。case_when当列名彼此非常相似时,拥有一长串列似乎效率不高。

# Dummy data
ignore1 <- c(1, 0, 0)
ignore2 <- c(1, 0, 1)
col1 <- c(0, 1, 0)
col2 <- c(0, 1, 1)
col3 <- c(0, 1, 0)

df <- data.frame(ignore1, ignore2, col1, col2, col3)
df %>% 
  mutate(evaluation = case_when(
    col1 == 0| col1 == 0 | col1 == 0  ~ "Failed",
    TRUE ~ "Passed"
    )
  )

这是预期的结果:

  ignore1 ignore2 col1 col2 col3 evaluation
1       1       1    0    0    0     Failed
2       0       0    1    1    1     Passed
3       0       1    0    1    0     Failed

其中第 2 行通过,因为,col1具有的值。col2col3 1

标签: rdplyr

解决方案


我们可以用它rowSums来提高效率

i1 <- startsWith(names(df), 'col')
c( "Failed",  "Passed")[(rowSums(df[i1] == 1) == 3) + 1]
#[1] "Failed" "Passed" "Failed"

或者另一个base R有效的选择是Reduce

c("Failed", "Passed")[Reduce(`&`, df[i1]) +1]
#[1] "Failed" "Passed" "Failed"

注意:两种base R解决方案都很紧凑并且非常高效


或与&

library(dplyr)
df %>% 
     mutate(evaluation =  c('Failed', 'Passed')[1 + (col1 & col2 & col3)])
#  ignore1 ignore2 col1 col2 col3 evaluation
#1       1       1    0    0    0     Failed
#2       0       0    1    1    1     Passed
#3       0       1    0    1    0     Failed

或者我们可以rowSumsdplyr

df %>%
   mutate(evaluation = c("Failed", "Passed")[(rowSums(.[i1] == 1) == 3) + 1])

注意:这两种解决方案都非常有效,并且不使用任何不需要的包

或者如果我们需要一些包,那么使用magrittrwithpurrr

library(magrittr)
library(purrr)
df %>% 
   mutate(evaluation = select(., starts_with('col')) %>% 
                          reduce(`&`) %>%
                          add(1) %>%
                          c("Failed", "Passed")[.])
#  ignore1 ignore2 col1 col2 col3 evaluation
#1       1       1    0    0    0     Failed
#2       0       0    1    1    1     Passed
#3       0       1    0    1    0     Failed

注意:在这里,我们也没有循环遍历行,所以它应该是有效的


推荐阅读