用所需值替换连续的零

Replacing consecutive zeros with a desired value

假设我有一个

形式的矩阵(或向量)
>set.seed(1)
>X=ifelse(matrix((runif(30)),ncol = 2)>0.4,0,1)

      [,1] [,2]
 [1,]    1    1
 [2,]    1    1
 [3,]    0    1
 [4,]    0    0
 [5,]    1    1
 [6,]    0    0
 [7,]    0    0
 [8,]    0    0
 [9,]    0    1
[10,]    1    0
[11,]    1    0
[12,]    1    0
[13,]    0    1
[14,]    1    0
[15,]    0    0
    ...
    etc

我如何计算每列中 1 之间的连续零的数量,并用 1 替换那些计数小于预定义常量 k 的零。或者至少获取每个零序列中的起始索引和元素数。 一般这个数据集中0的个数比1的多很多,而且大多数时候一个序列的长度都大于k

因此,例如,如果 k=1,则 [4,2];[13,1] 和 [15,1] 将被 1 替换。如果 k=2 除了 [ 4,1];[13,1] 和 [15,1],[3,1]、[4,1]、[14,2] 和 [15,2] 中的零将被 1 替换在这个例子中也是如此。

当然,我可以 运行 一个循环遍历所有行。我想知道是否有一个包或一个巧妙的矢量化技巧可以做到这一点。

Update:

k=1 的期望输出示例

      [,1] [,2]
 [1,]    1    1
 [2,]    1    1
 [3,]    0    1
 [4,]    0    1
 [5,]    1    1
 [6,]    0    0
 [7,]    0    0
 [8,]    0    0
 [9,]    0    1
[10,]    1    0
[11,]    1    0
[12,]    1    0
[13,]    1    1
[14,]    1    0
[15,]    1    0

k=2 的期望输出

      [,1] [,2]
 [1,]    1    1
 [2,]    1    1
 [3,]    1    1
 [4,]    1    1
 [5,]    1    1
 [6,]    0    0
 [7,]    0    0
 [8,]    0    0
 [9,]    0    1
[10,]    1    0
[11,]    1    0
[12,]    1    0
[13,]    1    1
[14,]    1    1
[15,]    1    1

运行 长度工具 rle 在这里工作:

fill_shortruns <- function(X,k=1,badval=0,newval=1){
    apply(X,2,function(x){
        r <- rle(x)
        r$values[ r$lengths <= k & r$values == badval ] <- newval
        inverse.rle(r)
    })
}

# smaller example

set.seed(1)
X0=ifelse(matrix((runif(10)),ncol = 2)>0.4,0,1)
#      [,1] [,2] [,3] [,4]
# [1,]    1    0    1    0
# [2,]    1    0    1    0
# [3,]    0    0    0    0
# [4,]    0    0    1    1
# [5,]    1    1    0    0

fill_shortruns(X0,2)
#      [,1] [,2] [,3] [,4]
# [1,]    1    0    1    0
# [2,]    1    0    1    0
# [3,]    1    0    1    0
# [4,]    1    0    1    1
# [5,]    1    1    1    1