用字符串中的0替换重复值

时间:2016-06-24 14:05:33

标签: r

我正在尝试用一列中的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

3 个答案:

答案 0 :(得分:3)

rleidduplicated

一起使用
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