Reputation: 267
I am trying to apply a function to an xts object. I am using the ave
function to apply the function to each day separately. The function is throwing the following error:
Error in rbind.zoo(...) : indexes overlap In addition: Warning messages:
1: In split.default(seq_len(nrow(xc)), f, drop = drop, ...) :
data length is not a multiple of split variable
2: In zoo(value2, i2) :
some methods for “zoo” objects do not work if the index entries in ‘order.by’ are not unique
I have debugged the function, and its throwing the error when I try and convert -Inf
to NA
with the following line: x[x == -Inf] <- NA
.
Here is a minimum reproducible example applying just the problematic line of the function via the ave
function:
x <- as.xts(c(NA,-Inf,1,2,3,-Inf,NA,NA,NA),as.POSIXct(c(
"2010-01-05 00:00:00", "2010-01-05 00:04:00", "2010-01-05 00:08:00",
"2010-01-05 00:12:00", "2010-01-05 00:16:00", "2010-01-05 00:20:00",
"2010-01-06 00:00:00", "2010-01-06 00:04:00", "2010-01-06 00:08:00")))
out <- ave(x, as.Date(index(x)), FUN= function(x) x[x == -Inf] <- NA)
Upvotes: 1
Views: 1996
Reputation: 6891
The existing answers are fine, but you can alternatively easily and succinctly achieve averaging (or any reasonable function) in time intervals (hour, day week etc) easily using xts
tools (converting zoo
to xts
). Are you aware of ?period.apply
, and its wrapper function apply.daily
?
# Solve your overall problem in one line with no error generated when Inf values included:
x.daily <- apply.daily(x, mean, na.rm = T)
# > x.daily
# [,1]
# 2010-01-05 00:20:00 -Inf
# 2010-01-06 00:08:00 NaN
# Solve your first problem compactly (Replace +-Inf values in column 1 (generalise to any column number) of `x` with NA):
x[!is.finite(x[, 1]) &!is.na(x[, 1]), 1] <- NA
# Solve your second problem compactly (average by day):
x.daily <- apply.daily(x, FUN = mean, na.rm = T)
#Optional: tidy up timestamps in x.daily for equal spaced alignment in YYMMDD HHMMSS (NB HHMMSS will vary depending on your timezone. Should align for 86400 to 00:00:00 equivalent in UTC):
x.daily <- align.time(x.daily, 86400)
# > x.daily
# [,1]
# 2010-01-05 19:00:00 2
# 2010-01-06 19:00:00 NaN
Upvotes: 1
Reputation: 269371
There is no reason to group by day here since the computation is done element by element anyways:
replace(x, x == -Inf, NA)
or if overwriting is ok then:
x[x == -Inf] <- NA
If your actual function does make use of grouping and this was just an example then apply ave
to coredata(x)
so that we are dealing with plain vectors and be sure that the function applied actually returns the result (which in the question it does not):
fun <- function(x) replace(x, x == -Inf, NA)
x[] <- ave(coredata(x), as.Date(index(x)), FUN = fun)
We could also consider using !is.finite(x)
for the test.
Upvotes: 2