Maybe there was a better way, but this is what I came up with. For the record.
# array_arithmetic.jl
"""
mean(AbstractArray{T})`
Returns the arithmetic mean of all elements in the array, ignoring NaNs.
"""
function mean(x::AbstractArray{T}) where T<:Number
return mean_count(x)[1]
end
"""
`mean_abs(AbstractArray{T})`
Returns the arithmetic mean of the absolute values of all elements in the array, ignoring NaNs.
"""
function mean_abs(x::AbstractArray{T}) where T<:Number
return mean_count(x, absolute = true)[1]
end
"""
Returns a tuple of the arithmetic mean of all elements in the array, ignoring NaNs,
and the number of non-NaN values in the array.
"""
function mean_count(x::AbstractArray{T}; absolute = false) where T<:Number
z = zero(eltype(x))
sum = z
count = 0
@simd for i in x
count += ifelse(isnan(i), 0, 1)
if absolute; i = abs(i); end
sum += ifelse(isnan(i), z, i)
end
result = sum / count
return (result, count)
end
A = [1 2 3 4 5; 6 7 8 9 10]
mean(A)
mean_abs(A)
mean(convert.(Float64, A))
mean_abs(convert.(Float64, A))
B = [1 -2 3 -4 5; -6 7 -8 9 -10]
mean(B)
mean_abs(B)