根据周围的值重新编码向量中的值
Recode a value in a vector based on surrounding values
如果 0
前后有三个 1
,我正在尝试以编程方式将变量从 0
更改为 1
。
例如,如果向量中的数字为 1
、1
、1
、0
、1
、1
和 1
,然后我想将 0
更改为 1
。
这里是 data.frame
df
中向量 dummy_code
中的数据:
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
,而我只想编码每个 NA
被三个 1s
包围为 1
.
有没有办法以编程方式高效地执行此操作?
这里是 one-liner 使用来自动物园的 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)
rle
替代方案,使用来自@G 的 x
。格洛腾迪克的回答:
r <- rle(x)
查找三个 1
的 运行 的索引:
i1 <- which(r$lengths == 3 & r$values == 1)
检查 0
周围的“1
个索引”中的哪些索引,并获取要替换的 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)]
对于"x"为零且1
的前后运行长度为3
,设置"x"为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
如果 0
前后有三个 1
,我正在尝试以编程方式将变量从 0
更改为 1
。
例如,如果向量中的数字为 1
、1
、1
、0
、1
、1
和 1
,然后我想将 0
更改为 1
。
这里是 data.frame
df
中向量 dummy_code
中的数据:
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
,而我只想编码每个 NA
被三个 1s
包围为 1
.
有没有办法以编程方式高效地执行此操作?
这里是 one-liner 使用来自动物园的 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)
rle
替代方案,使用来自@G 的 x
。格洛腾迪克的回答:
r <- rle(x)
查找三个 1
的 运行 的索引:
i1 <- which(r$lengths == 3 & r$values == 1)
检查 0
周围的“1
个索引”中的哪些索引,并获取要替换的 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)]
对于"x"为零且1
的前后运行长度为3
,设置"x"为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