From f91df38a7d9c596673374ab395e6efb0dae79ba5 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Fri, 25 Aug 2023 11:30:13 +0200 Subject: [PATCH 1/2] Revert "Prepare standalone package, step 2 (#128)" 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. --- docs/src/index.md | 2 + src/Statistics.jl | 318 +++++++++++++++++++++++----------------------- 2 files changed, 160 insertions(+), 160 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 911f724d..25da1110 100644 --- a/src/Statistics.jl +++ b/src/Statistics.jl @@ -16,189 +16,189 @@ 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 MethodError - rethrow(ArgumentError("""mean(f, itr) requires a function and an iterable. - Perhaps you meant middle(x, y)?""",)) - end - Base.reduce_first(+, f_value)/1 +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 MethodError + rethrow(ArgumentError("""mean(f, itr) requires a function and an iterable. + Perhaps you meant middle(x, y)?""",)) 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) - function mean(r::AbstractRange{<:Real}) - isempty(r) && return oftype((first(r) + last(r)) / 2, NaN) - (first(r) + last(r)) / 2 +_mean_promote(x::T, y::S) where {T,S} = convert(promote_type(T, S), y) + +# ::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 +median(r::AbstractRange{<:Real}) = mean(r) + ##### variances ##### # faster computation of real(conj(x)*y) @@ -877,8 +877,6 @@ _median(v::AbstractArray, dims) = mapslices(median!, v, dims = dims) _median(v::AbstractArray{T}, ::Colon) where {T} = median!(copyto!(Array{T,1}(undef, length(v)), v)) -median(r::AbstractRange{<:Real}) = mean(r) - """ quantile!([q::AbstractArray, ] v::AbstractVector, p; sorted=false, alpha::Real=1.0, beta::Real=alpha) From 59287a228bd41fdcad5ae6ddec90e90cc35537bc Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sun, 10 Sep 2023 16:38:58 +0200 Subject: [PATCH 2/2] Keep `median` where it was --- src/Statistics.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Statistics.jl b/src/Statistics.jl index 12b462cf..0fd8417f 100644 --- a/src/Statistics.jl +++ b/src/Statistics.jl @@ -201,8 +201,6 @@ function mean(r::AbstractRange{<:Real}) (first(r) + last(r)) / 2 end -median(r::AbstractRange{<:Real}) = mean(r) - ##### variances ##### # faster computation of real(conj(x)*y) @@ -881,6 +879,8 @@ _median(v::AbstractArray, dims) = mapslices(median!, v, dims = dims) _median(v::AbstractArray{T}, ::Colon) where {T} = median!(copyto!(Array{T,1}(undef, length(v)), v)) +median(r::AbstractRange{<:Real}) = mean(r) + """ quantile!([q::AbstractArray, ] v::AbstractVector, p; sorted=false, alpha::Real=1.0, beta::Real=alpha)