Class: SimpleTimeSeries

Inherits:
Object
  • Object
show all
Defined in:
lib/simple_time_series/version.rb,
lib/simple_time_series/simple_time_series.rb

Constant Summary collapse

VERSION =
"0.1.7"
DEBUG =
false

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ SimpleTimeSeries

Returns a new instance of SimpleTimeSeries.



7
8
9
10
11
12
13
# File 'lib/simple_time_series/simple_time_series.rb', line 7

def initialize(opts)
  @time_vars = opts[:time_vars]
  @data_vars = opts[:data_vars]
  @attribs = opts[:attribs]
  define_data_methods_and_set_values
  define_time_methods_and_set_values
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &block) ⇒ Object



15
16
17
18
19
20
21
# File 'lib/simple_time_series/simple_time_series.rb', line 15

def method_missing(meth, *args, &block)
  begin
    attribs[args[0]][meth]
  rescue
    super
  end
end

Instance Attribute Details

#attribsObject

Returns the value of attribute attribs.



5
6
7
# File 'lib/simple_time_series/simple_time_series.rb', line 5

def attribs
  @attribs
end

#data_varsObject

Returns the value of attribute data_vars.



5
6
7
# File 'lib/simple_time_series/simple_time_series.rb', line 5

def data_vars
  @data_vars
end

#time_varsObject

Returns the value of attribute time_vars.



5
6
7
# File 'lib/simple_time_series/simple_time_series.rb', line 5

def time_vars
  @time_vars
end

Instance Method Details

#current(what, opts = {}) ⇒ Object



67
68
69
70
# File 'lib/simple_time_series/simple_time_series.rb', line 67

def current(what, opts={})
  puts "#current called with #{what} and #{opts}" if DEBUG
  send(what.to_sym, opts)
end

#data_array(*data_var_names, opts) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/simple_time_series/simple_time_series.rb', line 45

def data_array(*data_var_names, opts)
  err_msg = "The last parameter passed to #data_array must be a hash of start/end values.\n"
  err_msg += "Example: {:start => 'Tuesday', :end => '2014-01-06'}\n"
  err_msg += "If you want to use all observations, you can pass a blank hash, like {}\n"
  raise err_msg unless opts
  data_arr = []
  Array(data_var_names).each do |name|
    puts "Looping through data_var_names inside data_array with #{name}" if DEBUG
    puts "Calling find(#{name}, #{opts[:start]}, #{opts[:end]}, #{opts})" if DEBUG
    data_arr << find(name, opts[:start], opts[:end], opts)
  end

  if opts[:prepend_names]
    if opts[:prepend_names].is_a? Array
      data_arr = data_arr.each_with_index.map { |var, idx| var.dup.unshift(opts[:prepend_names][idx]) }
    else
      data_arr = data_arr.each_with_index.map { |var, idx| var.dup.unshift(data_var_names[idx]) }
    end
  end
  data_arr
end

#find(what, date, end_date = nil, opts = {}) ⇒ Object



23
24
25
26
# File 'lib/simple_time_series/simple_time_series.rb', line 23

def find(what, date, end_date=nil, opts={})
  puts "Calling send(#{what}_on, #{date}, #{end_date}, #{opts})" if DEBUG
  send((what + '_on').to_sym, date, end_date, opts)
end

#find_plus_label(what, date, end_date = nil) ⇒ Object



28
29
30
# File 'lib/simple_time_series/simple_time_series.rb', line 28

def find_plus_label(what, date, end_date=nil)
  find(what, date, end_date).dup.unshift(what)
end

#index_of_date_value(date) ⇒ Object



72
73
74
75
76
77
# File 'lib/simple_time_series/simple_time_series.rb', line 72

def index_of_date_value(date)
  time_vars.each do |tv_key, tv_val|
    return tv_val.index(date) if tv_val.include?(date)
  end
  nil
end

#new_data_var(var, vals) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/simple_time_series/simple_time_series.rb', line 92

def new_data_var(var, vals)
  define_getter_and_setter(var)
  self.class.class_eval do
    define_method("#{var}_subset") do |first, last=first|
      start_idx = index_of_date_value(first)
      last_idx = index_of_date_value(last)
      (start_idx && last_idx) ? eval(var)[start_idx..last_idx] : nil
    end
    define_method("#{var}_subset_set") do |first, last, val_arr|
      start_idx = index_of_date_value(first)
      last_idx = index_of_date_value(last)
      if (start_idx && last_idx)
        eval(var)[start_idx..last_idx] = val_arr
      else
        raise "Could not run #{var}_subset with values #{val_arr}"
      end
    end
    define_method("#{var}_diff") do |first=nil, last=nil| # should work only on numeric data
      # this could be made more efficient by caching the full array and/or calculating only a subset of values
      time_vars.each do |tv_key, tv_val|
        start_idx = index_of_date_value(first) || 0
        last_idx = index_of_date_value(last) || (first.nil? ? -1 : start_idx)
        answer = (eval(var).each_cons(2).map { |val1, val2| val2 - val1 }.dup.unshift(nil))[start_idx..last_idx]
        return answer.length == 1 ? answer[0] : answer
      end
    end
    # should DRY out variable creation, probably by passing in a strategy along with the variable name
    define_method("#{var}_cumsum") do |first=nil, last=nil| # should work only on numeric data
      # this could be made more efficient by caching the full array and/or calculating only a subset of values
      time_vars.each do |tv_key, tv_val|
        start_idx = index_of_date_value(first) || 0
        last_idx = index_of_date_value(last) || (first.nil? ? -1 : start_idx)
        sum = eval(var)[0]
        answer = (eval(var).each_cons(2).map { |val1, val2| sum += val2 }.dup.unshift(eval(var)[start_idx]))[start_idx..last_idx]
        return answer.length == 1 ? answer[0] : answer
      end
    end
  end
  define_var_on(var)
  instance_variable_set("@#{var}", vals) if vals
  data_vars[var] = vals unless data_vars.has_key?(var)
end

#new_time_var(var, vals) ⇒ Object



85
86
87
88
89
90
# File 'lib/simple_time_series/simple_time_series.rb', line 85

def new_time_var(var, vals)
  define_getter_and_setter(var)
  instance_variable_set("@#{var}", vals) if vals
  time_vars[var] = vals unless time_vars.has_key?(var)
  define_var_on(var)
end

#set(data_var, date, value) ⇒ Object



79
80
81
82
# File 'lib/simple_time_series/simple_time_series.rb', line 79

def set(data_var, date, value)
  arr_index = index_of_date_value(date)
  current(data_var)[arr_index] = value
end

#sum_by_date(*data_var_names, opts) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/simple_time_series/simple_time_series.rb', line 32

def sum_by_date(*data_var_names, opts)
  arr = []
  data_var_names.each do |name|
    if opts[:start] && opts[:end]
      arr << find(name, opts[:start], opts[:end], opts)
    else
      arr << current(name, opts)
    end
  end
  arr = arr.transpose.map { |arr| arr.reduce(:+) }
  opts[:prepend_name] ? arr.dup.unshift(opts[:prepend_name]) : arr
end