首页 > 解决方案 > 在多列上使用 ifelse 条件

问题描述

我想生成变量来检查特定事件是否在多个条件下发生。下面是一个示例数据框。

df <- data.frame(
    index = c(1:20),
    con1 = c(1,3,2,4,2,7,5,9,1,2,5,6,1,0,8,0,4,5,7,3),
    con2 = c(3,5,1,6,3,4,7,3,2,1,5,7,9,1,4,2,4,3,4,3),
    con3 = c(2,7,3,4,1,9,4,0,7,0,5,2,7,5,9,3,5,2,1,2))

实际数据集有 20 个条件 [con*] 和 10 种不同的事件类型([con*] 中的每个数字。

我现在正在做的是使用这样一个乏味的命令;

df %>% mutate (Event1 = ifelse (con1==1 | con2==1 | con3==1,1,0))
df %>% mutate (Event2 = ifelse (con1==2 | con2==2 | con3==2,1,0))
...

它正是我想要得到的。但是,您可以想象这在脚本中有多少混乱,有 20 个条件和 10 个不同的事件。你知道我怎样才能使它整洁吗?

标签: rif-statementconditional-statements

解决方案


哈克,

library(dplyr)
library(purrr) # map_dfc
events <- setNames(1:4, paste0("Event", 1:4))
df %>%
  bind_cols(map_dfc(events, ~ +(rowSums(df[,-1] == .) > 0))) %>%
  head()
#   index con1 con2 con3 Event1 Event2 Event3 Event4
# 1     1    1    3    2      1      1      1      0
# 2     2    3    5    7      0      0      1      0
# 3     3    2    1    3      1      1      1      0
# 4     4    4    6    4      0      0      0      1
# 5     5    2    3    1      1      1      1      0
# 6     6    7    4    9      0      0      0      1

这在没有purrr::map_dfc, with 的情况下有效

library(dplyr)
df %>%
  bind_cols(lapply(events, function(ev) +(rowSums(df[,-1] == ev) > 0)))

# or even juset
cbind(df, lapply(events, function(ev) +(rowSums(df[,-1] == ev) > 0)))

使用df[,-1]的前提是您正在处理除第一列之外的所有列。它也可以用一些 tidyverse 动词 ( select(df, starts_with("con"))) 代替,以达到相同的效果。

这个答案的基本机制是使用rowSumsand ==df == ev返回一个逻辑矩阵。现在有了一个真/假矩阵,我们可以寻找行和,其中 false=0 和 true=1。这样一来,任何大于 0 的总和都意味着至少有一列是正确的。

+(...)是将逻辑转换为整数的快速技巧。


推荐阅读