【问题标题】:mutate with case_when - multiple LHS/RHS OR evaluations与 case_when 发生变异 - 多个 LHS/RHS OR 评估
【发布时间】:2019-08-14 23:49:56
【问题描述】:

我不确定提出这个问题的最佳方式。

我想使用 case_when(或 if_else,如果效果更好)来检查某个值是否存在于任何列范围内。

例如在 mtcars 中,我想检查任何列 vs、am、gear 或 carb 是否包含 1 或 2,如果有,则将新变量 newVar 设置为 1。我可以做到以下几点:

mtcars %>%
  mutate(newVar = case_when(vs %in% c(1, 2) | am %in% c(1, 2) | gear %in% c(1, 2) | carb %in% c(1, 2) ~ 1,
                            TRUE ~ 0))

有没有更漂亮的方法来做到这一点?我想检查超过 10 列,所以它会变长。比如:

mtcars %>%
  mutate(newVar = case_when(c(vs, am, gear, carb) %in% c(1, 2) ~ 1,
                            TRUE ~ 0))

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    我认为 base R 在这里可以很好地工作。选择您要检查的列并按行对逻辑向量求和以计算newVar

    df <- mtcars 
    cols <- c("vs", "am", "gear", "carb")
    df$newVar <- +(rowSums(df[cols] == 1 | df[cols] == 2) > 0)
    
    df
    #                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb newVar
    #Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4      1
    #Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4      1
    #Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1      1
    #Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1      1
    #Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2      1
    #Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1      1
    #Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4      0
    #Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2      1
    #Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2      1
    #Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4      1
    #....
    

    我们还可以使用apply 进行逐行操作

    df$newVar <- +(apply(df[cols] == 1 | df[cols] == 2, 1, any))
    

    【讨论】:

      【解决方案2】:

      我们可以使用tidyverse 选项来创建列

      library(dplyr)
      library(purrr)
      mtcars %>%
            mutate(newVar = select(., vs:carb) %>%
                              map(~ .x %in% 1:2) %>% 
                              reduce(`|`) %>% 
                              as.integer)
      #.   mpg cyl  disp  hp drat    wt  qsec vs am gear carb newVar
      #1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4      1
      #2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4      1
      #3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1      1
      #4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1      1
      #5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2      1
      #6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1      1
      #7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4      0
      #8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2      1
      # ...
      

      base R

      nm1 <- c("vs", "am", "gear", "carb")
      mtcars$newVar <- +(Reduce(`|`, lapply(mtcars[nm1], `%in%`, 1:2))) 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-27
        • 1970-01-01
        • 1970-01-01
        • 2018-05-31
        • 2021-01-21
        • 1970-01-01
        • 1970-01-01
        • 2018-08-18
        相关资源
        最近更新 更多