Module: Nuggets::Array::MeanMixin

Included in:
Array
Defined in:
lib/nuggets/array/mean_mixin.rb

Instance Method Summary collapse

Instance Method Details

#arithmetic_mean(&block) ⇒ Object Also known as: mean, average, avg

call-seq:

array.arithmetic_mean => aFloat
array.arithmetic_mean { |x| ... } => aFloat

Calculates the arithmetic mean of the values in array.

An optional block may be passed to provide a weight for each value. Defaults to 1. Returns nil if the sum of all weights is zero (this includes array being empty).



70
71
72
# File 'lib/nuggets/array/mean_mixin.rb', line 70

def arithmetic_mean(&block)
  generalized_mean(1, &block)
end

#generalized_mean(exponent, &block) ⇒ Object Also known as: power_mean, minkowski_mean

call-seq:

array.generalized_mean(exponent) => aFloat
array.generalized_mean(exponent) { |x| ... } => aFloat

Calculates the generalized mean of the values in array for exponent. Returns the #geometric_mean if exponent is zero.

An optional block may be passed to provide a weight for each value. Defaults to 1. Returns nil if the sum of all weights is zero (this includes array being empty).



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/nuggets/array/mean_mixin.rb', line 42

def generalized_mean(exponent, &block)
  return geometric_mean(&block) if exponent.zero?

  total, weights = 0, 0

  each { |x|
    weight = block ? block[x] : 1

    total   += weight * x ** exponent
    weights += weight
  }

  (total / weights.to_f) ** (1.0 / exponent) unless weights.zero?
end

#geometric_meanObject Also known as: geomean

call-seq:

array.geometric_mean => aFloat
array.geometric_mean { |x| ... } => aFloat

Calculates the geometric mean of the values in array.

An optional block may be passed to provide a weight for each value. Defaults to 1. Returns nil if the sum of all weights is zero (this includes array being empty).



121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/nuggets/array/mean_mixin.rb', line 121

def geometric_mean
  total, weights = 1, 0

  each { |x|
    weight = block_given? ? yield(x) : 1

    total   *= x ** weight
    weights += weight
  }

  total ** (1 / weights.to_f) unless weights.zero?
end

#harmonic_mean(&block) ⇒ Object Also known as: harmean

call-seq:

array.harmonic_mean => aFloat
array.harmonic_mean { |x| ... } => aFloat

Calculates the harmonic mean of the values in array.

An optional block may be passed to provide a weight for each value. Defaults to 1. Returns nil if the sum of all weights is zero (this includes array being empty).



105
106
107
# File 'lib/nuggets/array/mean_mixin.rb', line 105

def harmonic_mean(&block)
  generalized_mean(-1, &block)
end

#report_mean(method = nil, precision = 4) ⇒ Object

call-seq:

array.report_mean => anArray
array.report_mean(method[, precision]) => anArray

Expects array to be an array of arrays (“rows”) of numeric values; the first “row” may consist of strings (labels) instead. Returns an array of strings with the mean (according to method, default #mean) of each “column”, prepended with the label, if present, and appended with the standard deviation, if available; all values are subject to precision.

If array is a flat array of numeric values, it is treated as a single “column”.

Returns nil if array is empty.

Examples (with standard deviation):

[[9.4, 34.75], [9.46, 34.68], [9.51, 34.61]].report_mean
#=> ["9.4567 +/- 0.0450", "34.6800 +/- 0.0572"]

[[9.4, 34.75], [9.46, 34.68], [9.51, 34.61]].report_mean(:harmonic)
#=> ["9.4565 +/- 0.0450", "34.6799 +/- 0.0572"]

[["a", "b"], [9.4, 34.75], [9.46, 34.68], [9.51, 34.61]].report_mean(nil, 2)
#=> ["a  9.46 +/- 0.04", "b  34.68 +/- 0.06"]

CSV.read('csv', headers: true, converters: :numeric).to_a.report_mean
#=> ["a    9.4567 +/- 0.0450", "b    34.6800 +/- 0.0572"]

[9.4, 9.46, 9.51].report_mean
#=> ["9.4567 +/- 0.0450"]

[34.75, 34.68, 34.61].report_mean
#=> ["34.6800 +/- 0.0572"]

[].report_mean
#=> nil


174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/nuggets/array/mean_mixin.rb', line 174

def report_mean(method = nil, precision = 4)
  return if empty?

  return clone.replace(self.class.new.push(self).transpose).
    report_mean(method, precision) unless first.is_a?(self.class)

  met, sep = [method ||= :mean, 'mean'], ['', '_']
  lab, std = first.first.is_a?(::String), respond_to?(:std)

  fmt = ["%-#{precision}s", "%.#{precision}f", "+/- %.#{precision}f"]

  until respond_to?(method) || sep.empty?
    method = met.join(sep.shift)
  end

  transpose.map! { |x|
    i, a = [], []

    i << 0 and a << x.shift if lab
    i << 1 and a << x.send(method)
    i << 2 and a << x.std if std

    fmt.values_at(*i).join(' ') % a
  }
end

#root_mean_square(&block) ⇒ Object Also known as: rms, quadratic_mean

call-seq:

array.root_mean_square => aFloat
array.root_mean_square { |x| ... } => aFloat

Calculates the root mean square (quadratic mean) of the values in array.

An optional block may be passed to provide a weight for each value. Defaults to 1. Returns nil if the sum of all weights is zero (this includes array being empty).



88
89
90
# File 'lib/nuggets/array/mean_mixin.rb', line 88

def root_mean_square(&block)
  generalized_mean(2, &block)
end