如何将两个包含NA值的因子合并成一个变量?

5

我有很多类似这样的变量集:

   Var1    Var2
"Asian"      NA
     NA  "Black"
"White"      NA

我希望能方便地将它们转换成这种形式:
   Race
"Asian"
"Black"
"White"

我一直在尝试类似以下的操作:

Race <- ifelse(is.na(Var1), Var2, Var1)

但这会将值转换为级别的数字,而数字不匹配(例如,这将产生1,1,2)。有没有一种方便的方法来做到这一点(理想情况下是用简短、自我解释的代码)?(您可以使用as.character来退出此操作,但肯定有更好的方法。)

你需要使用因子吗?使用字符表示,你可以这样做:pmax(Var1,Var2,na.rm=TRUE) - thelatemail
@thelatemail,我刚试过了,但对我来说并没有起作用。我需要先对所有变量应用as.character吗? - gung - Reinstate Monica
@thelatemail,如果我先使用as.character,它似乎可以工作。如果您能将其放入一个方便的函数中,我会接受它。 - gung - Reinstate Monica
使用下面答案中的dat,对na.omit(c(t(as.matrix(dat))))有何看法? - rawr
@rawr,这只是一个简化的例子。我有一个非常大的数据框,所以我不能以那种方式对其进行操作。不过这个函数还是很好用的。 - gung - Reinstate Monica
你也可以使用tidyr中的unite函数! - Colonel Beauvel
3个回答

4

通过中间转换使用as.character:
假设这是您的数据:

dat <- data.frame(Var1=c("Asian",NA,"White"),Var2=c(NA,"Black",NA))

do.call(pmax,c(lapply(dat,as.character),na.rm=TRUE))
#[1] "Asian" "Black" "White"

如果您需要处理特定的子集,您可以这样做:
do.call(pmax,c(lapply(dat[c("Var1","Var2")],as.character),na.rm=TRUE))

一个不需要使用 as.character 的替代方法如下:
dat[cbind(1:nrow(dat),max.col(!is.na(dat)))]
#[1] "Asian" "Black" "White"

实际上,我的数据框有很多像这样的变量集。因此,我不能以这种方式操作整个数据框。我编写了一个简单的函数:collapse <- function(v1, v2) pmax(as.character(v1), as.character(v2), na.rm=T),似乎可以工作。 - gung - Reinstate Monica
感谢您的帮助。 - gung - Reinstate Monica
好主意!这个方法可能更适用于需要将两列以上合并为一列的情况:apply(df[c("Var1", "Var2")], 1, max, na.rm=TRUE) - Josh O'Brien
@JoshO'Brien,在我的情况下,将始终存在2个变量。如果您想编写一个方便地扩展到>2列的函数,我会点赞的。 - gung - Reinstate Monica
@JoshO'Brien - pmax 可以很好地处理任意数量的输入 - pmax(1:3,2:4,3:5) - thelatemail
没错,知道了很棒。 - Josh O'Brien

2
这个解决方案怎么样呢?
ind <- apply(df, 1, function(x) which(!is.na(x)))
df[cbind(seq_along(ind), ind)]
[1] "Asian" "Black" "White"

这个可能可以简化为 df[cbind(seq_len(nrow(df)), is.na(df$Var1) + 1)](至少在两列的情况下)。 - jbaums

1

另一个解决方案(可能有些奇怪,但相当简洁,你的列似乎需要是字符类型):

> library(tidyr)
> unite(replace(df, is.na(df), ""), V, c(Var1, Var2), sep=''))$V
#[1] "Asian" "Black" "White"

或者,使用gsub可能存在风险,但在这种情况下,NA是字符链的一部分,因此是安全的:

> gsub("NA", "", unite(df, V, c(Var1, Var2), sep='')$V)
#[1] "Asian" "Black" "White"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接