diff --git a/.travis.yml b/.travis.yml index 0197a78b..d1a1cd10 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,18 +3,19 @@ os: - linux - osx julia: - - 0.7 - - 1.0 + - 1.2 + - 1.3 - nightly notifications: email: false # Work around a Travis bug git: depth: 999999 -# Uncomment the following lines to override the default test script -#script: -# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi -# - julia -e 'Pkg.clone(pwd()); Pkg.build("StatsBase"); Pkg.test("StatsBase"; coverage=true)' +script: + - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi + # Needed to take precedence on Julia's version of Statistics + - julia -e 'using UUIDs; write("Project.toml", replace(read("Project.toml", String), r"uuid = .*?\n" =>"uuid = \"$(uuid4())\"\n"))' + - julia --project --check-bounds=yes -e 'import Pkg; Pkg.build(); Pkg.test(; coverage=true)' after_success: - julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder()); Codecov.submit(process_folder())'; jobs: diff --git a/Project.toml b/Project.toml index 12c96773..0ed48328 100644 --- a/Project.toml +++ b/Project.toml @@ -1,8 +1,8 @@ name = "Statistics" -uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" [extras] diff --git a/appveyor.yml b/appveyor.yml index e3488828..5cd86c7f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ environment: matrix: - - julia_version: 0.7 - - julia_version: 1.0 + - julia_version: 1.2 + - julia_version: 1.3 - julia_version: nightly platform: @@ -29,8 +29,11 @@ install: - ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1")) build_script: - - echo "%JL_BUILD_SCRIPT%" - - C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%" + - C:\julia\bin\julia -e "using InteractiveUtils; versioninfo(); + using UUIDs; + # Needed to take precedence on Julia's version of Statistics + write(\"Project.toml\", replace(read(\"Project.toml\", String), r"uuid = .*?\\\\n\" =>\"uuid = \\\\"$(uuid4())\\\\"\\\\n\"))' + import Pkg; Pkg.build()" test_script: - echo "%JL_TEST_SCRIPT%" diff --git a/src/Statistics.jl b/src/Statistics.jl index ac17bf68..7ac651dd 100644 --- a/src/Statistics.jl +++ b/src/Statistics.jl @@ -11,15 +11,23 @@ using LinearAlgebra, SparseArrays using Base: has_offset_axes, require_one_based_indexing +using Printf: @printf + export cor, cov, std, stdm, var, varm, mean!, mean, median!, median, middle, quantile!, quantile, + # moments.jl skewness, kurtosis, + # weights.jl AbstractWeights, Weights, AnalyticWeights, FrequencyWeights, ProbabilityWeights, - weights, aweights, fweights, pweights - + weights, aweights, fweights, pweights, + # scalarstats.jl + geomean, harmmean, genmean, mode, modes, percentile, span, variation, sem, mad, mad!, + iqr, genvar, totalvar, entropy, renyientropy, crossentropy, kldivergence, describe + include("weights.jl") include("wsum.jl") include("moments.jl") +include("scalarstats.jl") ##### mean ##### @@ -1193,6 +1201,17 @@ julia> quantile(skipmissing([1, 10, missing]), 0.5) quantile(itr, p; sorted::Bool=false, weights::Union{AbstractArray,Nothing}=nothing) = _quantile(itr, p, sorted, weights) +""" + quantile(x, n::Integer) + +Return the n-quantiles of collection `x`, i.e. the values which +partition `v` into `n` subsets of nearly equal size. + +Equivalent to `quantile(x, [0:n]/n)`. For example, `quantile(x, 5)` +returns a vector of quantiles, respectively at `[0.0, 0.2, 0.4, 0.6, 0.8, 1.0]`. +""" +quantile(x, n::Integer) = quantile(x, (0:n)/n) + _quantile(itr, p, sorted::Bool, weights::Nothing) = quantile!(collect(itr), p, sorted=sorted) @@ -1272,6 +1291,13 @@ _quantile(v::AbstractArray, p::Real, sorted::Bool, w::AbstractArray) = _quantile(itr, p, sorted::Bool, weights) = throw(ArgumentError("weights are only supported with AbstractArrays inputs")) +""" + percentile(x, p) + +Return the `p`th percentile of a collection `x`, i.e. `quantile(x, p / 100)`. +""" +percentile(x, p) = quantile(x, p * 0.01) + ##### SparseArrays optimizations ##### function cov(X::SparseMatrixCSC; dims::Int=1, corrected::Bool=true) diff --git a/src/scalarstats.jl b/src/scalarstats.jl index cbecbb58..443a0ef7 100644 --- a/src/scalarstats.jl +++ b/src/scalarstats.jl @@ -165,24 +165,6 @@ end # ############################# -""" - percentile(x, p) - -Return the `p`th percentile of a collection `x`, i.e. `quantile(x, p / 100)`. -""" -percentile(x, p) = quantile(x, p * 0.01) - -# TODO: move to same place as other quantile methods -""" - quantile(x, n::Integer) - -Return the n-quantiles of collection `x`, i.e. the values which -partition `v` into `n` subsets of nearly equal size. - -Equivalent to `quantile(x, [0:n]/n)`. For example, `quantile(x, 5)` -returns a vector of quantiles, respectively at `[0.0, 0.2, 0.4, 0.6, 0.8, 1.0]`. -""" -quantile(x, n::Integer) = quantile(x, (0:n)/n) ############################# @@ -230,7 +212,7 @@ end sem(x::AbstractArray) = sqrt(var(x, corrected=true) / length(x)) # Median absolute deviation -@irrational mad_constant 1.4826022185056018 BigFloat("1.482602218505601860547076529360423431326703202590312896536266275245674447622701") +Base.@irrational mad_constant 1.4826022185056018 BigFloat("1.482602218505601860547076529360423431326703202590312896536266275245674447622701") """ mad(x; center=median(x), normalize=true) diff --git a/test/runtests.jl b/test/runtests.jl index 11a63619..d72ace48 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -509,6 +509,15 @@ end @test_throws ArgumentError quantile([1, NaN], 0.5) @test quantile(skipmissing([1, missing, 2]), 0.5) === 1.5 + @test quantile(1:5, 2) ≈ [1, 3, 5] + @test quantile(1:5, 4) ≈ [1:5;] + @test quantile(skipmissing([missing, 2, 5, missing]), 2) ≈ [2.0, 3.5, 5.0] + + @test percentile([1:5;], 25) ≈ 2.0 + @test percentile([1:5;], [25, 50, 75]) ≈ [2.0, 3.0, 4.0] + @test percentile(skipmissing([missing, 2, 5, missing]), 25) ≈ 2.75 + @test percentile(skipmissing([missing, 2, 5, missing]), [25, 50, 75]) ≈ [2.75, 3.5, 4.25] + # make sure that type inference works correctly in normal cases for T in [Int, BigInt, Float64, Float16, BigFloat, Rational{Int}, Rational{BigInt}] for S in [Float64, Float16, BigFloat, Rational{Int}, Rational{BigInt}] @@ -724,3 +733,4 @@ end include("weights.jl") include("wsum.jl") include("moments.jl") +include("scalarstats.jl") diff --git a/test/scalarstats.jl b/test/scalarstats.jl index ca5fd6d3..cc4dfc42 100644 --- a/test/scalarstats.jl +++ b/test/scalarstats.jl @@ -48,19 +48,6 @@ using DelimitedFiles @test_throws ArgumentError mode(Any[]) @test_throws ArgumentError modes(Any[]) - -###### quantile & friends - -@test quantile(1:5, 2) ≈ [1, 3, 5] -@test quantile(1:5, 4) ≈ [1:5;] -@test quantile(skipmissing([missing, 2, 5, missing]), 2) ≈ [2.0, 3.5, 5.0] - -@test percentile([1:5;], 25) ≈ 2.0 -@test percentile([1:5;], [25, 50, 75]) ≈ [2.0, 3.0, 4.0] -@test percentile(skipmissing([missing, 2, 5, missing]), 25) ≈ 2.75 -@test percentile(skipmissing([missing, 2, 5, missing]), [25, 50, 75]) ≈ [2.75, 3.5, 4.25] - - ##### Dispersion @test span([3, 4, 5, 6, 2]) == (2:6)