用另一列的值替换属于一列的 NA

Replace NA's belonging to one column with values from another column

我有以下数据框(命名为 'df'),列名称为 ID、org1 和 org2。

结构:

 ID  org1  org2
 1    C1   NA
 2    C2   NA
 3    C3   C3
 4    C4   C4
 5    C1   NA
 6    NA   C2
 7    NA   C4
 8    NA   NA
 9    NA   NA
 10   C3   C3

现在,我希望 org1 从 org2 获取值,以防 org1 中的 'NA' 例如:ID 6

预期输出:

 ID  org1  org2
 1    C1   NA
 2    C2   NA
 3    C3   C3
 4    C4   C4
 5    C1   NA
 6    C2   C2
 7    C4   C4
 8    NA   NA
 9    NA   NA
 10   C3   C3

我厌倦了以下内容:

   df$org1[is.na(df$org1)] <- as.character(df$org2[is.na(df$org1)])

参考如下:Replace NA in column with value in adjacent column

但这产生了以下错误:

  Warning message:
  In `[<-.factor`(`*tmp*`, is.na(df$org1),  :invalid factor level, NA generated

谁能告诉我我做错了什么,有没有更好的解决方案。

通过使用 lapply.

遍历 factor 列,将 factor 列转换为 character class
  df1[-1] <- lapply(df1[-1], as.character)

然后我们可以使用 pmaxpmax 将获取两列之间的按行最大元素。由于 'org2' 与 'org1' 几乎相同,除了 NA 值之外, pmaxna.rm=TRUE 在存在一个 NA 和非 NA 时删除 NA 元素-NA,或者如果有两个 NA return NA,或者两个非 NA 相同 return 唯一元素。

df1$org1 <- do.call(pmax, c(df1[-1], list(na.rm=TRUE)))
df1
#   ID org1 org2
#1   1   C1 <NA>
#2   2   C2 <NA>
#3   3   C3   C3
#4   4   C4   C4
#5   5   C1 <NA>
#6   6   C2   C2
#7   7   C4   C4
#8   8 <NA> <NA>
#9   9 <NA> <NA>
#10 10   C3   C3

或者使用基于is.na的逻辑索引,根据索引对'org1'进行子集,并用'org2'的对应元素替换。

 ind <- is.na(df1$org1)
 df1$org1[ind] <- df1$org2[ind] 

或者正如@David Arenburg 在评论中提到的那样,我们可以 data.table 进行更快的分配。我们将 'data.frame' 转换为 'data.table' (setDT(df1)),使用 'i' 中的逻辑条件,我们将 'org1' 赋值为 'org2' 对应'i'.

library(data.table)
setDT(df)[is.na(org1), org1 := org2]   

数据

df1 <- structure(list(ID = 1:10, org1 = structure(c(1L, 2L, 3L, 4L,   
 1L, NA, NA, NA, NA, 3L), .Label = c("C1", "C2", "C3", "C4"),
 class = "factor"), 
org2 = structure(c(NA, NA, 2L, 3L, NA, 1L, 3L, NA, NA, 2L
), .Label = c("C2", "C3", "C4"), class = "factor")), .Names = c("ID", 
"org1", "org2"), row.names = c(NA, -10L), class = "data.frame")

选项(stringsAsFactors =F) 会将所有列变成字符串(as.character)

options(stringsAsFactors = F)
mydf <- data.frame(ID = 1:10, org1 = c('C1','C2','C3','C4','C1',NA,NA,NA,NA,'C3'),
                   org2 = c(NA,NA,'C3','C4',NA,'C2','C4',NA,NA,'C3'))
mydf$org1[is.na(mydf$org1)] <- mydf$org2[is.na(mydf$org1)]