仅当两个其他列也是NA时,才使用值替换数据框列中的NA

时间:2018-01-03 22:14:06

标签: r tidyverse

库(tidyverse)

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

我想使用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的。)

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)

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

你的问题有一些错误,所以我的回答将尝试填补空白。例如,您提供的数据框不包含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

答案 2 :(得分:0)

此解决方案适用于任意数量的列。对于每列中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

var cellText = document.createTextNode(value);
cell.appendChild(cellText);
row.appendChild(cell);