Module: Chartnado::Series

Included in:
Evaluator::OperatorEvaluator, GroupBy, Renderer
Defined in:
lib/chartnado/series.rb

Instance Method Summary collapse

Instance Method Details

#median(array) ⇒ Object

Returns Value.

Examples:

median([0,1]) => {0.5}
median([0,1,1,2,2]) => {1}

Returns:

  • Value



137
138
139
140
141
# File 'lib/chartnado/series.rb', line 137

def median(array)
  sorted = array.sort
  len = sorted.length
  (sorted[(len - 1) / 2] + sorted[len / 2]) / 2.0
end

#series_product(val, series, precision: 2) ⇒ Series/Multiple-Series

Examples:

series_product(2.0, {0 => 1}) => {0 => 2.0}
series_product({0 => 1}, 2.0) => {0 => 2.0}

Returns:



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/chartnado/series.rb', line 11

def series_product(val, series, precision: 2)
  if dimensions(val) > dimensions(series)
    return series_product(series, val)
  end

  return with_precision(precision, val.to_f * series.to_f) unless series.respond_to?(:length)
  return series unless series.length > 0

  if is_an_array_of_named_series?(series) || series.is_a?(Array) && series.first.is_a?(Array)
    series.map { |(name, data)| [name, series_product(val, data)] }
  elsif series.is_a?(Hash)
    series.to_a.reduce({}) do |hash, (key, value)|
      if val.is_a?(Hash)
        if key.is_a?(Array)
          scalar = val[key.second]
        else
          scalar = val[key]
        end
      else
        scalar = val
      end
      scalar ||= 0
      hash[key] = scalar * value
      hash
    end
  else
    series.map do |value|
      val * value
    end
  end
end

#series_ratio(top_series, bottom_series, multiplier: 1.0, precision: 2) ⇒ Series/Multiple-Series

Examples:

series_ratio({0 => 1}, 2.0) => {0 => 0.5}

Returns:



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/chartnado/series.rb', line 48

def series_ratio(top_series, bottom_series, multiplier: 1.0, precision: 2)
  if bottom_series.is_a?(Numeric)
    return series_product(1.0 * multiplier / bottom_series, top_series, precision: precision)
  end
  if has_multiple_series?(top_series) && !has_multiple_series?(bottom_series)
    top_series_by_name = data_by_name(top_series)
    if is_an_array_of_named_series?(top_series)
      top_series_by_name.map do |name, top_values|
        [
          name,
          series_ratio(top_values, bottom_series, multiplier: multiplier, precision: precision)
        ]
      end
    else
      bottom_series.reduce({}) do |hash, (key, value)|
        top_series_by_name.keys.each do |name|
          top_key = [name, *key]
          top_value = top_series_by_name[name][top_key]
          if top_value
            hash[top_key] = series_ratio(top_value, value, multiplier: multiplier, precision: precision)
          end
        end
        hash
      end
    end
  elsif is_an_array_of_named_series?(bottom_series)
    top_series_by_name = data_by_name(top_series)
    bottom_series.map do |(name, data)|
      [
        name,
        series_ratio(top_series_by_name[name], data, multiplier: multiplier, precision: precision)
      ]
    end
  elsif bottom_series.respond_to?(:reduce)
    bottom_series.reduce({}) do |hash, (key, value)|
      hash[key] = series_ratio(top_series[key] || 0, value, multiplier: multiplier, precision: precision)
      hash
    end
  else
    with_precision(precision, top_series.to_f * multiplier.to_f / bottom_series.to_f)
  end
end

#series_sum(*series, scalar_sum: 0.0) ⇒ Series/Multiple-Series/Scalar

Examples:

series_sum({0 => 1}, 2.0) => {0 => 3.0}
series_sum({0 => 1}, {0 => 1}) => {0 => 2}
series_sum({0 => 1}, 2.0, 3.0) => {0 => 6.0}
series_sum(1, 2) => 3
series_sum() => []

Returns:



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
# File 'lib/chartnado/series.rb', line 100

def series_sum(*series, scalar_sum: 0.0)
  return [] unless series.length > 0

  (series, scalars) = series.partition { |s| s.respond_to?(:map) }
  scalar_sum += scalars.reduce(:+) || 0.0

  if series.first.is_a?(Hash)
    keys = series.map(&:keys).flatten(1).uniq
    keys.reduce({}) do |hash, key|
      hash[key] = (series.map { |s| s[key] }.compact.reduce(:+) || 0) + scalar_sum
      hash
    end
  elsif is_an_array_of_named_series?(series.first)
    series.flatten(1).group_by(&:first).map do |name, values|
      data = values.map(&:second).reduce(Hash.new(scalar_sum)) do |hash, values|
        values.each do |key, value|
          hash[key] += value
        end
        hash
      end
      [
        name, data
      ]
    end
  elsif series.first.is_a?(Array)
    series.map { |s| s.reduce(:+) + scalar_sum }
  else
    scalar_sum
  end
end