在多列上应用相同标准来计算新列

时间:2017-08-01 09:17:02

标签: r dplyr data-manipulation tidyr

我有一个类似于下面的数据框,除了我有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)

我想创建一个新列,输出&#34;是&#34;如果17个变量中的任何一个具有值1,2或3,并且&#34; No&#34;除此以外。我想要的输出是:

# 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))

4 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

我们可以使用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

答案 2 :(得分:1)

一个选项如下:

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)。希望这会有所帮助。

答案 3 :(得分:1)

你可以添加所有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