R:将几列合并为一列,每行有一个值

R:将几列合并为一列,每行有一个值,r,dataframe,merge,R,Dataframe,Merge,现在我有这样一个数据帧: Z A B C D F 1 82 1 NA NA NA 77 2 454 NA 2 NA NA 18 3 606 NA NA 3 NA 12 4 55 NA NA NA 4 23 5 32 NA 2 NA NA 4 # And many more rows follows A、B、C、D列中只有一列在每行上有值,并且每列中的值相同。我想把它们合并成一列,1,2,3,4将成为这个新列的因子级别 预期结果: Z

现在我有这样一个数据帧:

   Z    A  B  C  D  F
1  82   1 NA NA NA 77
2 454  NA  2 NA NA 18
3 606  NA NA  3 NA 12
4  55  NA NA NA  4 23
5  32  NA  2 NA NA  4
# And many more rows follows
A、B、C、D列中只有一列在每行上有值,并且每列中的值相同。我想把它们合并成一列,1,2,3,4将成为这个新列的因子级别

预期结果:

   Z    A  B  C  D  F  E
1  82   1 NA NA NA 77  1
2 454  NA  2 NA NA 18  2
3 606  NA NA  3 NA 12  3
4  55  NA NA NA  4 23  4
5  32  NA  2 NA NA  4  2
# And many more rows follows
# Dropping A,B,C,D as a side-effect is OK
我曾尝试使用
ifelse
语句(
data$E=ifelse(data$A==1,5,data$A)
),但每个
ifelse
语句都会覆盖前面的修改,因此在最后,只有级别4s会写入列E

有什么优雅的方法可以合并这些列吗?删除A、B、C、D作为副作用是可以的。谢谢


编辑:如果左侧和右侧有更多不相关的列,该怎么办?是否需要某种类型的切片?(请参见编辑的代码)

我们可以使用
pmax
pmin
na.rm=TRUE

df1$E <- do.call(pmax, c(df1, na.rm=TRUE))
df1
#   A  B  C  D E
#1  1 NA NA NA 1
#2 NA  2 NA NA 2
#3 NA NA  3 NA 3
#4 NA NA NA  4 4
#5 NA  2 NA NA 2
大体上

df1[cbind(1:nrow(df1), max.col(!is.na(df1)))]
或者我们可以使用
%*%
获得每行非NA元素的列索引

(+(!is.na(df1)) %*% seq_along(df1))[,1]

如果我们使用的是
hadleyverse
,那么
合并也会有所帮助

library(dplyr)
df1 %>% 
     mutate(E = coalesce(A, B, C, D))
#   A  B  C  D E
#1  1 NA NA NA 1
#2 NA  2 NA NA 2
#3 NA NA  3 NA 3
#4 NA NA NA  4 4
#5 NA  2 NA NA 2

或另一个带有
data.table的选项

library(data.table)
setDT(df1)[, E := na.omit(unlist(.SD)) ,1:nrow(df1)]
注:此解决方案基于OP的初始示例/预期输出以及本帖的
标题
R:将多个列合并为一列,每行一个值

数据
df1只要每行只有一个值,
rowSums
就可以工作:

df$E <- rowSums(df, na.rm = TRUE)

df
##    A  B  C  D E
## 1  1 NA NA NA 1
## 2 NA  2 NA NA 2
## 3 NA NA  3 NA 3
## 4 NA NA NA  4 4
## 5 NA  2 NA NA 2

df$E谢谢,但是如果我的df中有与这个新构建的列不相关的额外列怎么办?我是否需要首先将这些列切掉以完成它?调用中的
df
子集:
rowSums(df[,2:5],na.rm=T)
谢谢,我用了一种更简单的方式
df$E,这很好。特别是如果你有很多列,用名称进行子集可以更安全、更容易混淆。
df1 <- structure(list(A = c(1L, NA, NA, NA, NA), B = c(NA, 2L, NA, NA, 
2L), C = c(NA, NA, 3L, NA, NA), D = c(NA, NA, NA, 4L, NA)), .Names = c("A", 
"B", "C", "D"), class = "data.frame", row.names = c("1", "2", 
"3", "4", "5"))
df$E <- rowSums(df, na.rm = TRUE)

df
##    A  B  C  D E
## 1  1 NA NA NA 1
## 2 NA  2 NA NA 2
## 3 NA NA  3 NA 3
## 4 NA NA NA  4 4
## 5 NA  2 NA NA 2