Class: TimeSeriesMath::TimeSeries

Inherits:
Object
  • Object
show all
Defined in:
lib/time_series_math/time_series.rb

Overview

TimeSeries

TimeSeries class provides an efficient data structure for storing timestamped data values.

TimeSeries maintains order of its elements and provides efficient search methods for near-constant time access (depends strongly on timestamps distribution – the more even, the better).

Examples:

require 'time_series_math'
include TimeSeriesMath

# one by one element insertion
ts = TimeSeries.new
ts.push 1.0, { x: 2.0, y: 3.0 }
ts.push 1.2, { x: 2.0, y: 3.0 }
ts.push 1.6, { x: 2.0, y: 3.0 }
ts.push 1.9, { x: 2.0, y: 3.0 }
ts.push 2.1, { x: 2.0, y: 3.0 }

# more time-efficient batch insertion using arrays:
ts = TimeSeries.new
tt = [ 1.0, 1.2, 1.6, 1.9, 2.1 ]
dd = [ {x: 2.0}, {x: 2.1}, {x: 2.5}, {x: 2.7}, {x: 2.85} ]
ts.push_array(tt, dd)

# retrieve closest element before given time
ts[1.2] # => { x: 2.1 }
ts[2.095] # => { x: 2.7 }

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(arr_t = nil, arr_v = nil) ⇒ TimeSeries

Creates a TimeSeries object.

Examples:

ts = TimeSeries.new # creates empty TimeSeries object

ts = TimeSeries.new([0.1, 0.5, 1.0], [120.0, 130.0, 140.0])

Parameters:

  • arr_t (Array<Float>) (defaults to: nil)

    Array of timestamps

  • arr_v (Array) (defaults to: nil)

    Array of corresponding values, should be of the same size as arr_t



47
48
49
50
51
# File 'lib/time_series_math/time_series.rb', line 47

def initialize(arr_t = nil, arr_v = nil)
  @data = []
  @processor = nil
  push_array(arr_t, arr_v) if arr_t && arr_v
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



34
35
36
# File 'lib/time_series_math/time_series.rb', line 34

def data
  @data
end

#processorObject (readonly)

Returns the value of attribute processor.



34
35
36
# File 'lib/time_series_math/time_series.rb', line 34

def processor
  @processor
end

Instance Method Details

#[](t) ⇒ Object

Returns value calculated at t.

The actual value returned depends on the processor used by TimeSeries object. When no processor is used, the returned value is the value of the last element preceding, or exactly at t.



149
150
151
152
# File 'lib/time_series_math/time_series.rb', line 149

def [](t)
  i = left_index_at(t)
  i && @data[i][1]
end

#[]=(t, v) ⇒ Object

Alias for #push(t, v)

Example:

ts = TimeSeries.new
ts[1.0] = { x: 123.0 }
ts[2.0] = { x: 125.0 }

ts[1.0] # => { x: 123.0 }

Parameters:

  • t (Float)

    Timestamp of the new value

  • v (Fixnum, Float, Array, Hash)

    New value



121
122
123
# File 'lib/time_series_math/time_series.rb', line 121

def []=(t, v)
  push(t, v)
end

#firstArray?

Returns First element of the time series.

Returns:

  • (Array, nil)

    First element of the time series



73
74
75
# File 'lib/time_series_math/time_series.rb', line 73

def first
  @data.first
end

#indices_at(t) ⇒ Array

Returns indices of the elements surrounding t.

Returns:

  • (Array)

    indices of the elements surrounding t.



156
157
158
# File 'lib/time_series_math/time_series.rb', line 156

def indices_at(t)
  bsearch_indices_at(t)
end

#keysArray

Returns Array of timestamps.

Returns:

  • (Array)

    Array of timestamps



61
62
63
# File 'lib/time_series_math/time_series.rb', line 61

def keys
  @data.map { |d| d[0] }
end

#lastArray?

Returns Last element of the time series.

Returns:

  • (Array, nil)

    Last element of the time series



85
86
87
# File 'lib/time_series_math/time_series.rb', line 85

def last
  @data.last
end

#left_index_at(t) ⇒ Object

Returns index of the element preceding t.

Returns:

  • index of the element preceding t



139
140
141
# File 'lib/time_series_math/time_series.rb', line 139

def left_index_at(t)
  indices_at(t).first
end

#push(t, v) ⇒ Object

Inserts new element into time series.

Parameters:

  • t (Float)

    Timestamp of the new value

  • v (Fixnum, Float, Array, Hash)

    New value



99
100
101
102
103
104
105
106
107
# File 'lib/time_series_math/time_series.rb', line 99

def push(t, v)
  t = t.to_f
  i = left_index_at(t)
  if i.nil?
    @data.unshift([t, v])
  else
    @data.insert(i + 1, [t, v])
  end
end

#push_array(arr_t, arr_v) ⇒ Object

Inserts batch of new values into time series. This method is more time efficient than using #push to insert elements one by one.

Parameters:

  • arr_t (Array)

    Array of timestamps

  • arr_v (Array)

    Array of corresponding values, should be of the same size as arr_t



131
132
133
134
135
# File 'lib/time_series_math/time_series.rb', line 131

def push_array(arr_t, arr_v)
  arr_data = arr_t.zip(arr_v)
  @data.concat(arr_data)
  @data.sort_by! { |d| d[0] }
end

#sizeObject

Returns number of values in the series.

Returns:

  • number of values in the series



55
56
57
# File 'lib/time_series_math/time_series.rb', line 55

def size
  @data.size
end

#t_firstFloat?

Returns Timestamp of the first element.

Returns:

  • (Float, nil)

    Timestamp of the first element



79
80
81
# File 'lib/time_series_math/time_series.rb', line 79

def t_first
  first && first[0]
end

#t_lastFloat?

Returns Timestamp of the last element.

Returns:

  • (Float, nil)

    Timestamp of the last element



91
92
93
# File 'lib/time_series_math/time_series.rb', line 91

def t_last
  last && last[0]
end

#use(processor_module) ⇒ Object

Use processor



162
163
164
165
# File 'lib/time_series_math/time_series.rb', line 162

def use(processor_module)
  @processor = processor_module
  extend processor_module
end

#valuesArray

Returns Array of values.

Returns:

  • (Array)

    Array of values



67
68
69
# File 'lib/time_series_math/time_series.rb', line 67

def values
  @data.map { |d| d[1] }
end