我在数据框中有一个矢量/列,其虚拟变量如下所示:
2 2 0 0 0 0 1 1 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 2
但我希望看起来像这样:
2 2 3 3 3 3 1 1 1 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 4 4 4 4 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 1 1 1 4 4 4 4 4 4 2
基本上我想替换2之后和3之前的所有0,并替换1之后但2之前的所有0&#4&# 39; S。我该怎么做呢?
请注意,1&2和2之间的0的数量不是恒定的。这也只是大型数据帧的一小部分(> 13,300次观测),但目前该向量中的每个值都是0,1或2。
可重复输入:
x = c(2L, 2L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 2L, 2L,
2L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L,
1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 2L, 2L, 2L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L,
2L)
答案 0 :(得分:2)
由于您需要按顺序处理事物,Reduce
在这里很有用。例如
Reduce(function(a, b) {
if (b==0) {
if (a==2) {
3
} else if (a==1) {
4
} else {
a
}
} else {
b
}
}, x, accumulate=TRUE)
# [1] 2 2 3 3 3 3 1 1 1 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1
#[33] 1 4 4 4 4 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 1 1 1 4 4 4 4 4 4 2
这假设原始序列中的唯一数字是0,1或2,并且相同的数字永远不会出现在0字符串的两边。
答案 1 :(得分:2)
使用rle
和inverse.rle
:
y <- rle(x)
y$values[y$values == 0] <- y$values[-1][y$values == 0] +2
inverse.rle(y)
# [1] 2 2 3 3 3 3 1 1 1 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 4 4 4 4 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 1 1 1 4 4 4 4 4 4 2
使用data.table
和滚动连接:
library(data.table)
y <- setkey(data.table(z=x+2)[,id:=1:.N][x!=0],id)
x[x==0] <- y[.(1:max(id)),roll=-Inf][x==0,z]
# [1] 2 2 3 3 3 3 1 1 1 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 4 4 4 4 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 1 1 1 4 4 4 4 4 4 2
或tidyverse
,有点矫枉过正:
x[x==0] <- NA
library(tidyverse)
tibble(x,y=x) %>%
fill(x,.direction = "up") %>%
fill(y,.direction = "down") %>%
mutate(z = case_when(x < y ~3L, x > y ~ 4L, TRUE ~ x)) %>%
pull(z)
# [1] 2 2 3 3 3 3 1 1 1 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 4 4 4 4 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 1 1 1 4 4 4 4 4 4 2
最后,使用正则表达式的解决方案:
y <- paste(x,collapse="")
m <- gregexpr("20*1",y)
regmatches(y,m)[[1]] <- chartr("0","3",regmatches(y,m)[[1]])
y <- chartr("0","4",y)
as.numeric(unlist(strsplit(y,"")))
# [1] 2 2 3 3 3 3 1 1 1 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 1 1 1 4 4 4 4 4 4 4 4 2 2 2 3 3 3 3 3 3 3 3 3 3 1 1 1 4 4 4 4 4 4 2