将第一个非缺失值存储在新列中

时间:2018-09-13 01:21:59

标签: r extract apply

Ciao,我有几列代表分数。对于每个学生,我要获取第一个非NA分数并将其存储在名为TEST的新列中。

这是我的复制示例。这是我现在拥有的数据:

df <- data.frame(STUDENT=c(1,2,3,4,5), 
                 CLASS=c(90,91,92,93,95),
                 SCORE1=c(10,NA,NA,NA,NA), 
                 SCORE2=c(2,NA,8,NA,NA), 
                 SCORE3=c(9,6,6,NA,NA),
                 SCORE4=c(NA,7,5,1,9),
                 ROOM=c(01,02, 03, 04, 05))

这是我要添加的列:

df$FIRST <- c(10,6,8,1,9)

这是我的尝试:

df$FIRSTGUESS <- max.col(!is.na(df[3:6]), "first")

4 个答案:

答案 0 :(得分:2)

您可以使用applywhich.min(is.na(...))

df$FIRSTGUESS <- apply(df[, grep("^SCORE", names(df))], 1, function(x) 
    x[which.min(is.na(x))])
df
#  STUDENT CLASS SCORE1 SCORE2 SCORE3 SCORE4 ROOM FIRSTGUESS
#1       1    90     10      2      9     NA    1         10
#2       2    91     NA     NA      6      7    2          6
#3       3    92     NA      8      6      5    3          8
#4       4    93     NA     NA     NA      1    4          1
#5       5    95     NA     NA     NA      9    5          9

请注意,我们需要is.na而不是!is.na,因为FALSE对应于0,并且我们想返回第一个(which.min){{1} }值。

答案 1 :(得分:2)

这正是软件包coalesce中的dplyr所做的。如其文档中所述:

  

给定一组向量,coalesce()找到第一个非缺失值   在每个位置。

因此,您可以简化操作:

library(dplyr)
df$FIRST <- do.call(coalesce, df[grepl('SCORE', names(df))])

这是结果:

> df
  STUDENT CLASS SCORE1 SCORE2 SCORE3 SCORE4 ROOM FIRST
1       1    90     10      2      9     NA    1    10
2       2    91     NA     NA      6      7    2     6
3       3    92     NA      8      6      5    3     8
4       4    93     NA     NA     NA      1    4     1
5       5    95     NA     NA     NA      9    5     9

答案 2 :(得分:1)

不幸的是,max.col给出最大值的索引,而不是值本身。但是,我们可以使用mapply调用来对原始数据帧中的值进行子集化。

#Select only columns which has "SCORE" in it
sub_df <- df[grepl("SCORE", names(df))]

#Get the first non-NA value by row 
inds <- max.col(!is.na(sub_df), ties.method = "first")

#Get the inds value by row
df$FIRSTGUESS <- mapply(function(x, y) sub_df[x,y], 1:nrow(sub_df), inds)

df

#  STUDENT CLASS SCORE1 SCORE2 SCORE3 SCORE4 ROOM FIRST FIRSTGUESS
#1       1    90     10      2      9     NA    1    10         10
#2       2    91     NA     NA      6      7    2     6          6
#3       3    92     NA      8      6      5    3     8          8
#4       4    93     NA     NA     NA      1    4     1          1
#5       5    95     NA     NA     NA      9    5     9          9

答案 3 :(得分:0)

使用zoona.locf,从Ronak借用sub_df

 df['New']=zoo::na.locf(t(sub_df),fromLast=T)[1,]
 df
  STUDENT CLASS SCORE1 SCORE2 SCORE3 SCORE4 ROOM New
1       1    90     10      2      9     NA    1  10
2       2    91     NA     NA      6      7    2   6
3       3    92     NA      8      6      5    3   8
4       4    93     NA     NA     NA      1    4   1
5       5    95     NA     NA     NA      9    5   9