Time series interpolation

Suppose i have two vectors, one containing timestamps and one containing values:

using Dates
dt = collect(Date(1900,1,1):Day(2):Date(1902,1,1))
y = randn(length(x))

I want to upsample these data to daily resolution by interpolation. However, I couldn’t find a way to do this yet. I tried interpolating with Interpolations.jl, but when using the dates as index it never finishes. When I use a “helper index” that is just a number range, I get a MethodError, because it can’t interpolate the dates I guess.

using Interpolations
LinearInterpolation(dt, y)  # This command never finishes

i = range(1, len(dt))

LinearInterpolation(i, dt)  # MethodError: no method matching *(::Float64, ::Date)

Ialso tried to put these vectors in a TimeArray from TimeSeries.jl and tried using TimeSeriesResampler:

using TimeSeries, TimeSeriesResampler
ts = TimeArray(dt, y)
resample(ts[:A], Day(1))

This correctly constructs a TimeSeriesResampler object. However, in the documentation I only see options like sum or mean to aggregate data to a lower resolution and no options for interpolation.

Can anyone point me to some ideas on how to interpolate time series data (linearly)?

One option is to convert the dates to number of days:

itp = LinearInterpolation(Dates.days.(dt), y)
dt1 = Date(1900,1,1):Day(1):Date(1902,1,1)
y1 = itp(Dates.days.(dt1))

Anoter way of getting number of days as floats is:

(dt .- dt[1])/Day(1)

NB:
As @DNF would say, do not use collect, unless really necessary.

1 Like

Great and simple solution. I guess it will also work correctly with irregularly sampled timeseries, yay! Two follow up questions:

  1. How to get back to a date from the integer day values? Dates.Date.(Dates.days.(dt1)) doesn’t work.

  2. Is there a similar thing if the timestamps are sub-daily resolution? Like Dates.seconds.(dt1)? Tried this but the method doesnt exist…

EDIT: Found it. For conversion of dates to days since epoch and vice versa you can use eds = Dates.date2epochdays(Date(1900, 1, 1)) and Dates.epochdays2date(eds). This also works with datetime (useful for timeframes samaller than days) with ems = Dates.datetime2epochms(DateTime(1900, 1, 1)) and Dates.epochms2datetime(ems).

There is:

Dates.datetime2epochms.(DateTime.(dt))

which takes DateTime and returns the number of milliseconds since the rounding epoch (0000-01-01T00:00:00).

The inverse is: Dates.epochms2datetime()

The use of these functions is probably preferable.