【问题标题】:Replace NA in a Dataframe Column with a Value Only when Two Other Columns Are Also NA仅当其他两个列也为 NA 时,才将数据框列中的 NA 替换为值
【发布时间】:2018-01-03 22:14:06
【问题描述】:

图书馆(tidyverse)

使用下面的示例数据,我试图用数字 22222 替换 Col1 中的 NA,但前提是所有三列都是 NA。所以最终结果应该只有 22222 在 Col1 中的第 4 行和第 7 行。

我想使用 tidyverse,我正在尝试以下方式:

DF%>%mutate_at(vars(Col1),funs(replace(.,if_else(is.na(one_of(Col1,Col2,Col3),22222,.)))))

示例数据:(不确定这是否是在示例数据中创建真实“NA”(与 is.na 一起使用)的正确方法?我的真实数据在 Excel 文件中有空白单元格,当转换为 CSV 并导入到 R 时,结果为 NA's。)

Col1<-c(34564,NA,43456,NA,45655,6789,99999,87667)
Col3<-c(45673,88789,11123,NA,55676,76566,NA,NA)
Col1<-c(34564,NA,43456,NA,45655,6789,NA,87667)
Col2<-c(34565,43456,55555,NA,65433,22234,NA,98909)
DF<-data_frame(ID,Col1,Col2,Col3)

【问题讨论】:

  • 您的数据框中有一些奇怪的东西。向量的创建有两个 Col1,没有 ID 变量。
  • 我假设一个Col1 作为ID。

标签: r tidyverse


【解决方案1】:

一种解决方案是使用mapply 函数。

#Define a function to replace missing row values
replMissing <- function(x, y, z){
  ifelse(is.na(x) & is.na(y) & is.na(z), 22222, x )
}
# Call mapply and pass value of Col1, Col2 and Col3
DF$Col1 <- mapply(replMissing, DF$Col1, DF$Col2, DF$Col3)

#results
> DF
# A tibble: 8 x 4
     ID  Col1  Col2  Col3
  <dbl> <dbl> <dbl> <dbl>
1 34564 34564 34565 45673
2    NA    NA 43456 88789
3 43456 43456 55555 11123
4    NA 22222    NA    NA
5 45655 45655 65433 55676
6  6789  6789 22234 76566
7 99999 22222    NA    NA
8 87667 87667 98909    NA

使用data.table,解决方案会简单得多。

DF <- data.table(DF)
DF[is.na(Col1) & is.na(Col2) & is.na(Col3), Col1 := 22222]
# Result
> DF
      ID  Col1  Col2  Col3
1: 34564 34564 34565 45673
2:    NA    NA 43456 88789
3: 43456 43456 55555 11123
4:    NA 22222    NA    NA
5: 45655 45655 65433 55676
6:  6789  6789 22234 76566
7: 99999 22222    NA    NA
8: 87667 87667 98909    NA

【讨论】:

    【解决方案2】:

    您的问题有一些错误,因此我的回答将尝试填补空白。例如,您提供的数据框不包含id。我已经修改了您的样本以使其可重现。

    library(dplyr)
    
    df <- tibble(
      id = c(34564, NA, 43456, NA, 45655, 6789, 99999, 87667),
      col1 = c(45673, 88789, 11123, NA, 55676, 76566, NA, NA),
      col2 = c(34564, NA, 43456, NA, 45655, 6789, NA, 87667),
      col3 = c(34565, 43456, 55555, NA, 65433, 22234, NA, 98909)
    )
    

    要解决单个列,您可以在正常的变异中使用 if/else。

    df %>%
      mutate(col1 = if_else(
        is.na(col1) & is.na(col2) & is.na(col3), 22222, col1
      ))
    
    # # A tibble: 8 x 4
    #      id  col1  col2  col3
    #   <dbl> <dbl> <dbl> <dbl>
    # 1 34564 45673 34564 34565
    # 2    NA 88789    NA 43456
    # 3 43456 11123 43456 55555
    # 4    NA 22222    NA    NA
    # 5 45655 55676 45655 65433
    # 6  6789 76566  6789 22234
    # 7 99999 22222    NA    NA
    # 8 87667    NA 87667 98909
    

    您的问题表明您实际上希望每一列都发生突变,而不仅仅是col1。您可以替换您开始使用的 funs(replace()) 方法,将较早的 if/else 应用于 vars 中列出的每一列。

    df %>%
      mutate_at(
        vars(col1, col2, col3),
        ~if_else(is.na(df$col1) & is.na(df$col2) & is.na(df$col3), 22222, .)
      )
    
    # # A tibble: 8 x 4
    #      id  col1  col2  col3
    #   <dbl> <dbl> <dbl> <dbl>
    # 1 34564 45673 34564 34565
    # 2    NA 88789    NA 43456
    # 3 43456 11123 43456 55555
    # 4    NA 22222 22222 22222
    # 5 45655 55676 45655 65433
    # 6  6789 76566  6789 22234
    # 7 99999 22222 22222 22222
    # 8 87667    NA 87667 98909
    

    【讨论】:

    • 谢谢,您的答案(第一部分)正是我想要的。我只有大约 5 分钟的时间来创建示例数据,因此对于 ID 列的错误,我深表歉意,但感谢您解决这个问题!
    【解决方案3】:

    此解决方案适用于任意数量的列。它将用22222 替换每一行的值,每行都是NA

    library(dplyr, warn.conflicts = FALSE)
    Col1<-c(34564,NA,43456,NA,45655,6789,99999,87667)
    Col2<-c(34565,43456,55555,NA,65433,22234,NA,98909)
    Col3<-c(45673,88789,11123,NA,55676,76566,NA,NA)
    DF<-data_frame(Col1,Col2,Col3)
    
    # Find the rows with all NA. Works with any number of column
    all_na <- DF %>%
      is.na() %>%
      apply(1, all)
    
    # Replace the value from this rows with 2222 and keep others
    DF %>%
      mutate_all(funs(if_else(all_na, 22222, .)))
    #> # A tibble: 8 x 3
    #>    Col1  Col2  Col3
    #>   <dbl> <dbl> <dbl>
    #> 1 34564 34565 45673
    #> 2    NA 43456 88789
    #> 3 43456 55555 11123
    #> 4 22222 22222 22222
    #> 5 45655 65433 55676
    #> 6  6789 22234 76566
    #> 7 99999    NA    NA
    #> 8 87667 98909    NA
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-21
      • 1970-01-01
      相关资源
      最近更新 更多