Combine methods

TimeSeries supports merging two TimeArrays, and squishing the timestamp to a longer-term interval while representing values that make sense.

merge

The merge method performs joins between two TimeArrays. The default behaviour is to perform an inner join, such that the resulting TimeArray contains only timestamps that both TimeArrays share, and values that correspond to that timestamp.

The AAPL object from MarketData has 8,336 rows of data from Dec 12, 1980 to Dec 31, 2013. If we merge it with the CAT object, which contains 13,090 rows of data from Jan 2, 1962 to Dec 31, 2013 we might expect the resulting TimeArray to have 8,336 rows of data, corresponding to the length of AAPL. This assumes that every day that Apple Computer, Inc. traded, Caterpillar, Inc likewise traded. It turns out that this isn't true. CAT did not trade on Sep 27, 1985 because Hurricane Glorio shut down the New York Stock Exchange. Apple Computer trades on the electronic NASDAQ and its trading was not halted on that day. The result of the merge should then be 8,335 rows:

julia> using TimeSeries
julia> using MarketData
julia> AppleCat = merge(AAPL, CAT);
julia> length(AppleCat)8335

Left, right, and outer joins can also be performed by passing the corresponding symbol. These joins introduce NaN values when data for a particular timestamp only exists in one of the series to be merged. For example:

julia> merge(op[1:3], cl[2:4], method = :left)3×2 TimeArray{Float64, 2, Date, Matrix{Float64}} 2000-01-03 to 2000-01-05
┌────────────┬────────┬───────┐
│            │ Open   │ Close │
├────────────┼────────┼───────┤
│ 2000-01-03 │ 104.88 │   NaN │
│ 2000-01-04 │ 108.25 │ 102.5 │
│ 2000-01-05 │ 103.75 │ 104.0 │
└────────────┴────────┴───────┘
julia> merge(op[1:3], cl[2:4], method = :right)3×2 TimeArray{Float64, 2, Date, Matrix{Float64}} 2000-01-04 to 2000-01-06 ┌────────────┬────────┬───────┐ │ │ Open │ Close │ ├────────────┼────────┼───────┤ │ 2000-01-04 │ 108.25 │ 102.5 │ │ 2000-01-05 │ 103.75 │ 104.0 │ │ 2000-01-06 │ NaN │ 95.0 │ └────────────┴────────┴───────┘
julia> merge(op[1:3], cl[2:4], method = :outer)4×2 TimeArray{Float64, 2, Date, Matrix{Float64}} 2000-01-03 to 2000-01-06 ┌────────────┬────────┬───────┐ │ │ Open │ Close │ ├────────────┼────────┼───────┤ │ 2000-01-03 │ 104.88 │ NaN │ │ 2000-01-04 │ 108.25 │ 102.5 │ │ 2000-01-05 │ 103.75 │ 104.0 │ │ 2000-01-06 │ NaN │ 95.0 │ └────────────┴────────┴───────┘

The merge method allows users to specify the value for the meta field of the merged object. When that value is not explicitly provided, merge will concatenate the meta field values, assuming these values to be strings. This covers the vast majority of use cases. In edge cases when users do not provide a meta value and both field values are not strings, the merged object will take on Void as its meta field value:

julia> meta(AppleCat)"AAPL_CAT"
julia> CatApple = merge(CAT, AAPL, meta = 47);
julia> meta(CatApple)47
julia> meta(merge(AppleCat, CatApple))
Base.mergeFunction
merge(ta1::TimeArray{T}, ta2::TimeArray{T}, [tas::TimeArray{T}...];
      method = :inner, colnames = [...], padvalue = NaN)

Merge several TimeArrays along with the time index.

Argument

  • method::Symbol: :inner, :outer, :left or :right.
source

collapse

The collapse method allows for compressing data into a larger time frame. For example, converting daily data into monthly data. When compressing dates, something rational has to be done with the values that lived in the more granular time frame. To define what happens, a function call is made. In our example, we want to compress the daily cl closing prices from daily to monthly. It makes sense for us to take the last value known and have that represented with the corresponding timestamp. A non-exhaustive list of valid time methods is presented below.

Dates methodTime length
Dates.quarterquarterly
daydaily
weekweekly, starting from Monday.
monthmonthly
yearyearly
hourhourly
minuteminutely
secondsecondly

Showing this code in REPL:

julia> using TimeSeries
julia> using MarketData
julia> collapse(cl, month, last)24×1 TimeArray{Float64, 1, Date, Vector{Float64}} 2000-01-31 to 2001-12-31 ┌────────────┬────────┐ │ │ Close │ ├────────────┼────────┤ │ 2000-01-31 │ 103.75 │ │ 2000-02-29 │ 114.62 │ │ 2000-03-31 │ 135.81 │ │ 2000-04-28 │ 124.06 │ │ 2000-05-31 │ 84.0 │ │ 2000-06-30 │ 52.38 │ │ 2000-07-31 │ 50.81 │ │ 2000-08-31 │ 60.94 │ │ ⋮ │ ⋮ │ │ 2001-06-29 │ 23.25 │ │ 2001-07-31 │ 18.79 │ │ 2001-08-31 │ 18.55 │ │ 2001-09-28 │ 15.51 │ │ 2001-10-31 │ 17.56 │ │ 2001-11-30 │ 21.3 │ │ 2001-12-31 │ 21.9 │ └────────────┴────────┘ 9 rows omitted

We can also supply the function that chooses the timestamp and the function that determines the corresponding value independently:

julia> using Statistics
julia> collapse(cl, month, last, mean)24×1 TimeArray{Float64, 1, Date, Vector{Float64}} 2000-01-31 to 2001-12-31 ┌────────────┬─────────┐ │ │ Close │ ├────────────┼─────────┤ │ 2000-01-31 │ 103.359 │ │ 2000-02-29 │ 111.638 │ │ 2000-03-31 │ 128.503 │ │ 2000-04-28 │ 123.106 │ │ 2000-05-31 │ 100.81 │ │ 2000-06-30 │ 78.8891 │ │ 2000-07-31 │ 53.7585 │ │ 2000-08-31 │ 51.3122 │ │ ⋮ │ ⋮ │ │ 2001-06-29 │ 21.531 │ │ 2001-07-31 │ 21.4624 │ │ 2001-08-31 │ 18.6465 │ │ 2001-09-28 │ 16.602 │ │ 2001-10-31 │ 17.3222 │ │ 2001-11-30 │ 19.649 │ │ 2001-12-31 │ 21.695 │ └────────────┴─────────┘ 9 rows omitted

vcat

The vcat method is used to concatenate time series: if you have two time series with the same columns, this function can merge them into a single object. Notably, it can be used to merge data that is split into multiple files. Its behaviour is quite different from merge, which does not consider that its arguments are actually the same time series.

This concatenation is vertical (vcat) because it does not create columns, it extends existing ones (which are represented vertically).

Base.vcatMethod
vcat(tas)

Concatenate two $TimeArray$ into single object.

If there are duplicated timestamps, we will keep order as the function input.

julia> a = TimeArray([Date(2015, 10, 1), Date(2015, 10, 2), Date(2015, 10, 3)], [1, 2, 3]);

julia> b = TimeArray([Date(2015, 10, 2), Date(2015, 10, 3)], [4, 5]);

julia> [a; b]
5×1 TimeArray{Int64,1,Date,Array{Int64,1}} 2015-10-01 to 2015-10-03
│            │ A     │
├────────────┼───────┤
│ 2015-10-01 │ 1     │
│ 2015-10-02 │ 2     │
│ 2015-10-02 │ 4     │
│ 2015-10-03 │ 3     │
│ 2015-10-03 │ 5     │
source

map

This function allows complete transformation of the data within the time series, with alteration on both the time stamps and the associated values. It works exactly like Base.map: the first argument is a binary function (the time stamp and the values) that returns two values, respectively the new time stamp and the new vector of values. It does not perform any kind of compression like collapse, but rather transformations.

The simplest example is to postpone all time stamps in the given time series, here by one year:

julia> using TimeSeries
julia> using Dates
julia> ta = TimeArray([Date(2015, 10, 01), Date(2015, 11, 01)], [15, 16])2×1 TimeArray{Int64, 1, Date, Vector{Int64}} 2015-10-01 to 2015-11-01 ┌────────────┬────┐ │ │ A │ ├────────────┼────┤ │ 2015-10-01 │ 15 │ │ 2015-11-01 │ 16 │ └────────────┴────┘
julia> map((timestamp, values) -> (timestamp + Year(1), values), ta)2×1 TimeArray{Int64, 1, Date, Vector{Int64}} 2016-10-01 to 2016-11-01 ┌────────────┬────┐ │ │ A │ ├────────────┼────┤ │ 2016-10-01 │ 15 │ │ 2016-11-01 │ 16 │ └────────────┴────┘