在一行中用零替换初始 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
对于更新的示例:
我们可以按行使用 apply
和 replace
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
原答案
我们可以一起使用 which
和 min
来找到第一个非 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))
考虑数据集中的以下行:-
#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
对于更新的示例:
我们可以按行使用 apply
和 replace
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
原答案
我们可以一起使用 which
和 min
来找到第一个非 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))