假设我有一个根据以下代码生成的数据帧df
。
set.seed(1)
x1<-data.frame(cbind(paste("I",sample(1:10,3),sep=""), sample(50:80,3)))
x2<-data.frame(cbind(paste("I",sample(1:10,3),sep=""), sample(50:80,3)))
x3<-data.frame(cbind(paste("I",sample(1:10,3),sep=""), sample(50:80,3)))
df<-Reduce(function(x,y) merge(x,y, by="X1", all=T), list(x1,x2,x3))
colnames(df)<-c("ID","X1","X2","X3")
> df
ID X1 X2 X3
1 I3 78 <NA> <NA>
2 I4 56 <NA> 71
3 I5 76 <NA> <NA>
4 I10 <NA> 51 78
5 I6 <NA> 56 <NA>
6 I9 <NA> 55 <NA>
7 I7 <NA> <NA> 65
X1中的值是最旧的,而X3中的值是最新的。我需要的是一个数据框,其中的值从最旧的到最新的,而忽略了NA。我想要的数据框看起来像
ID NewX
1 I3 78
2 I4 71
3 I5 76
4 I10 78
5 I6 56
6 I9 55
7 I7 65
尽管在此示例中只有三个变量,但我的真实数据有15个以上的变量。因此,我试图避免手动更新。任何想法将不胜感激。谢谢。
答案 0 :(得分:1)
我们可以使用row/column
索引提取值。使用max.col
(将ties.method
指定为“ last”)获取每行非NA元素的列索引,cbind
行索引(即行序列)并提取匹配元素这些索引cbind
和第一列(即“ ID”列)的数据集
cbind(df[1], NewX = df[-1][cbind(seq_len(nrow(df)),
max.col(!is.na(df[-1]), "last"))])
# ID NewX
#1 I3 78
#2 I4 71
#3 I5 76
#4 I10 78
#5 I6 56
#6 I9 55
#7 I7 65
或将tidyverse
与coalesce
一起使用
library(tidyverse)
df %>%
mutate_at(2:4, funs(as.numeric(as.character(.)))) %>% # change factor class
transmute(ID, NewX = coalesce(X3, X2, X1))
# if there are many columns, convert the column names to symbol and evaluate
# transmute(ID, NewX = coalesce(!!! rlang::syms(names(.)[4:2])))
# ID NewX
#1 I3 78
#2 I4 71
#3 I5 76
#4 I10 78
#5 I6 56
#6 I9 55
#7 I7 65