我有一个0
s和1
s的向量,并且希望识别一个0
s的字符串被1
s包围的索引。如果1
s之间的0
s的个数小于或等于5,我想将这些零改为1
s。
下面是一个示例:
> x <- c(0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1)
在位置7,8和9中,我只有三个零,因此这些都需要改变为1。其他的零大于5,因此不需要改变。
生成的向量应该如下所示:
> x_converted <- c(0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1)
我是用一个for
循环和if else
语句来完成这个任务的,但是我确信必须有一个更快的方法来做到这一点。
谢谢。
发布于 2022-02-03 15:36:22
一种可能的rle
解决方案,在x
的开头或结尾不改变0的短序列
# create the run length encoding
r <- rle(x)
# create an index of which zero's should be changed
i <- r$values == 0 & r$lengths < 5 &
c(tail(r$values, -1) == 1, FALSE) &
c(FALSE, head(r$values, -1) == 1)
# set the appropriate values to 1
r$values[i] <- 1
# use the inverse of rle to recreate the vector
inverse.rle(r)
这意味着:
[1] 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1
发布于 2022-02-03 15:32:19
您可以使用rle()
来获取运行。然后根据运行的长度更改它,不包括第一次运行,只需查看cumprod()
即可。
x_rle <- rle(x)
x_0 <- cumprod(x_rle$values == 0)
x_rev_0 <- rev(cumprod(rev(x_rle$values) == 0))
x_rle$values <- ifelse(
x_rle$lengths > 5 | x_0 | x_rev_0,
x_rle$values,
1
)
rep(x_rle$values, x_rle$lengths)
#> [1] 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1
发布于 2022-02-03 15:25:30
rle()
(游程-长度-编码)函数使得这非常容易。
x <- c(0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1)
r <- rle(x)
## modify values appropriately
r$values[r$values==0 & r$lengths<=5] <- 1
## convert back to full vector
x_new <- rep(r$values, r$lengths)
## [1] 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1
但是,对于文字边缘情况,这仍然需要进行一些调整--这已经将3 0的初始运行转换为1。
n <- length(r$values)
rv_int <- r$values[2:(n-1)]
rl_int <- r$lengths[2:(n-1)]
rv_int[rv_int == 0 &
rl_int <= 5] <- 1
x_new <- rep(c(r$values[1], rv_int, r$values[n]),
c(r$lengths[1], rl_int, r$lengths[n]))
https://stackoverflow.com/questions/70973799
复制相似问题