I have a vector that I want to modify so that it contains only elements that are equal too or larger than the previous element. The vector represents a phenomena that should only increase or stay the same (i.e. cumulative deaths by day), but reporting errors result in elements that are less than the previous element. I want to correct this by replacing elements with previous ones until the vector meets the aforementioned criteria.
raw data : 1 3 3 6 8 10 7 9 15 12
desired modified data: 1 3 3 6 6 6 7 9 9 12
library(zoo)
raw <- c(1, 3, 3, 6, 8, 10, 7, 9, 15, 12)
replace.errors <- function(x){
x %>%
replace(diff(x) < 0, NA) %>%
na.locf(na.rm=FALSE)
}
replace.errors(raw)
# [1] 1 3 3 6 8 8 7 9 9 12
My function does not work if multiple sequential elements in a row need to be replaced (8 and 10), as it just pulls forward an element that is still greater than the next one.
A data.table option using nafill along with cummin
nafill(replace(raw, rev(cummin(rev(raw))) != raw, NA), type = "locf")
gives
> nafill(replace(raw, rev(cummin(rev(raw))) != raw, NA), type = "locf")
[1] 1 3 3 6 6 6 7 9 9 12
Following the similar idea from above approach, your function replace.errors can be defined as
replace.errors <- function(x){
x %>%
replace(rev(cummin(rev(.))) != (.), NA) %>%
na.locf()
}
such that
> replace.errors(raw)
[1] 1 3 3 6 6 6 7 9 9 12
Another option is to define a user function like below
f <- function(v) {
for (k in which(c(FALSE, diff(v) < 0))) {
p <- max(v[v < v[k]])
v <- replace(v, tail(which(v == p), 1):(k - 1), p)
}
v
}
which gives
> f(raw)
[1] 1 3 3 6 6 6 7 9 9 12
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With