我正在尝试用一列中的0替换连续的1或2。我似乎无法想出一种方法来做到这一点,除了一个循环,它并不真正适合R最佳实践。任何人都可以提供有关如何以" R方式执行此操作的提示"?
set.seed(42)
temp<-sample(c(2,1),10,replace=T)
df<-data.frame(vals=temp)
示例结果:
vals goal
1 1 1
2 1 0
3 2 2
4 1 1
5 1 0
6 1 0
7 1 0
8 2 2
9 1 1
10 1 0
我的(非工作)尝试:
#get all strings with 1
match <- gregexpr("1+", as.vector(df$vals))
#iterate over all matches and create vectors that replace consecutive values with 0 based on the length of match.length
lapply(match,function(y){
sapply(attr(y, "match.length"),function(x)rep(0,x))
})
如果需要,只需添加另一个示例:
val goal
1 1
2 2
2 0
2 0
1 1
1 0
1 0
答案 0 :(得分:3)
将rleid
与duplicated
:
library(data.table)
df$goal <- df$vals
df$goal[duplicated(rleid(df$goal))] <- 0
df
vals goal
1 1 1
2 1 0
3 2 2
4 1 1
5 1 0
6 1 0
7 1 0
8 2 2
9 1 1
10 1 0
或者将vals
与滞后vals
进行比较,如果条件满足则分配零,对于第二个示例:
df$goal <- df$vals
df$goal[df$vals == shift(df$vals)] <- 0
val goal
1 1 1
2 2 2
3 2 0
4 2 0
5 1 1
6 1 0
7 1 0
答案 1 :(得分:3)
我们可以使用diff
检查一个值是否与上一个值相同:
df$goal<- df$vals
df$goal[-1] <- ifelse(diff(df$vals)==0, 0, df$vals[-1])
df
vals out
1 1 1
2 1 0
3 2 2
4 1 1
5 1 0
6 1 0
7 1 0
8 2 2
9 1 1
10 1 0
或类似地,
df$goal[which(diff(df$vals) == 0) +1L] <- 0
答案 2 :(得分:1)
我们可以使用rle
base R.
df$vals *!duplicated(inverse.rle(within.list(rle(df$vals),
values <-seq_along(values))))
#[1] 1 0 2 1 0 0 0 2 1 0
要了解rle
的工作原理,最好将代码拆分,
rle(df$vals)
#Run Length Encoding
#lengths: int [1:5] 2 1 4 1 2
# values : num [1:5] 1 2 1 2 1
返回list
个2个元素,即'length'和'values',其中lengths
具有每个重复相邻元素的长度。由于它是list
,我们使用within.list
循环将“值”更改为“值”序列。
within.list(rle(df$vals), values <-seq_along(values))
# Run Length Encoding
# lengths: int [1:5] 2 1 4 1 2
# values : int [1:5] 1 2 3 4 5 ## changed
如果我们使用inverse.rle
,则会返回由'lengths'复制的'values'向量
inverse.rle(within.list(rle(df$vals), values <-seq_along(values)))
#[1] 1 1 2 3 3 3 3 4 5 5
我们使用
获得duplicated
元素的逻辑向量
duplicated(inverse.rle(within.list(rle(df$vals), values <-seq_along(values))))
#[1] FALSE TRUE FALSE FALSE TRUE TRUE TRUE FALSE FALSE TRUE
否定(!
)将FALSE/TRUE
更改为TRUE/FALSE
。
!duplicated(inverse.rle(within.list(rle(df$vals), values <-seq_along(values))))
#[1] TRUE FALSE TRUE TRUE FALSE FALSE FALSE TRUE TRUE FALSE
TRUE/FALSE
存储为1/0
。因此,当与1/0
相乘时,对应于0的元素将返回0