【问题标题】:Add a column based on the values of other two columns in the same data frame in r根据r中同一数据框中其他两列的值添加一列
【发布时间】:2017-11-21 02:41:45
【问题描述】:

假设我有一个包含三个变量的数据框,我想添加第四个变量,其值基于第二个和第三个变量的值,例如。如果 var2 = var3 则 var4 = 3,如果 var2 = Y 且 var3 = NA 则 var4 = 1,如果 var2 = NA 且 var3 = Y 则 var4 = 2。

var1 var2 var3
m01  Y    NA    
m02  Y    NA
m03  NA   Y
m04  NA   Y
m05  Y    Y
m06  Y    NA
m07  Y    Y

我想得到一个这样的数据框:

var1 var2 var3 var4
m01  Y    NA   1
m02  Y    NA   1
m03  NA   Y    2
m04  NA   Y    2
m05  Y    Y    3
m06  Y    NA   1
m07  Y    Y    3

我正在尝试使用ifelse,但没有成功。

有什么想法吗?

【问题讨论】:

  • df$var4 <- apply(df[-1], 1, function(x){sum(which(x == 'Y'))})
  • This 的帖子可能会帮助您了解如何使用嵌套的ifelse

标签: r dataframe


【解决方案1】:

每个人都忘记了可怜的老interaction

c(3,2,1,4)[interaction(lapply(dat[-1], is.na))]
#[1] 1 1 2 2 3 1 3

【讨论】:

  • 只需一点点工作,您就可以使关卡对齐:as.integer(interaction(lapply(df[-1], Negate(is.na)), drop = TRUE))
  • @alistaire - 不错的变化。我特别喜欢 Negate 用于嵌套函数,因此您不必明确地执行 function(x) !is.na(x)。我从来没有用过那个。
【解决方案2】:

试试这个:

library(dplyr)
df <- data.frame(var1 = paste0("m0",1:7), 
             var2 = c(rep("Y",2) ,rep(NA, 2), rep("Y", 3)),
             var3 = c(rep(NA, 2), rep("Y", 3), NA, "Y"))
mutate(df, var4 = if_else(var2 ==  "Y", 
                      if_else(var3 == "Y", 3, 1,1), 
                      2, 2))

dplyr 包中的if_else 也将处理丢失数字 (NA) 的情况

【讨论】:

    【解决方案3】:

    使用 ifelse:

    df$var4 <- ifelse(df$var2 == df$var3, 3, 
                 ifelse(df$var3 == "NA" & df$var2 == "y", 1, 
                   ifelse(df$var2 == "NA" & df$var3 == "y", 2, "?")))
    

    如果“NA”是因子值,则有效。否则将df$var3 == "NA" 替换为is.na(df$var3),将df$var2 == "NA" 替换为is.na(df$var2)

    【讨论】:

      【解决方案4】:

      一些选项:

      df <- read.table(text = 'var1 var2 var3
      m01  Y    NA    
      m02  Y    NA
      m03  NA   Y
      m04  NA   Y
      m05  Y    Y
      m06  Y    NA
      m07  Y    Y', head = TRUE, stringsAsFactors = FALSE)
      

      典型的基本 R 方法是 apply 在必要的列中逐行迭代。这是在默默地强制转换为矩阵,这就是为什么有些人会避免这种方法。

      apply(df[-1], 1, function(x){sum(which(x == 'Y'))})
      #> [1] 1 1 2 2 3 1 3
      

      您可以使用 rowwise 将其转换为 dplyr,它不会强制转换为矩阵,但通常不是最快的方法:

      library(dplyr)
      
      df %>% 
          rowwise() %>% 
          mutate(var4 = sum(which(c(var2, var3) == 'Y')))
      #> Source: local data frame [7 x 4]
      #> Groups: <by row>
      #> 
      #> # A tibble: 7 x 4
      #>    var1  var2  var3  var4
      #>   <chr> <chr> <chr> <int>
      #> 1   m01     Y  <NA>     1
      #> 2   m02     Y  <NA>     1
      #> 3   m03  <NA>     Y     2
      #> 4   m04  <NA>     Y     2
      #> 5   m05     Y     Y     3
      #> 6   m06     Y  <NA>     1
      #> 7   m07     Y     Y     3
      

      对于因子(通过c 将其转换为整数),这也将失败,但可以预先或在内部强制它们,或者您可以使用is.na 而不是检查相等性。

      更多创造性的基本选项包括将列粘贴在一起以创建一个可以故意平衡以强制转换为整数的因子:

      as.integer(factor(paste0(df$var2, df$var3), levels = c('YNA', 'NAY', 'YY')))
      #> [1] 1 1 2 2 3 1 3
      

      或使用do.call 将函数列表和df 的每个所需变量(用c 展平)传递给mapply

      do.call(mapply, 
              c(function(...){sum(which(!is.na(c(...))))}, 
                df[-1], 
                USE.NAMES = FALSE))
      #> [1] 1 1 2 2 3 1 3
      

      如果你真的想要 ifelse 逻辑,dplyr::case_when 让你可以使用级联条件句,而不会使用混乱的语法:

      df %>% mutate(var4 = case_when(var2 == 'Y' & var3 == 'Y' ~ 3,
                                     var2 == 'Y' ~ 1, 
                                     var3 == 'Y' ~ 2))
      #>   var1 var2 var3 var4
      #> 1  m01    Y <NA>    1
      #> 2  m02    Y <NA>    1
      #> 3  m03 <NA>    Y    2
      #> 4  m04 <NA>    Y    2
      #> 5  m05    Y    Y    3
      #> 6  m06    Y <NA>    1
      #> 7  m07    Y    Y    3
      

      【讨论】:

        猜你喜欢
        • 2022-08-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多