【问题标题】:How to combine rowSums and ifelse with mutate如何将 rowSums 和 ifelse 与 mutate 结合使用
【发布时间】:2026-02-09 17:20:04
【问题描述】:

我需要结合rowSumsifelse 来创建一个新变量。我的数据如下所示:

boss var1 var2 var3 newvar
 1    NA   NA   3    NA
 1     2    3   3    8
 2    NA    NA  NA   0
 2    NA    NA  NA   0
 2    NA    NA  NA   0
 1    1     NA  2    3

如果boss==1,并且var1var3的缺失值不止一个,newvar应该是NA,否则应该是var1+var2+var3的结果

如果boss==2newvar 应自动为0

到目前为止,我已经能够使用dplyr解决部分问题:

mutate(newvar=rowSums(.[,2:4],na.rm=TRUE) +
    ifelse(rowSums(is.na(.[,2:4]))>1 & boss==2,NA,0))

mutate(newvar=ifelse(boss==2,0,NA)

但是,我正在努力将两者结合起来。非常感谢任何帮助。

【问题讨论】:

    标签: r if-statement dplyr


    【解决方案1】:

    这是case_when 的一个选项,我们在其中创建一个索引 ('i1'),它计算行中 NA 元素的数量。在case_when 中使用索引来创建分配值的逻辑条件

    df %>% 
        mutate(i1 = rowSums(is.na(.[-1]))) %>% 
        mutate(newvar = case_when(i1 > 1 & boss==1 ~ NA_integer_,
                              boss==2 ~ 0L, 
                              i1 <=1 & boss != 2~ as.integer(rowSums(.[2:4], na.rm = TRUE)))) %>%
        select(-i1)
    #   boss var1 var2 var3 newvar
    #1    1   NA   NA    3     NA
    #2    1    2    3    3      8
    #3    2   NA   NA   NA      0
    #4    2   NA   NA   NA      0
    #5    2   NA   NA   NA      0
    #6    1    1   NA    2      3
    

    base R 中,这可以通过创建索引而不使用任何ifelse 来完成

    i1 <- df$boss != 2
    tmp <- i1 * df[-1]
    df$newvar <- NA^(rowSums(is.na(tmp)) > 1 & i1) * rowSums(tmp, na.rm = TRUE)
    df$newvar
    #[1] NA  8  0  0  0  3
    

    数据

    df <- structure(list(boss = c(1L, 1L, 2L, 2L, 2L, 1L), var1 = c(NA, 
     2L, NA, NA, NA, 1L), var2 = c(NA, 3L, NA, NA, NA, NA), var3 = c(3L, 
     3L, NA, NA, NA, 2L)), .Names = c("boss", "var1", "var2", "var3"
     ), row.names = c(NA, -6L), class = "data.frame")
    

    【讨论】:

      【解决方案2】:

      base-R 中使用apply 的解决方案可以是:

      df$newvar <- apply(df,1, function(x){
        #retVal = NA
        if(x["boss"]==2){
          0
        } else if(sum(is.na(x[-1])) > 1){
          NA
        } else{
          sum(x[-1], na.rm = TRUE)
        }
      })
      
      #   boss var1 var2 var3 newvar
      # 1    1   NA   NA    3     NA
      # 2    1    2    3    3      8
      # 3    2   NA   NA   NA      0
      # 4    2   NA   NA   NA      0
      # 5    2   NA   NA   NA      0
      # 6    1    1   NA    2      3
      

      数据:

      df <- read.table(text = 
      "boss var1 var2 var3
      1    NA   NA   3    
      1     2    3   3    
      2    NA    NA  NA   
      2    NA    NA  NA   
      2    NA    NA  NA   
      1    1     NA  2",
      header = TRUE, stringsAsFactors = FALSE)
      

      【讨论】: