@@ -626,7 +626,7 @@ is strictly superior to ``h``. The weighted ``p`` quantile is given by ``v_k +
626626with ``γ = (h - S_k)/(S_{k+1} - S_k)``. In particular, when all weights are equal,
627627the function returns the same result as the unweighted `quantile`.
628628"""
629- function quantile(v:: AbstractVector{V} , w:: AbstractWeights{W} , p:: AbstractVector{<:Real} ) where {V<: Real , W<: Real }
629+ function quantile(v:: AbstractVector{V} , w:: AbstractWeights{W} , p:: AbstractVector{<:Real} ) where {V, W<: Real }
630630 # checks
631631 isempty(v) && throw(ArgumentError(" quantile of an empty array is undefined" ))
632632 isempty(p) && throw(ArgumentError(" empty quantile array" ))
@@ -650,24 +650,32 @@ function quantile(v::AbstractVector{V}, w::AbstractWeights{W}, p::AbstractVector
650650 vw = sort!(collect(zip(view(v, nz), view(w, nz))))
651651 N = length(vw)
652652
653+ # missing is always sorted last
654+ if ismissing(vw[end ][1 ])
655+ throw(ArgumentError(" quantiles are undefined in presence of missing values" ))
656+ end
657+
653658 # prepare percentiles
654659 ppermute = sortperm(p)
655660 p = p[ppermute]
656661
657662 # prepare out vector
658- out = Vector{typeof(zero(V)/ 1 )}(undef, length(p))
663+ v1 = vw[1 ][1 ]
664+ out = Vector{typeof(v1 + zero(eltype(p))* zero(W)* zero(v1))}(undef, length(p))
659665 fill!(out, vw[end ][1 ])
660666
661- for x in v
662- isnan(x) && return fill!(out, x)
667+ # NaN is always sorted last in the absence of missing
668+ # This behavior isn't consistent with Statistics.quantile, but preserve it for backward compatibility
669+ if vw[end ][1 ] isa Number && isnan(vw[end ][1 ])
670+ return fill(vw[end ][1 ], length(p))
663671 end
664672
665673 # loop on quantiles
674+ w1 = vw[1 ][2 ]
666675 Sk, Skold = zero(W), zero(W)
667- vk, vkold = zero(V ), zero(V )
676+ vk, vkold = zero(v1 ), zero(v1 )
668677 k = 0
669678
670- w1 = vw[1 ][2 ]
671679 for i in 1 : length(p)
672680 if isa(w, FrequencyWeights)
673681 h = p[i] * (wsum - 1 ) + 1
@@ -693,19 +701,19 @@ function quantile(v::AbstractVector{V}, w::AbstractWeights{W}, p::AbstractVector
693701 return out
694702end
695703
696- function quantile(v:: AbstractVector{<:Real} , w:: UnitWeights , p:: AbstractVector{<:Real} )
704+ function quantile(v:: AbstractVector , w:: UnitWeights , p:: AbstractVector{<:Real} )
697705 length(v) != length(w) && throw(DimensionMismatch(" Inconsistent array dimension." ))
698706 return quantile(v, p)
699707end
700708
701- quantile(v:: AbstractVector{<:Real} , w:: AbstractWeights{<:Real} , p:: Number ) = quantile(v, w, [p])[1 ]
709+ quantile(v:: AbstractVector , w:: AbstractWeights , p:: Real ) = quantile(v, w, [p])[1 ]
702710
703711# #### Weighted median #####
704712
705713"""
706- median(v::AbstractVector{<:Real} , w::AbstractWeights)
714+ median(v::AbstractVector, w::AbstractWeights)
707715
708716Compute the weighted median of `v` with weights `w`
709717(of type `AbstractWeights`). See the documentation for [`quantile`](@ref) for more details.
710718"""
711- median(v:: AbstractVector{<:Real} , w:: AbstractWeights{<:Real} ) = quantile(v, w, 0.5 )
719+ median(v:: AbstractVector , w:: AbstractWeights ) = quantile(v, w, 0.5 )
0 commit comments