如何获取最后一个非零元素的位置

20

我有一个二进制变量,表示事件是否发生:

event <- c(0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0)

我需要获取一个变量,以指示上次事件发生的时间。预期输出应为:

last_event <- c(0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 13, 13, 13, 13)

我应该如何在基本R、整洁集或其他方式中获得这个?

4个回答

19

利用您拥有的二进制向量的特点,以下内容为您提供所需的输出:

cummax(seq_along(event) * event)

6
太好了!比我的解决方案优雅多了。我考虑过累积和,但没想到要把二进制向量的索引相乘。 - Konrad Rudolph
3
如果不使用乘法,则翻译为:cummax(ifelse(event, seq_along(event), 0))。该表达式的意思是在事件发生时返回一个递增的序列,否则返回零,并计算这个序列的累积最大值。 - jogo
@jogo 如果 event 的类型是 logical,那么这个解决方案是有意义的。由于 R 的隐式转换,即使对于数字向量也可以工作,但是... 嗯。 - Konrad Rudolph

9

每当您需要使用一个值填充重复项时,请考虑使用运行长度编码

在这种情况下,您可以确定连续相同数值的数量,然后将count == 0的索引号重复相应次数:

lengths = rle(event == 0)$lengths
nonzeros = which(event != 0)
runs = c(0, rep(nonzeros, each = 2))
result = rep(runs, lengths)

替代方案是,替换RLE中的运行,并将其反转:

rle = rle(event == 0)
nonzeros = which(event != 0)
rle$values = c(0, rep(nonzeros, each = 2))
result = inverse.rle(rle)

1
你也可以像这样做 -
> zero.locf <- function(x) {
  v <- x!=0
  c(0, x[v])[cumsum(v)+1]
}

> zero.locf(1:length(event)*event)

[1]  0  0  0  0  5  5  5  5  5  5  5  5 13 13 13 13

1

另一个选项是找到event == 1的索引,并根据length进行重复。

rep(c(0, which(event == 1)), tapply(event, cumsum(event == 1), length))
#[1]  0  0  0  0  5  5  5  5  5  5  5  5 13 13 13 13

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