根据r中相同数据框中其他两列的值添加列

时间:2017-06-19 01:30:29

标签: r dataframe

假设我有一个数据框,其中包含三个变量,我想添加第四个变量,其值基于第二个和第三个变量的值,例如。如果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,但我没有成功。

有什么想法吗?

4 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分: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))
来自if_else包的

dplyr将处理缺少号码(NA)的情况

答案 2 :(得分:1)

一些选项:

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而不是检查相等。< / p>

更多创意基本选项包括将列粘贴在一起以创建一个可以故意调整为强制到整数的因子:

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

答案 3 :(得分:1)

使用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)