#r #tidyverse #base
#r #tidyverse #База
Вопрос:
У меня есть двоичная переменная, представляющая, произошло событие или нет:
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)
Как я могу получить это с помощью base R, tidyverse или любым другим способом?
Ответ №1:
Используя тот факт, что у вас есть двоичный вектор, следующее дает желаемый результат:
cummax(seq_along(event) * event)
Комментарии:
1. Да! Это намного элегантнее, чем мое решение. Я думал о совокупных суммах, но я не думал о умножении индексов на двоичный вектор.
2. или без умножения
cummax(ifelse(event, seq_along(event), 0))
3. @jogo Это решение имеет смысл, если тип
event
равенlogical
. Это работает даже для числового вектора из-за неявных преобразований R, но … эх.
Ответ №2:
Всякий раз, когда вам нужно заполнить повторения значением, подумайте о кодировании длины выполнения.
В этом случае вы можете определить длину пробега, а затем повторить индексы 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)
Ответ №3:
Вы также можете сделать что-то подобное-
> 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
Ответ №4:
Другой вариант — найти индекс where 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