R- 在第一个 NA 之后用 NA 替换数据帧行中的所有值

R- Replace all values in rows of dataframe after first NA by NA

我有一个包含 3500 个观测值和 278 个变量的数据框。对于从第一列开始的每一行,我想用 NA 替换第一个 NA 之后出现的所有值。例如,我想从这样的数据框开始:

X1 X2 X3 X4 X5
 1  3 NA  6  9
 1 NA  4  6 18
 6  7 NA  3  1 
10  1  2 NA  2 

类似于

X1 X2 X3 X4 X5
 1  3 NA NA NA
 1 NA NA NA NA
 6  7 NA NA NA 
10  1  2 NA NA   

我尝试使用以下嵌套 for 循环,但它没有终止:

for(i in 2:3500){
 firstna <- min(which(is.na(df[i,])))
 df[i, firstna:278] <- NA
}

有没有更有效的方法来做到这一点?提前致谢。

你可以这样做:

# sample data
mat <- matrix(1, 10, 10)
set.seed(231)
mat[sample(100, 7)] <- NA

您可以将 applycumsumis.na 一起使用来跟踪需要放置 NA 的位置(即跨行放置 NA 的累积总和大于0).然后,使用这些位置将 NA 分配给适当位置的原始结构。

mat[t(apply(is.na(mat), 1, cumsum)) > 0 ] <- NA
#     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]    1    1    1    1    1    1   NA   NA   NA    NA
# [2,]   NA   NA   NA   NA   NA   NA   NA   NA   NA    NA
# [3,]    1    1    1    1    1    1    1    1    1     1
# [4,]    1    1    1    1    1    1    1    1    1     1
# [5,]    1    1    1   NA   NA   NA   NA   NA   NA    NA
# [6,]    1    1    1    1    1    1    1    1    1     1
# [7,]    1   NA   NA   NA   NA   NA   NA   NA   NA    NA
# [8,]    1    1    1    1    1    1    1    1    1     1
# [9,]    1    1    1    1    1    1    1    1    1     1
#[10,]    1    1   NA   NA   NA   NA   NA   NA   NA    NA

适用于数据框。使用提供的示例数据:

d<-read.table(text="
X1 X2 X3 X4 X5
 1  3 NA  6  9
 1 NA  4  6 18
 6  7 NA  3  1 
10  1  2 NA  2 ", header=TRUE)

d[t(apply(is.na(d), 1, cumsum)) > 0 ] <- NA
#  X1 X2 X3 X4 X5
#1  1  3 NA NA NA
#2  1 NA NA NA NA
#3  6  7 NA NA NA
#4 10  1  2 NA NA

我们可以使用 rowCumsumslibrary(matrixStats)

library(matrixStats)
d*NA^rowCumsums(+(is.na(d)))
#  X1 X2 X3 X4 X5
#1  1  3 NA NA NA
#2  1 NA NA NA NA
#3  6  7 NA NA NA
#4 10  1  2 NA NA

或者base R选项是

d*NA^do.call(cbind,Reduce(`+`,lapply(d, is.na), accumulate=TRUE))

我使用 dplyr 包中的 cumany 函数完成此操作,满足条件后每个元素都 returns TRUE

df <- read.table(text = "X1 X2 X3 X4 X5
                         1  3 NA  6  9
                         1 NA  4  6 18
                         6  7 NA  3  1 
                         10  1  2 NA  2 ",
                 header = T)

library(plyr)
library(dplyr)

na_row_replace <- function(x){
  x[which(cumany(is.na(x)))] <- NA
  return(x)
}

adply(df, 1, na_row_replace)