在二进制向量中删除重复值并保留第一个值

10

我想从一个二进制向量中删除重复的元素,但保留第一个。

x = c(0,0,1,1,0,1,0,1,1,1,0,1) # the input 
y = c(0,0,1,0,1,0,1,0,1)     # the desired output

即第一组和第三组中的一个 1 和两个 1 分别被删除,并且保留该组中的第一个。

我正在尝试使用 rlecumsum,但还没有弄清楚。任何建议都将不胜感激。


2
这是另一个 x[ave(x, cumsum(x == 0), FUN = cumsum) <= 1] - rawr
5个回答

8
使用 /
res <- rle(x)
res$lengths[res$values == 1] <- 1
inverse.rle(res)
## [1] 0 0 1 0 1 0 1 0 1

1
或者使用 inverse.rle(within(unclass(rle(x)),lengths[values==1]<-1)) 将其转换为一行代码。 - nicola
@nicola 是的,我本来想把它变成一行代码,但是尝试使用 with(rle(x), lengths[values == 1] <- 1) 却不起作用。使用 withinunclass 看起来很难阅读。 - David Arenburg
1
不知道有一个相反的,太棒了! - Francis

8
我们可以使用 diff:
x[c(1, diff(x)) == 1 | x == 0]

1
如果想要对数据框进行子集操作,若向量是其中一列,则保留索引非常方便。非常感谢! - Francis

4
x = c(0,0,1,1,0,1,0,1,1,1,0,1)
x[!(x == 1 & #remove each value that is a 1
    c(x[-1] == 1, FALSE) #followed by a 1 (never the case for the last value)
  )]
#[1] 0 0 1 0 1 0 1 0 1

这显然比我的回答更简洁。你能解释一下它是如何工作的吗? - Brant Mullinix
@BrantMullinix 我已经添加了注释。 - Roland
你为什么要使用向量c(x[-1]==1,FALSE)?与只使用x[!(x == 1 & x[-1] == 1)]有什么区别? - Brant Mullinix
对于其他有同样疑问的人,我自己找到了答案。x[-1]返回一个没有第一个元素的向量,因此当你将其与第一部分进行&运算时,向量长度不同。虽然R可以自行处理这个问题,但它会产生影响,不建议这样做。为了解决这个问题,@Roland在向量末尾添加了一个FALSE,因为在这种比较中最后一个值将是false。这使得两个向量长度相等,并避免了警告“长对象长度不是短对象长度的倍数”。 - Brant Mullinix

1
x = c(0,0,1,1,0,1,0,1,1,1,0,1)
x1 <- rle(x)
x1$lengths[x1$values==1] <- 1
inverse.rle(x1)

这是我即将发布的版本。 - Therkel
@David Arenburg 更快 - Ven Yao

0
根据向量大小,您可以循环遍历它并使用条件将值附加到结果中。这里是一个简单的解决方案,使用您提供的输入。
x <- c(0,0,1,1,0,1,0,1,1,1,0,1)
prev <- 0
y <- c()
for(i in x){
  if (i == 1){
    if (prev != 1){
      y <- append(y,i)
    }
  }else{
    y <- append(y,i)
  }
  prev <- i
}

3
不要在循环中生成对象。请阅读《The R Inferno》(http://www.burns-stat.com/pages/Tutor/R_inferno.pdf)。 - Roland
谢谢建议。@Roland - Brant Mullinix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接