Skip to content

Commit 750d93b

Browse files
committed
Fix statistics functions for non-1 indices
1 parent 28c9b2b commit 750d93b

File tree

3 files changed

+29
-19
lines changed

3 files changed

+29
-19
lines changed

base/sort.jl

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module Sort
44

5-
using Base: Order, Checked, copymutable, linearindices, linearindexing, viewindexing, LinearFast
5+
using Base: Order, Checked, copymutable, linearindices, linearindexing, viewindexing, LinearFast, _length
66

77
import
88
Base.sort,
@@ -66,7 +66,8 @@ issorted(itr;
6666
issorted(itr, ord(lt,by,rev,order))
6767

6868
function select!(v::AbstractVector, k::Union{Int,OrdinalRange}, o::Ordering)
69-
sort!(v, 1, length(v), PartialQuickSort(k), o)
69+
inds = indices(v, 1)
70+
sort!(v, first(inds), last(inds), PartialQuickSort(k), o)
7071
v[k]
7172
end
7273
select!(v::AbstractVector, k::Union{Int,OrdinalRange};
@@ -187,7 +188,7 @@ searchsorted{T<:Real}(a::Range{T}, x::Real, o::DirectOrdering) =
187188

188189
for s in [:searchsortedfirst, :searchsortedlast, :searchsorted]
189190
@eval begin
190-
$s(v::AbstractVector, x, o::Ordering) = $s(v,x,1,length(v),o)
191+
$s(v::AbstractVector, x, o::Ordering) = (inds = indices(v, 1); $s(v,x,first(inds),last(inds),o))
191192
$s(v::AbstractVector, x;
192193
lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) =
193194
$s(v,x,ord(lt,by,rev,order))
@@ -432,7 +433,7 @@ function sort!(v::AbstractVector;
432433
order::Ordering=Forward)
433434
ordr = ord(lt,by,rev,order)
434435
if ordr === Forward && isa(v,Vector) && eltype(v)<:Integer
435-
n = length(v)
436+
n = _length(v)
436437
if n > 1
437438
min, max = extrema(v)
438439
(diff, o1) = sub_with_overflow(max, min)
@@ -478,7 +479,7 @@ sort(v::AbstractVector; kws...) = sort!(copymutable(v); kws...)
478479
## selectperm: the permutation to sort the first k elements of an array ##
479480

480481
selectperm(v::AbstractVector, k::Union{Integer,OrdinalRange}; kwargs...) =
481-
selectperm!(Vector{eltype(k)}(length(v)), v, k; kwargs..., initialized=false)
482+
selectperm!(similar(Vector{eltype(k)}, indices(v,1)), v, k; kwargs..., initialized=false)
482483

483484
function selectperm!{I<:Integer}(ix::AbstractVector{I}, v::AbstractVector,
484485
k::Union{Int, OrdinalRange};
@@ -521,7 +522,7 @@ function sortperm(v::AbstractVector;
521522
order::Ordering=Forward)
522523
ordr = ord(lt,by,rev,order)
523524
if ordr === Forward && isa(v,Vector) && eltype(v)<:Integer
524-
n = length(v)
525+
n = _length(v)
525526
if n > 1
526527
min, max = extrema(v)
527528
(diff, o1) = sub_with_overflow(max, min)
@@ -553,7 +554,7 @@ function sortperm!{I<:Integer}(x::AbstractVector{I}, v::AbstractVector;
553554
order::Ordering=Forward,
554555
initialized::Bool=false)
555556
if indices(x,1) != indices(v,1)
556-
throw(ArgumentError("index vector must be the same length as the source vector, $(indices(x,1)) != $(indices(v,1))"))
557+
throw(ArgumentError("index vector must have the same indices as the source vector, $(indices(x,1)) != $(indices(v,1))"))
557558
end
558559
if !initialized
559560
@inbounds for i = indices(v,1)

base/statistics.jl

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ function mean(f::Callable, iterable)
2424
return total/count
2525
end
2626
mean(iterable) = mean(identity, iterable)
27-
mean(f::Callable, A::AbstractArray) = sum(f, A) / length(A)
28-
mean(A::AbstractArray) = sum(A) / length(A)
27+
mean(f::Callable, A::AbstractArray) = sum(f, A) / _length(A)
28+
mean(A::AbstractArray) = sum(A) / _length(A)
2929

3030
function mean!{T}(R::AbstractArray{T}, A::AbstractArray)
3131
sum!(R, A; init=true)
32-
scale!(R, length(R) / length(A))
32+
scale!(R, _length(R) / _length(A))
3333
return R
3434
end
3535

@@ -140,7 +140,7 @@ function centralize_sumabs2!{S,T,N}(R::AbstractArray{S}, A::AbstractArray{T,N},
140140
end
141141

142142
function varm{T}(A::AbstractArray{T}, m::Number; corrected::Bool=true)
143-
n = length(A)
143+
n = _length(A)
144144
n == 0 && return convert(real(momenttype(T)), NaN)
145145
n == 1 && return convert(real(momenttype(T)), abs2(A[1] - m)/(1 - Int(corrected)))
146146
return centralize_sumabs2(A, m) / (n - Int(corrected))
@@ -150,7 +150,7 @@ function varm!{S}(R::AbstractArray{S}, A::AbstractArray, m::AbstractArray; corre
150150
if isempty(A)
151151
fill!(R, convert(S, NaN))
152152
else
153-
rn = div(length(A), length(R)) - Int(corrected)
153+
rn = div(_length(A), _length(R)) - Int(corrected)
154154
scale!(centralize_sumabs2!(R, A, m), convert(S, 1/rn))
155155
end
156156
return R
@@ -282,7 +282,7 @@ stdm(iterable, m::Number; corrected::Bool=true) =
282282
_conj{T<:Real}(x::AbstractArray{T}) = x
283283
_conj(x::AbstractArray) = conj(x)
284284

285-
_getnobs(x::AbstractVector, vardim::Int) = length(x)
285+
_getnobs(x::AbstractVector, vardim::Int) = _length(x)
286286
_getnobs(x::AbstractMatrix, vardim::Int) = size(x, vardim)
287287

288288
function _getnobs(x::AbstractVecOrMat, y::AbstractVecOrMat, vardim::Int)
@@ -309,11 +309,11 @@ unscaled_covzm(x::AbstractMatrix, y::AbstractMatrix, vardim::Int) =
309309

310310
# covzm (with centered data)
311311

312-
covzm(x::AbstractVector, corrected::Bool=true) = unscaled_covzm(x) / (length(x) - Int(corrected))
312+
covzm(x::AbstractVector, corrected::Bool=true) = unscaled_covzm(x) / (_length(x) - Int(corrected))
313313
covzm(x::AbstractMatrix, vardim::Int=1, corrected::Bool=true) =
314314
scale!(unscaled_covzm(x, vardim), inv(size(x,vardim) - Int(corrected)))
315315
covzm(x::AbstractVector, y::AbstractVector, corrected::Bool=true) =
316-
unscaled_covzm(x, y) / (length(x) - Int(corrected))
316+
unscaled_covzm(x, y) / (_length(x) - Int(corrected))
317317
covzm(x::AbstractVecOrMat, y::AbstractVecOrMat, vardim::Int=1, corrected::Bool=true) =
318318
scale!(unscaled_covzm(x, y, vardim), inv(_getnobs(x, y, vardim) - Int(corrected)))
319319

@@ -568,16 +568,18 @@ function median!{T}(v::AbstractVector{T})
568568
isnan(x) && return x
569569
end
570570
end
571-
n = length(v)
571+
inds = indices(v, 1)
572+
n = length(inds)
573+
mid = div(first(inds)+last(inds),2)
572574
if isodd(n)
573-
return middle(select!(v,div(n+1,2)))
575+
return middle(select!(v,mid))
574576
else
575-
m = select!(v, div(n,2):div(n,2)+1)
577+
m = select!(v, mid:mid+1)
576578
return middle(m[1], m[2])
577579
end
578580
end
579581
median!{T}(v::AbstractArray{T}) = median!(vec(v))
580-
median{T}(v::AbstractArray{T}) = median!(copy!(Array{T,1}(length(v)), v))
582+
median{T}(v::AbstractArray{T}) = median!(copy!(Array{T,1}(_length(v)), v))
581583

582584
"""
583585
median(v[, region])

test/offsetarray.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,13 @@ I,J,N = findnz(z)
310310
@test find(x->x>0, h) == [-1,1]
311311
@test find(x->x<0, h) == [-2,0]
312312
@test find(x->x==0, h) == [2]
313+
@test mean(A_3_3) == median(A_3_3) == 5
314+
@test mean(x->2x, A_3_3) == 10
315+
@test mean(A_3_3, 1) == median(A_3_3, 1) == OffsetArray([2 5 8], (0,A_3_3.offsets[2]))
316+
@test mean(A_3_3, 2) == median(A_3_3, 2) == OffsetArray([4,5,6]'', (A_3_3.offsets[1],0))
317+
@test var(A_3_3) == 7.5
318+
@test std(A_3_3, 1) == OffsetArray([1 1 1], (0,A_3_3.offsets[2]))
319+
@test std(A_3_3, 2) == OffsetArray([3,3,3]'', (A_3_3.offsets[1],0))
313320

314321
@test_approx_eq vecnorm(v) vecnorm(parent(v))
315322
@test_approx_eq vecnorm(A) vecnorm(parent(A))

0 commit comments

Comments
 (0)