Skip to content

Commit 00e61ba

Browse files
mzgubicMiha Zgubicnickrobinson251
authored
Add median function implementation (#41)
* add tests for median function * add median implementation * add documentation for median * version bump * change readme to include median function * do not change the inputs in median * use multiple dispatch rather than dims to flatten multidimensional array * Ensure type stability for median Co-authored-by: Nick Robinson <[email protected]> * add Float32 test * format comment according to REPL convention Co-authored-by: Miha Zgubic <[email protected]> Co-authored-by: Nick Robinson <[email protected]>
1 parent fe68737 commit 00e61ba

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name = "NaNMath"
22
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
33
repo = "https://github.com/mlubin/NaNMath.jl.git"
44
authors = ["Miles Lubin"]
5-
version = "0.3.3"
5+
version = "0.3.4"
66

77
[deps]
88

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ maximum
2121
minimum
2222
extrema
2323
mean
24+
median
2425
var
2526
std
2627
min

src/NaNMath.jl

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,51 @@ function sum(x::AbstractArray{T}) where T<:AbstractFloat
6161
return result
6262
end
6363

64+
"""
65+
NaNMath.median(A)
66+
67+
##### Args:
68+
* `A`: An array of floating point numbers
69+
70+
##### Returns:
71+
* Returns the median of all elements in the array, ignoring NaN's.
72+
Returns NaN for an empty array or array containing NaNs only.
73+
74+
##### Examples:
75+
```jldoctest
76+
julia> using NaNMath
77+
78+
julia> NaNMath.median([1., 2., 3., NaN])
79+
2.
80+
81+
julia> NaNMath.median([1., 2., NaN])
82+
1.5
83+
84+
julia> NaNMath.median([NaN])
85+
NaN
86+
```
87+
"""
88+
median(x::AbstractArray{<:AbstractFloat}) = median(collect(Iterators.flatten(x)))
89+
90+
function median(x::AbstractVector{<:AbstractFloat})
91+
92+
x = sort(filter(!isnan, x))
93+
94+
n = length(x)
95+
if n == 0
96+
return convert(eltype(x), NaN)
97+
elseif isodd(n)
98+
ind = ceil(Int, n/2)
99+
return x[ind]
100+
else
101+
ind = Int(n/2)
102+
lower = x[ind]
103+
upper = x[ind+1]
104+
return (lower + upper) / 2
105+
end
106+
107+
end
108+
64109
"""
65110
NaNMath.maximum(A)
66111
@@ -313,4 +358,3 @@ for f in (:min, :max)
313358
end
314359

315360
end
316-

test/runtests.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ using Test
2525
@test NaNMath.var([1., 2., NaN]) == 0.5
2626
@test NaNMath.std([1., 2., NaN]) == 0.7071067811865476
2727

28+
@test NaNMath.median([1.]) == 1.
29+
@test NaNMath.median([1., NaN]) == 1.
30+
@test NaNMath.median([NaN, 1., 3.]) == 2.
31+
@test NaNMath.median([1., 3., 2., NaN]) == 2.
32+
@test NaNMath.median([NaN, 1, 3]) == 2.
33+
@test NaNMath.median([1, 2, NaN]) == 1.5
34+
@test NaNMath.median([1 2; NaN NaN]) == 1.5
35+
@test NaNMath.median([NaN 2; 1 NaN]) == 1.5
36+
@test isnan(NaNMath.median(Float64[]))
37+
@test isnan(NaNMath.median(Float32[]))
38+
@test isnan(NaNMath.median([NaN]))
39+
2840
@test NaNMath.min(1, 2) == 1
2941
@test NaNMath.min(1.0, 2.0) == 1.0
3042
@test NaNMath.min(1, 2.0) == 1.0

0 commit comments

Comments
 (0)