dplyr:case_when()在具有多个条件的多个列上

时间:2019-02-06 16:05:30

标签: r dplyr

我已经做了一个最小的可复制示例,以例证我的问题。我已经设法解决了这个问题,但是我敢肯定,有更优雅的编码方法。

问题是关于基于多个标准的二进制分类。为了获得甜甜圈(编码1),至少需要获得3分(或更高分)的评分:“ a”标准项中的至少一项,“ b”标准项中的至少两项以及“ c”标准中的至少三种标准项目。如果不满足这些要求,则不会颁发甜甜圈(编码为0)。

这是我的解决方案。您将如何更简洁/优雅地编写代码?

require(dplyr)
df <- data.frame("a1" = c(3,2,2,5), 
                 "a2" = c(2,1,3,1),
                 "b1" = c(2,1,5,4),
                 "b2" = c(1,2,1,4),
                 "b3" = c(3,2,3,4),
                 "c1" = c(3,3,1,3),
                 "c2" = c(4,2,3,4),
                 "c3" = c(3,3,4,1),
                 "c4" = c(1,2,3,4),
stringsAsFactors = FALSE)

df_names <- names(df[, 1:9])
a_items <- names(df[, 1:2])
b_items <- names(df[, 3:5])
c_items <- names(df[, 6:9])

df_response <-  df %>% 
  select(df_names) %>% 
  mutate_all(
    funs(case_when(
      . >=3 ~ 1,
      is.na(.) ~ 0,
      TRUE  ~  0))) %>% 

  mutate(a_crit = case_when( rowSums(.[ ,a_items]) >=1 ~ 1,    # one a item needed
                             TRUE  ~  0)) %>% 
  mutate(b_crit = case_when( rowSums(.[ ,b_items]) >=2 ~ 1,    # two b items needed
                             TRUE  ~  0)) %>% 
  mutate(c_crit = case_when( rowSums(.[ ,c_items]) >=3 ~ 1,    # three c items needed
                             TRUE  ~  0)) %>% 
  mutate(overal_crit = case_when( a_crit == 1 & b_crit == 1 & c_crit == 1 ~ 1,
                                  TRUE  ~  0)) 

df_response$overal_crit

3 个答案:

答案 0 :(得分:2)

我将通过简单的public class YourModule extends ReactContextBaseJavaModule { Timer tim = new Timer(); public void startTimer() { tim.cancel(); tim = new Timer(); tim.scheduleAtFixedRate( new TimerTask() { public void run() { // Run tasks } }, 0, 1000); } } 通话

mutate

答案 1 :(得分:1)

df %>% 
   mutate(over_all=if_else(rowSums(.[grepl('a',names(.))]>=3)>=1 & 
                           rowSums(.[grepl('b',names(.))]>=3)>=2 & 
                           rowSums(.[grepl('c',names(.))]>=3)>=3, 1, 0))

答案 2 :(得分:0)

如果我们有几个名称列表,那么使用map

会更容易
library(tidyverse)
map2_dfc(list(a_items, b_items, c_items), 1:3, ~  
          df[.x]  %>% 
             {+(rowSums(. >= 3) >= .y)}) %>%
      rename_all(~ paste0(letters[1:3], "_crit")) %>% 
      mutate(overal_crit = +(rowSums(.)==3) ) %>%
      bind_cols(df, .)
#  a1 a2 b1 b2 b3 c1 c2 c3 c4 a_crit b_crit c_crit overal_crit
#1  3  2  2  1  3  3  4  3  1      1      0      1           0
#2  2  1  1  2  2  3  2  3  2      0      0      0           0
#3  2  3  5  1  3  1  3  4  3      1      1      1           1
#4  5  1  4  4  4  3  4  1  4      1      1      1           1

注意:此处的代码行数不会随用于比较的不同向量的数量而改变


或与base R一起使用Map方法

lst1 <- Map(function(x, y) rowSums(df[x] >= 3) >= y, 
        list(a_items, b_items, c_items), 1:3)
df[paste0(c(letters[1:3], "overall"),  "_crit")] <- c(lst1, list(Reduce(`&`, lst1)))