对多列应用相同的条件来计算新列

Applying The Same Criteria Over Many Columns to Compute a New Column

我有一个类似于下面的数据框,除了我有 17 个变量(如 Var1Var2)而不是 2 个。

df <- read.table(header = TRUE, text = 
          "STUD_ID       Var1   Var2
                 1          0      0
                 1          0      1
                 2          1      2
                 3          3      0", stringsAsFactors = FALSE)

我想创建一个新列,如果 17 个变量中的任何一个的值为 1、2 或 3,则输出 "Yes",否则输出 "No"。我想要的输出是:

# STUD_ID       Var1   Var2  Output
#       1          0      0    "No"
#       1          0      1   "Yes"
#       2          1      2   "Yes"
#       3          3      0   "Yes"

我尝试了以下代码,但它给出了错误,我不想将部分代码复制粘贴 17 次:

df %>%
  mutate(output = if_else(var1 %in% 1:3 |
                          var2 %in% 1:3, 1, 0))

一个选项如下:

df$Output = sapply(seq(1,nrow(df)), 
          function(x) {ifelse(any(df[x,c(2:3)] %in% c(1,2,3)),"Yes","No")})

您可以将 c(2:3) 替换为您的列索引范围或包含列名的数组。希望这有帮助。

尝试尽可能矢量化(但仍然不如转换为字符串的效率)的一种方法是使用 do.call 粘贴行和 grepl 您需要的值, 即

ifelse(grepl('1|2|3', do.call(paste0, df[-1])), 'Yes', 'No')
#[1] "No"  "Yes" "Yes" "Yes"

我们可以使用base R

df$Output <- c("No", "Yes")[Reduce(`|`, lapply(df[-1], `%in%`, 1:3)) + 1]
df$Output
#[1] "No"  "Yes" "Yes" "Yes"

或者用tidyverse

library(tidyverse)
df %>% 
    mutate_at(vars(matches("Var")), funs(. %in% 1:3)) %>%
    select(-STUD_ID) %>% 
    reduce( `|`) %>% {c('No', 'Yes')[. + 1]} %>% 
    mutate(df, output = .)
#   STUD_ID Var1 Var2 output
#1       1    0    0     No
#2       1    0    1    Yes
#3       2    1    2    Yes
#4       3    3    0    Yes

你可以把这17个变量全部相加,如果sum大于0,说明至少有一个非零值

> df$VarNew=df$Var1+df$Var2
> df
  STUD_ID Var1 Var2 VarNew
1       1    0    0      0
2       1    0    1      1
3       2    1    2      3
4       3    3    0      3
> df$VarNew2=ifelse(df$VarNew>0,"Yes","No")
> df
  STUD_ID Var1 Var2 VarNew VarNew2
1       1    0    0      0      No
2       1    0    1      1     Yes
3       2    1    2      3     Yes
4       3    3    0      3     Yes