Извините, что выкопал старый вопрос.Я не мог найти функцию для выполнения этой работы в поезде, поэтому сам написал ее.
Я с гордостью обнаружил, что она чуть-чуть быстрее.
Хотя она менее гибкая.
Но это хорошо с ave
, и это то, что мне было нужно.
repeat.before = function(x) { # repeats the last non NA value. Keeps leading NA
ind = which(!is.na(x)) # get positions of nonmissing values
if(is.na(x[1])) # if it begins with a missing, add the
ind = c(1,ind) # first position to the indices
rep(x[ind], times = diff( # repeat the values at these indices
c(ind, length(x) + 1) )) # diffing the indices + length yields how often
} # they need to be repeated
x = c(NA,NA,'a',NA,NA,NA,NA,NA,NA,NA,NA,'b','c','d',NA,NA,NA,NA,NA,'e')
xx = rep(x, 1000000)
system.time({ yzoo = na.locf(xx,na.rm=F)})
## user system elapsed
## 2.754 0.667 3.406
system.time({ yrep = repeat.before(xx)})
## user system elapsed
## 0.597 0.199 0.793
Редактировать
Поскольку это стало моим самым голосуемым ответом, мне часто напоминали, что яне использую мою собственную функцию, потому что мне часто нужен аргумент maxgap
в зоопарке.Поскольку у zoo есть некоторые странные проблемы в крайних случаях, когда я использую даты dplyr +, которые я не смог отладить, я вернулся к этому сегодня, чтобы улучшить мою старую функцию.
Я провел сравнительный анализ своей улучшенной функции и всех других записейВот.Для базового набора функций, tidyr::fill
является самым быстрым, но при этом не исключает крайние случаи.Запись Rcpp от @BrandonBertelsen еще быстрее, но она негибкая в отношении типа ввода (он неправильно тестировал крайние варианты из-за неправильного понимания all.equal
).
Если вам нужен maxgap
, моя функция нижебыстрее, чем зоопарк (и не имеет странных проблем с датами).
Я выставил документацию о моих тестах .
Новая функция
repeat_last = function(x, forward = TRUE, maxgap = Inf, na.rm = FALSE) {
if (!forward) x = rev(x) # reverse x twice if carrying backward
ind = which(!is.na(x)) # get positions of nonmissing values
if (is.na(x[1]) && !na.rm) # if it begins with NA
ind = c(1,ind) # add first pos
rep_times = diff( # diffing the indices + length yields how often
c(ind, length(x) + 1) ) # they need to be repeated
if (maxgap < Inf) {
exceed = rep_times - 1 > maxgap # exceeding maxgap
if (any(exceed)) { # any exceed?
ind = sort(c(ind[exceed] + 1, ind)) # add NA in gaps
rep_times = diff(c(ind, length(x) + 1) ) # diff again
}
}
x = rep(x[ind], times = rep_times) # repeat the values at these indices
if (!forward) x = rev(x) # second reversion
x
}
Я также поместил эту функцию в свой пакет опалубки (только Github).