我有以下数据框(名为'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
有人可以告诉我我做错了什么,是否有更好的解决方案。
答案 0 :(得分:2)
使用factor
循环遍历character
列,将factor
列转换为lapply
类。
df1[-1] <- lapply(df1[-1], as.character)
然后我们可以使用pmax
。 pmax
将获得两列之间的行方向最大元素。由于'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)]