在一行中用零替换初始 NA 值,直到非 NA 列

Replace initial NA values with zero in a row until non NA column

考虑数据集中的以下行:-

#Row (initially):
NA NA NA NA NA NA NA 2 3 1 4 5 2 NA NA 6 7

我希望将所有此类行转换为

#Row  (modified) :
0  0  0  0  0  0  0 2 3 1 4 5 2 NA NA 6 7

只有出现在任何非 na 值之前的初始 NA 才会被零替换,而不是之后出现的那些。

编辑:我的数据是矩阵,例子:

NA   NA   NA   NA    1    1    1    1    1     1
NA   NA   NA   NA    1    1    1    1    1     1
NA   NA   NA   NA    1    1    1    1    1     1
NA   NA   NA   NA   NA   NA   NA    1   NA     1
NA   NA   NA   NA   NA   NA   NA    1   NA     1
NA   NA   NA   NA   NA   NA   NA   NA   NA     1
1    1    1    1    1    1    1    1   NA     1
1    1    1    1    1    1    1    1    1     1

应该修改为

0    0    0    0    1    1    1    1    1     1
0    0    0    0    1    1    1    1    1     1
0    0    0    0    1    1    1    1    1     1
0    0    0    0    0    0    0    1   NA     1
0    0    0    0    0    0    0    1   NA     1
0    0    0    0    0    0    0    0    0     1
1    1    1    1    1    1    1    1   NA     1
1    1    1    1    1    1    1    1    1     1

对于更新的示例:

我们可以按行使用 applyreplace 0 的值,直到第一次出现非 NA 值。

t(apply(mat, 1, function(x) replace(x, cumsum(!is.na(x)) == 0, 0)))


#     V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
#[1,]  0  0  0  0  1  1  1  1  1   1
#[2,]  0  0  0  0  1  1  1  1  1   1
#[3,]  0  0  0  0  1  1  1  1  1   1
#[4,]  0  0  0  0  0  0  0  1 NA   1
#[5,]  0  0  0  0  0  0  0  1 NA   1
#[6,]  0  0  0  0  0  0  0  0  0   1
#[7,]  1  1  1  1  1  1  1  1 NA   1
#[8,]  1  1  1  1  1  1  1  1  1   1

原答案

我们可以一起使用 whichmin 来找到第一个非 NA 值的索引,并将这些值替换为 0。

x[1:min(which(!is.na(x))) - 1] <- 0
x
#[1]  0  0  0  0  0  0  0  2  3  1  4  5  2 NA NA  6  7

which.max

x[1:which.max(!is.na(x)) - 1] <- 0

和最简单的which.min

x[1:which.min(is.na(x)) - 1] <- 0

数据

x <- c(NA, NA, NA, NA, NA, NA, NA, 2, 3, 1, 4, 5, 2, NA, NA, 6, 7)

定义一个函数并使用apply。这是一个工作示例。该函数只是测试逻辑值的累积和是否在增加。

x<-c(NA,NA,NA,NA,1,0,NA,NA,3)
    y<-c(2,NA,3,NA,1,0,NA,2,3)
    z<-c(NA,NA,3,NA,1,0,NA,NA,3)
    df<-data.frame(x,y,z)


    initialNA<-function(x){
      index<-cumsum(is.na(x))>=seq_along(x)
      x[index]<-0
      x
    }

    df2<-data.frame(t(apply(df,1,initialNA)))

使用cummin:

x[cummin(is.na(x))==1] <- 0

#[1]  0  0  0  0  0  0  0  2  3  1  4  5  2 NA NA  6  7

cumprod也可以用

至于你的编辑,对整个矩阵做同样的事情说 m:

t(apply(m,1,function(x) replace(x, cummin(is.na(x))==1, 0)))

    # [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]    0    0    0    0    1    1    1    1    1     1
# [2,]    0    0    0    0    1    1    1    1    1     1
# [3,]    0    0    0    0    1    1    1    1    1     1
# [4,]    0    0    0    0    0    0    0    1   NA     1
# [5,]    0    0    0    0    0    0    0    1   NA     1
# [6,]    0    0    0    0    0    0    0    0    0     1
# [7,]    1    1    1    1    1    1    1    1   NA     1
# [8,]    1    1    1    1    1    1    1    1    1     1

这是 rle() 的解决方案:

x <- c(NA, NA, NA, NA, NA, NA, NA, 2, 3, 1, 4, 5, 2, NA, NA, 6, 7)
if (is.na(x[1])) x[1:rle(is.na(x))$lengths[1]] <- 0
x

对于按行应用:

f <- function(x) {
    if (is.na(x[1])) x[1:rle(is.na(x))$lengths[1]] <- 0
    x
}
apply(yourMatrix, 1, f)

最终您必须转置结果,因为 apply() 根据矩阵的行逐列构造结果:

t(apply(yourMatrix, 1, f))

带有 zoo 包:

zoo 中有一个函数用于此任务:

x <- c(NA, NA, NA, NA, NA, NA, NA, 2, 3, 1, 4, 5, 2, NA, NA, 6, 7)
library("zoo")
na.fill(x, c(0,NA,NA))