From 46290a0d703a42d74dba9080d5af460e97955f55 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sun, 10 Sep 2023 16:54:45 +0200 Subject: [PATCH] Revert "Prepare standalone package, step 2 (#128)" (#148) This reverts commit 14438ab59ec5ea76d6eea844f03040c692d3b1f3. `mean` will not be moved to Base as Statistics will remain an (upgradable) stdlib. Keep version at 1.11.0 though, and `median` where it is as the new place is more logical. --- docs/src/index.md | 2 + src/Statistics.jl | 320 +++++++++++++++++++++++----------------------- 2 files changed, 161 insertions(+), 161 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index c49b803a..93f3db59 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -9,6 +9,8 @@ var varm cor cov +mean! +mean median! median middle diff --git a/src/Statistics.jl b/src/Statistics.jl index 560b227d..0fd8417f 100644 --- a/src/Statistics.jl +++ b/src/Statistics.jl @@ -16,193 +16,191 @@ export cor, cov, std, stdm, var, varm, mean!, mean, ##### mean ##### -if !isdefined(Base, :mean) - """ - mean(itr) - - Compute the mean of all elements in a collection. - - !!! note - If `itr` contains `NaN` or [`missing`](@ref) values, the result is also - `NaN` or `missing` (`missing` takes precedence if array contains both). - Use the [`skipmissing`](@ref) function to omit `missing` entries and compute the - mean of non-missing values. - - # Examples - ```jldoctest - julia> using Statistics - - julia> mean(1:20) - 10.5 - - julia> mean([1, missing, 3]) - missing - - julia> mean(skipmissing([1, missing, 3])) - 2.0 - ``` - """ - mean(itr) = mean(identity, itr) - - """ - mean(f, itr) - - Apply the function `f` to each element of collection `itr` and take the mean. - - ```jldoctest - julia> using Statistics - - julia> mean(√, [1, 2, 3]) - 1.3820881233139908 - - julia> mean([√1, √2, √3]) - 1.3820881233139908 - ``` - """ - function mean(f, itr) - y = iterate(itr) - if y === nothing - return Base.mapreduce_empty_iter(f, +, itr, - Base.IteratorEltype(itr)) / 0 - end - count = 1 +""" + mean(itr) + +Compute the mean of all elements in a collection. + +!!! note + If `itr` contains `NaN` or [`missing`](@ref) values, the result is also + `NaN` or `missing` (`missing` takes precedence if array contains both). + Use the [`skipmissing`](@ref) function to omit `missing` entries and compute the + mean of non-missing values. + +# Examples +```jldoctest +julia> using Statistics + +julia> mean(1:20) +10.5 + +julia> mean([1, missing, 3]) +missing + +julia> mean(skipmissing([1, missing, 3])) +2.0 +``` +""" +mean(itr) = mean(identity, itr) + +""" + mean(f, itr) + +Apply the function `f` to each element of collection `itr` and take the mean. + +```jldoctest +julia> using Statistics + +julia> mean(√, [1, 2, 3]) +1.3820881233139908 + +julia> mean([√1, √2, √3]) +1.3820881233139908 +``` +""" +function mean(f, itr) + y = iterate(itr) + if y === nothing + return Base.mapreduce_empty_iter(f, +, itr, + Base.IteratorEltype(itr)) / 0 + end + count = 1 + value, state = y + f_value = f(value)/1 + total = Base.reduce_first(+, f_value) + y = iterate(itr, state) + while y !== nothing value, state = y - f_value = f(value)/1 - total = Base.reduce_first(+, f_value) + total += _mean_promote(total, f(value)) + count += 1 y = iterate(itr, state) - while y !== nothing - value, state = y - total += _mean_promote(total, f(value)) - count += 1 - y = iterate(itr, state) - end - return total/count end + return total/count +end - """ - mean(f, A::AbstractArray; dims) - - Apply the function `f` to each element of array `A` and take the mean over dimensions `dims`. +""" + mean(f, A::AbstractArray; dims) - !!! compat "Julia 1.3" - This method requires at least Julia 1.3. +Apply the function `f` to each element of array `A` and take the mean over dimensions `dims`. - ```jldoctest - julia> using Statistics +!!! compat "Julia 1.3" + This method requires at least Julia 1.3. - julia> mean(√, [1, 2, 3]) - 1.3820881233139908 +```jldoctest +julia> using Statistics - julia> mean([√1, √2, √3]) - 1.3820881233139908 +julia> mean(√, [1, 2, 3]) +1.3820881233139908 - julia> mean(√, [1 2 3; 4 5 6], dims=2) - 2×1 Matrix{Float64}: - 1.3820881233139908 - 2.2285192400943226 - ``` - """ - mean(f, A::AbstractArray; dims=:) = _mean(f, A, dims) +julia> mean([√1, √2, √3]) +1.3820881233139908 - function mean(f::Number, itr::Number) - f_value = try - f(itr) - catch err - if err isa MethodError && err.f === f && err.args == (itr,) - rethrow(ArgumentError("""mean(f, itr) requires a function and an iterable. - Perhaps you meant mean((x, y))?""")) - else - rethrow(err) - end +julia> mean(√, [1 2 3; 4 5 6], dims=2) +2×1 Matrix{Float64}: + 1.3820881233139908 + 2.2285192400943226 +``` +""" +mean(f, A::AbstractArray; dims=:) = _mean(f, A, dims) + +function mean(f::Number, itr::Number) + f_value = try + f(itr) + catch err + if err isa MethodError && err.f === f && err.args == (itr,) + rethrow(ArgumentError("""mean(f, itr) requires a function and an iterable. + Perhaps you meant mean((x, y))?""")) + else + rethrow(err) end - Base.reduce_first(+, f_value)/1 end + Base.reduce_first(+, f_value)/1 +end - """ - mean!(r, v) - - Compute the mean of `v` over the singleton dimensions of `r`, and write results to `r`. - - # Examples - ```jldoctest - julia> using Statistics - - julia> v = [1 2; 3 4] - 2×2 Matrix{Int64}: - 1 2 - 3 4 - - julia> mean!([1., 1.], v) - 2-element Vector{Float64}: - 1.5 - 3.5 - - julia> mean!([1. 1.], v) - 1×2 Matrix{Float64}: - 2.0 3.0 - ``` - """ - function mean!(R::AbstractArray, A::AbstractArray) - sum!(R, A; init=true) - x = max(1, length(R)) // length(A) - R .= R .* x - return R - end +""" + mean!(r, v) - """ - mean(A::AbstractArray; dims) +Compute the mean of `v` over the singleton dimensions of `r`, and write results to `r`. - Compute the mean of an array over the given dimensions. +# Examples +```jldoctest +julia> using Statistics - !!! compat "Julia 1.1" - `mean` for empty arrays requires at least Julia 1.1. +julia> v = [1 2; 3 4] +2×2 Matrix{Int64}: + 1 2 + 3 4 - # Examples - ```jldoctest - julia> using Statistics +julia> mean!([1., 1.], v) +2-element Vector{Float64}: + 1.5 + 3.5 - julia> A = [1 2; 3 4] - 2×2 Matrix{Int64}: - 1 2 - 3 4 +julia> mean!([1. 1.], v) +1×2 Matrix{Float64}: + 2.0 3.0 +``` +""" +function mean!(R::AbstractArray, A::AbstractArray) + sum!(R, A; init=true) + x = max(1, length(R)) // length(A) + R .= R .* x + return R +end - julia> mean(A, dims=1) - 1×2 Matrix{Float64}: - 2.0 3.0 +""" + mean(A::AbstractArray; dims) - julia> mean(A, dims=2) - 2×1 Matrix{Float64}: - 1.5 - 3.5 - ``` - """ - mean(A::AbstractArray; dims=:) = _mean(identity, A, dims) +Compute the mean of an array over the given dimensions. - _mean_promote(x::T, y::S) where {T,S} = convert(promote_type(T, S), y) +!!! compat "Julia 1.1" + `mean` for empty arrays requires at least Julia 1.1. - # ::Dims is there to force specializing on Colon (as it is a Function) - function _mean(f, A::AbstractArray, dims::Dims=:) where Dims - isempty(A) && return sum(f, A, dims=dims)/0 - if dims === (:) - n = length(A) - else - n = mapreduce(i -> size(A, i), *, unique(dims); init=1) - end - x1 = f(first(A)) / 1 - result = sum(x -> _mean_promote(x1, f(x)), A, dims=dims) - if dims === (:) - return result / n - else - return result ./= n - end - end +# Examples +```jldoctest +julia> using Statistics + +julia> A = [1 2; 3 4] +2×2 Matrix{Int64}: + 1 2 + 3 4 + +julia> mean(A, dims=1) +1×2 Matrix{Float64}: + 2.0 3.0 + +julia> mean(A, dims=2) +2×1 Matrix{Float64}: + 1.5 + 3.5 +``` +""" +mean(A::AbstractArray; dims=:) = _mean(identity, A, dims) + +_mean_promote(x::T, y::S) where {T,S} = convert(promote_type(T, S), y) - function mean(r::AbstractRange{<:Real}) - isempty(r) && return oftype((first(r) + last(r)) / 2, NaN) - (first(r) + last(r)) / 2 +# ::Dims is there to force specializing on Colon (as it is a Function) +function _mean(f, A::AbstractArray, dims::Dims=:) where Dims + isempty(A) && return sum(f, A, dims=dims)/0 + if dims === (:) + n = length(A) + else + n = mapreduce(i -> size(A, i), *, unique(dims); init=1) + end + x1 = f(first(A)) / 1 + result = sum(x -> _mean_promote(x1, f(x)), A, dims=dims) + if dims === (:) + return result / n + else + return result ./= n end end +function mean(r::AbstractRange{<:Real}) + isempty(r) && return oftype((first(r) + last(r)) / 2, NaN) + (first(r) + last(r)) / 2 +end + ##### variances ##### # faster computation of real(conj(x)*y)