如果在0
之前和之后有三个1
s,我尝试以编程方式将变量从1
更改为0
。
例如,如果向量中的数字是1
,1
,1
,0
,1
,1
和1
,然后我想将0
更改为1
。
以下是dummy_code
data.frame
中向量df
中的数据:
original_df <- data.frame(dummy_code = c(1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1))
以下是我尝试重新编码值的方法:
desired_df <- data.frame(dummy_code = c(1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1)
我尝试使用the function fill
in the package tidyr
,但这填补了缺失值,因此无法使用。如果我要重新编码要丢失的0
值,那么这也不会有效,因为它只会将每个NA
编码为1
,而我只想编写每个{ {1}}被NA
三个1s
包围。
有没有办法以编程方式有效地执行此操作?
答案 0 :(得分:3)
以下是来自动物园的rollapply
的单行代码:
library(zoo)
rollapply(c(0, 0, 0, x, 0, 0, 0), 7, function(x) if (all(x[-4] == 1)) 1 else x[4])
## [1] 1 0 0 1 1 1 1 1 1 1 0 0 1
注意:使用的输入是:
x <- c(1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1)
答案 1 :(得分:3)
rle
替代方案,使用@G中的x
。格洛腾迪克的回答:
r <- rle(x)
查找三个1
的运行索引:
i1 <- which(r$lengths == 3 & r$values == 1)
检查&#34; 1
索引中的哪一个&#34;围绕0
,并获取要替换的0
的索引:
i2 <- i1[which(diff(i1) == 2)] + 1
将相关的0
替换为1
:
r$values[i2] <- 1
在更新的运行中反转rle
操作:
inverse.rle(r)
# [1] 1 0 0 1 1 1 1 1 1 1 0 0 1
基于data.table::rleid
的类似解决方案,稍微更紧凑,也许更容易阅读:
library(data.table)
d <- data.table(x)
计算每次运行的长度:
d[ , n := .N, by = rleid(x)]
对于&#34; x&#34;它们为零,1
的先前和后续运行的长度为3
,设置为&#34; x&#34;到1
:
d[x == 0 & shift(n) == 3 & shift(n, type = "lead") == 3, x := 1]
d$x
# [1] 1 0 0 1 1 1 1 1 1 1 0 0 1