6
$\begingroup$

I am working with a large number of TimeSeries of irregular length. This means that if I sum them, or compute the mean, it cuts off at the terminus of the shortest series. Is there a convenient way to make it compute to the end of the longest series, assuming that the missing data did not change?

For example, given

test1 = TimeSeries[{{{2000, 1, 1}, 1}, {{2001, 1, 1}, 2}, {{2002, 1, 1}, 3}}];
test2 = TimeSeries[{{{2000, 1, 1}, 2}, {{2001, 1, 1}, 2}}];

Mathematica computes Mean[{test1, test2}]["Values"] to be {1.5, 2}. I would prefer to get {1.5, 2, 2.5}.

What is a straightforward way to do this?

$\endgroup$
6
  • $\begingroup$ Extrapolating the data in your 2nd example as flat seems reasonable for that toy example, but what reason do you have for believing that will always be a good way to go? $\endgroup$
    – m_goldberg
    Commented Jan 5, 2016 at 16:55
  • 1
    $\begingroup$ Mean[{ArrayPad[test2["Values"], {0, 1}, "Fixed"], test1["Values"]}]? $\endgroup$ Commented Jan 5, 2016 at 16:57
  • $\begingroup$ @m_goldberg For my data, it's better than omitting these dates entirely. $\endgroup$ Commented Jan 5, 2016 at 16:57
  • 2
    $\begingroup$ Try TimeSeriesThread[Mean, {test1, test2}]["Values"]. You can play around with the ResamplingMethod for each time series to have more control over the result. $\endgroup$
    – Andy Ross
    Commented Jan 5, 2016 at 17:11
  • 1
    $\begingroup$ @AndyRoss the docs only reveal "Interpolation" as a possible method so while you could play around with the interpolation order (and are there any other additional options available for the interpolation resampling method ..the docs imply there are) what other methods are available? $\endgroup$ Commented Jan 5, 2016 at 23:18

1 Answer 1

9
$\begingroup$

The simple answer to this is to use TimeSeriesThread which will perform the extrapolation you are after (though it will rightly complain about extrapolating).

test1 = TimeSeries[{{{2000, 1, 1}, 1}, {{2001, 1, 1}, 2}, {{2002, 1, 1}, 3}}];
test2 = TimeSeries[{{{2000, 1, 1}, 2}, {{2001, 1, 1}, 2}}];

TimeSeriesThread[Mean, {test1, test2}]["Values"]

(* {3/2, 2, 5/2} *)

If you want finer control over the extrapolation you can set the ResamplingMethod on each TimeSeries object. The documentation is pretty thin on options. Currently the only documented possibilities are to either use a constant or to set interpolation options. By default, linear interpolation is used for TimeSeries.

In your case, using a constant makes sense and doesn't complain about extrapolation.

test1 = TimeSeries[{{{2000, 1, 1}, 1}, {{2001, 1, 1}, 2}, {{2002, 1, 1}, 3}}, 
                ResamplingMethod -> {"Constant", 3}];

test2 = TimeSeries[{{{2000, 1, 1}, 2}, {{2001, 1, 1}, 2}}, 
                ResamplingMethod -> {"Constant", 2}];

TimeSeriesThread[Mean, {test1, test2}]["Values"]

(* {3/2, 2, 5/2} *)

You can also set various interpolation options. In fact, you can use any valid option setting for Interpolation. For example, say you wanted to do zero order interpolation.

m = {"Interpolation", InterpolationOrder -> 0};

test1 = TimeSeries[{{{2000, 1, 1}, 1}, {{2001, 1, 1}, 2}, {{2002, 1, 1}, 3}}, 
              ResamplingMethod -> m];

test2 = TimeSeries[{{{2000, 1, 1}, 2}, {{2001, 1, 1}, 2}}, 
              ResamplingMethod -> m];

TimeSeriesThread[Mean, {test1, test2}]["Values"]

(* {3/2, 2, 5/2} *)

Finally, you can create your own resampling method. The usual warnings apply here since this is undocumented functionality and is subject to change.

ResamplingMethod can be given as a function that takes the TemporalData object (TimeSeries is a special case) and returns a list of Listable functions, one for each path, that return a value given a time or list of times. These are what is returned by the "PathFunctions" property of TemporalData.

Suppose we want to do linear interpolation for values in the range of the TimeSeries and then give the last value for all times beyond the TimeSeries. We can create a function that does this as such.

f[ts_TemporalData] := Block[{fns, mxs, vs},
  fns = Interpolation[#, InterpolationOrder -> 1] & /@ ts["Paths"];
  mxs = Max /@ ts["ValueList"];
  vs = Last /@ ts["ValueList"];
  MapThread[
   Function[\[FormalX], 
     Piecewise[{{#1[\[FormalX]], \[FormalX] <= #2}}, #3], 
     Listable] &, {fns, mxs, vs}]
  ]

Now we can use this function for the ResamplingMethod.

test1 = TimeSeries[{{{2000, 1, 1}, 1}, {{2001, 1, 1}, 2}, {{2002, 1, 1},3}}, 
             ResamplingMethod -> f];

test2 = TimeSeries[{{{2000, 1, 1}, 2}, {{2001, 1, 1}, 2}}, 
             ResamplingMethod -> f];

TimeSeriesThread[Mean, {test1, test2}]["Values"]

(*{3/2, 2, 5/2}*)

Obviously this is messy, which is probably why it isn't documented, but it could certainly be useful.

$\endgroup$
3
  • $\begingroup$ @Mike Honeychurch hopefully this answers your question $\endgroup$
    – Andy Ross
    Commented Jan 6, 2016 at 1:31
  • $\begingroup$ yes thanks for this information. cheers $\endgroup$ Commented Jan 6, 2016 at 22:49
  • $\begingroup$ Using a function for ResamplingMethod is quite convenient, however, at least on MMA 11.1 and 11.2 the resulting time series does not work with any function that tries to retrieve the path function, including TimeSeriesResample. test1["PathFunction"] results in the error message: Path function failed to be created with the current setting of ResamplingMethod option. I suspect this is another reason why this is not documented. $\endgroup$ Commented Sep 22, 2017 at 22:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.