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

Store first non-missing value in a new column

再见,我有几列代表分数。对于每个学生,我想获取第一个非 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")

您可以使用 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 并且我们想要 return 第一个(which.min) FALSE 值。

不幸的是,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

使用zoona.locf,从

借用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

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

Given a set of vectors, coalesce() finds the first non-missing value at each position.

因此,你可以简化做:

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