将属于一列的NA替换为另一列中的值

时间:2015-11-09 10:14:23

标签: r dataframe missing-data

我有以下数据框(名为'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

有人可以告诉我我做错了什么,是否有更好的解决方案。

2 个答案:

答案 0 :(得分:2)

使用factor循环遍历character列,将factor列转换为lapply类。

  df1[-1] <- lapply(df1[-1], as.character)

然后我们可以使用pmaxpmax将获得两列之间的行方向最大元素。由于'org2'与'org1'几乎完全相同,但NA值除外,pmax na.rm=TRUE当有一个NA且非NA时删除NA​​元素,或者如果有两个NA返回NA,或者两个非NA相同则返回唯一元素。

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")

答案 1 :(得分:0)

选项(stringAsFactors = 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)]