将第一个非缺失值存储在新列中
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")
您可以使用 apply
和 which.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
使用zoo
、na.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
再见,我有几列代表分数。对于每个学生,我想获取第一个非 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")
您可以使用 apply
和 which.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
使用zoo
、na.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