Module: Chartnado::GroupBy

Includes:
Series
Defined in:
lib/chartnado/group_by.rb

Instance Method Summary collapse

Methods included from Series

#median, #series_product, #series_ratio, #series_sum

Instance Method Details

#geometric_mean(array) ⇒ Object

Returns Value.

Returns:

  • Value



64
65
66
67
68
# File 'lib/chartnado/group_by.rb', line 64

def geometric_mean(array)
  array.reduce(:*) ** (1.0 / array.length)
rescue Math::DomainError
  nil
end

#group_by(group_name, scope, label_block = nil, &eval_block) ⇒ Multiple-Series

Examples:

group_by('tasks.user_id', Task.all) { count('DISTINCT project_id') }

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
42
# File 'lib/chartnado/group_by.rb', line 11

def group_by(group_name, scope, label_block = nil, &eval_block)
  group_values = [group_name] + scope.group_values
  series = scope.except(:group).group(group_values).
    instance_eval(&eval_block)

  if label_block
    update_key_from_block = lambda do |(key, data)|
      if key.is_a?(Array)
        group_key = key.first
        sub_key = key[1..-1]
        sub_key = sub_key.first if sub_key.length == 1
        data = {sub_key => data}
      else
        group_key = key
      end
      (new_key, data) = label_block.call(group_key, data)
      if key.is_a?(Array)
        {[new_key, *Array.wrap(sub_key)] => data.values.first}
      else
        {new_key => data}
      end
    end

    if series.length > 0
      series_sum *series.map(&update_key_from_block)
    else
      {}
    end
  else
    series
  end
end

#grouped_mean_and_median(series) ⇒ Object

Returns Value.

Returns:

  • Value



81
82
83
84
85
86
87
88
89
90
91
# File 'lib/chartnado/group_by.rb', line 81

def grouped_mean_and_median(series)
  series.group_by(&:first).reduce({}) do |hash, (key, values)|
    values = values.map(&:second).compact
    next hash unless values.present?
    hash[['median', key]] = median(values)
    hash[['mean', key]] = mean(values)
    hash[['geometric', key]] = geometric_mean(values)
    hash[['harmonic', key]] = harmonic_mean(values)
    hash
  end
end

#grouped_median(series) ⇒ Object

Returns Value.

Returns:

  • Value



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

def grouped_median(series)
  series.group_by(&:first).reduce({}) do |hash, (key, values)|
    hash[key] = median(values.map(&:second))
    hash
  end
end

#harmonic_mean(array) ⇒ Object

Returns Value.

Returns:

  • Value



56
57
58
59
60
# File 'lib/chartnado/group_by.rb', line 56

def harmonic_mean(array)
  array = array.reject(&:zero?)
  return nil unless array.present?
  array.size / (array.reduce(0) { |mean, value| mean + 1.0 / value })
end

#mean(array) ⇒ Object

Returns Value.

Examples:

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

Returns:

  • Value



50
51
52
# File 'lib/chartnado/group_by.rb', line 50

def mean(array)
  array.reduce(:+) / array.length
end