基于周围值在矢量中重新编码值

时间:2017-01-29 19:43:25

标签: r tidyr

如果在0之前和之后有三个1 s,我尝试以编程方式将变量从1更改为0

例如,如果向量中的数字是1110111,然后我想将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包围。

有没有办法以编程方式有效地执行此操作?

2 个答案:

答案 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