Skip to content

Commit

Permalink
Add generalized mean function (JuliaLang#209)
Browse files Browse the repository at this point in the history
  • Loading branch information
c123w authored and nalimilan committed Sep 20, 2016
1 parent 07109b6 commit 99ee7c3
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 3 deletions.
12 changes: 9 additions & 3 deletions docs/source/means.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ The package provides functions to compute means of different kinds.

Compute the harmonic mean of ``x``.

.. function:: genmean(x, p)

Compute the generalized/power mean of ``x`` with exponent ``p``,
i.e. :math:`\left( \frac{1}{n} \sum_{i=1}^n x_i^p \right)^{\frac{1}{p}}`, where ``n = length(x)``.
It is taken to be the geometric mean when ``p == 0``.

.. function:: trimmean(x, p)

Compute the trimmed mean of ``x``, with fraction ``p`` of elements ignored.
Expand All @@ -19,14 +25,14 @@ The package provides functions to compute means of different kinds.

.. code-block:: julia
# computes the mean using 80% of the numbers in ``x``,
# computes the mean using 80% of the numbers in ``x``,
# ignoring 10% of the largest and 10% of the smallest values.
trimmean(x, 0.2)
.. function:: mean(x, w)

The ``mean`` function is also extended to accept a weight vector of type ``WeightVec`` (see :ref:`weightvec`) to compute weighted mean.
The ``mean`` function is also extended to accept a weight vector of type ``WeightVec`` (see :ref:`weightvec`) to compute weighted mean.

**Examples:**

Expand All @@ -41,4 +47,4 @@ The package provides functions to compute means of different kinds.

.. function:: mean!(dst, x, w, dim)

Compute weighted means along a certain dimension, and write results to a pre-allocated destination vector ``dst``.
Compute weighted means along a certain dimension, and write results to a pre-allocated destination vector ``dst``.
1 change: 1 addition & 0 deletions src/StatsBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module StatsBase
## scalarstats
geomean, # geometric mean
harmmean, # harmonic mean
genmean, # generalized/power mean
trimmean, # trimmed mean
middle, # the mean of two real numbers
mode, # find a mode from data (the first one)
Expand Down
22 changes: 22 additions & 0 deletions src/scalarstats.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,28 @@ function harmmean(a::RealArray)
return n / s
end

# Generalized mean
"""
genmean(a, p)
Return the generalized/power mean with exponent `p` of a real-valued array,
i.e. ``\left( \frac{1}{n} \sum_{i=1}^n a_i^p \right)^{\frac{1}{p}}``, where `n = length(a)`.
It is taken to be the geometric mean when `p == 0`.
"""
function genmean(a::RealArray, p::Real)
if p == 0
return geomean(a)
end
s = 0.0
n = length(a)
for x in a
#= At least one of `x` or `p` must not be an int to avoid domain errors when `p` is a negative int.
We choose `x` in order to exploit exponentiation by squaring when `p` is an int. =#
@inbounds s += convert(Float64, x)^p
end
return (s/n)^(1/p)
end

# Trimmed mean
"""
trimmean(x, p)
Expand Down
12 changes: 12 additions & 0 deletions test/scalarstats.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ using Base.Test
@test_approx_eq harmmean(1:3) 3 / (1 + 1/2 + 1/3)
@test_approx_eq harmmean([1, 2, 4]) 12 / 7

## genmean
@test_approx_eq genmean([1,1,2,3], 1) 7/4
@test_approx_eq genmean([1,4,2], -1) 12/7
@test_approx_eq genmean([1,1,2,3], 0) (6.0)^(1/4)
@test_approx_eq genmean([1.2,-0.5,0], 2) sqrt(169/300)
@test_approx_eq genmean([16/9,0.25,1.0], 1.5) (755/648)^(2/3)
# Test numerical stability for `p` close to 0 (genmean should be close to geometric mean).
@test_approx_eq_eps genmean([1,1,2,3], -1e-8) (6.0)^(1/4) 1e-8
# Test numerical stability for large `p` (genmean should be close to max).
@test_approx_eq_eps genmean([0.98,1.02], 1e4) 1.02 1e-4


## trimmean

@test_approx_eq trimmean([-100, 2, 3, 7, 200], 0.0) 22.4
Expand Down

0 comments on commit 99ee7c3

Please sign in to comment.