Skip to content
This repository has been archived by the owner on May 4, 2019. It is now read-only.

Commit

Permalink
Stop lying about eltype
Browse files Browse the repository at this point in the history
  • Loading branch information
andreasnoack committed Jul 29, 2017
1 parent 2103a21 commit 881d5ab
Show file tree
Hide file tree
Showing 12 changed files with 53 additions and 36 deletions.
4 changes: 1 addition & 3 deletions src/abstractdataarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
An `N`-dimensional `AbstractArray` whose entries can take on values of type
`T` or the value `NA`.
"""
abstract type AbstractDataArray{T, N} <: AbstractArray{T, N} end
abstract type AbstractDataArray{T, N} <: AbstractArray{Union{T,NAtype}, N} end

"""
AbstractDataVector{T}
Expand All @@ -20,8 +20,6 @@ A 2-dimensional [`AbstractDataArray`](@ref) with element type `T`.
"""
const AbstractDataMatrix{T} = AbstractDataArray{T, 2}

Base.eltype{T, N}(d::AbstractDataArray{T, N}) = T

# Generic iteration over AbstractDataArray's

Base.start(x::AbstractDataArray) = 1
Expand Down
2 changes: 1 addition & 1 deletion src/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,6 @@ Base.Broadcast.broadcast_indices(::Type{T}, A) where T<:AbstractDataArray = indi
@inline function Base.Broadcast.broadcast_c{S<:AbstractDataArray}(f, ::Type{S}, A, Bs...)
T = Base.Broadcast._broadcast_eltype(f, A, Bs...)
shape = Base.Broadcast.broadcast_indices(A, Bs...)
dest = S(T, Base.index_lengths(shape...))
dest = S(extractT(T), Base.index_lengths(shape...))
return broadcast!(f, dest, A, Bs...)
end
2 changes: 1 addition & 1 deletion src/dataarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ function Base.resize!{T}(da::DataArray{T,1}, n::Int)
end

function Base.similar(da::DataArray, T::Type, dims::Dims) #-> DataArray{T}
return DataArray(Array{T}(dims), trues(dims))
return DataArray(Array{extractT(T)}(dims), trues(dims))
end

Base.size(d::DataArray) = size(d.data) # -> (Int...)
Expand Down
12 changes: 12 additions & 0 deletions src/natype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,24 @@ struct NAException <: Exception
end
NAException() = NAException("NA found")

Base.promote_rule(::Type{Union{T,NAtype}}, ::Type{Union{S,NAtype}}) where {T<:Number,S<:Number} =
Union{promote_type(T,S),NAtype}
Base.promote_rule(::Type{T}, ::Type{Union{S,NAtype}}) where {T<:Number,S<:Number} =
Union{promote_type(T,S),NAtype}
Base.promote_rule(::Type{Union{T,NAtype}}, ::Type{S}) where {T<:Number,S<:Number} =
Union{promote_type(T,S),NAtype}

Base.length(x::NAtype) = 1
Base.size(x::NAtype) = ()
Base.size(x::NAtype, i::Integer) = i < 1 ? throw(BoundsError()) : 1
Base.ndims(x::NAtype) = 0
Base.getindex(x::NAtype, i) = i == 1 ? NA : throw(BoundsError())

Base.@pure extractT(::Type{T}) where {T} = T
Base.@pure extractT(::Type{Union{T,NAtype}}) where {T} = T

Base.zero(::Type{Union{T,NAtype}}) where {T} = zero(T)

"""
isna(x) -> Bool
Expand Down
25 changes: 13 additions & 12 deletions src/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ for f in [:+,:-,:*,:/]
end

# Unary operators, DataArrays.
@dataarray_unary(+, Any, T)
@dataarray_unary(-, Bool, Int)
@dataarray_unary(-, Any, T)
@dataarray_unary(!, Bool, T)
Expand Down Expand Up @@ -531,31 +532,31 @@ function (-){TA,TJ<:Number}(J::UniformScaling{TJ},A::DataArray{TA,2})
end

(+)(A::DataArray{Bool,2},J::UniformScaling{Bool}) =
invoke(+, Tuple{AbstractArray{Bool,2},UniformScaling{Bool}}, A, J)
invoke(+, Tuple{AbstractArray{Union{Bool,NAtype},2},UniformScaling{Bool}}, A, J)
(+)(J::UniformScaling{Bool},A::DataArray{Bool,2}) =
invoke(+, Tuple{UniformScaling{Bool},AbstractArray{Bool,2}}, J, A)
invoke(+, Tuple{UniformScaling{Bool},AbstractArray{Union{Bool,NAtype},2}}, J, A)
(-)(A::DataArray{Bool,2},J::UniformScaling{Bool}) =
invoke(-, Tuple{AbstractArray{Bool,2},UniformScaling{Bool}}, A, J)
invoke(-, Tuple{AbstractArray{Union{Bool,NAtype},2},UniformScaling{Bool}}, A, J)
(-)(J::UniformScaling{Bool},A::DataArray{Bool,2}) =
invoke(-, Tuple{UniformScaling{Bool},AbstractArray{Bool,2}}, J, A)
invoke(-, Tuple{UniformScaling{Bool},AbstractArray{Union{Bool,NAtype},2}}, J, A)

(+){TA,TJ}(A::AbstractDataArray{TA,2},J::UniformScaling{TJ}) =
invoke(+, Tuple{AbstractArray{TA,2},UniformScaling{TJ}}, A, J)
invoke(+, Tuple{AbstractArray{Union{TA,NAtype},2},UniformScaling{TJ}}, A, J)
(+){TA}(J::UniformScaling,A::AbstractDataArray{TA,2}) =
invoke(+, Tuple{UniformScaling,AbstractArray{TA,2}}, J, A)
invoke(+, Tuple{UniformScaling,AbstractArray{Union{TA,NAtype},2}}, J, A)
(-){TA,TJ<:Number}(A::AbstractDataArray{TA,2},J::UniformScaling{TJ}) =
invoke(-, Tuple{AbstractArray{TA,2},UniformScaling{TJ}}, A, J)
invoke(-, Tuple{AbstractArray{Union{TA,NAtype},2},UniformScaling{TJ}}, A, J)
(-){TA,TJ<:Number}(J::UniformScaling{TJ},A::AbstractDataArray{TA,2}) =
invoke(-, Tuple{UniformScaling{TJ},AbstractArray{TA,2}}, J, A)
invoke(-, Tuple{UniformScaling{TJ},AbstractArray{Union{TA,NAtype},2}}, J, A)

(+)(A::AbstractDataArray{Bool,2},J::UniformScaling{Bool}) =
invoke(+, Tuple{AbstractArray{Bool,2},UniformScaling{Bool}}, A, J)
invoke(+, Tuple{AbstractArray{Union{Bool,NAtype},2},UniformScaling{Bool}}, A, J)
(+)(J::UniformScaling{Bool},A::AbstractDataArray{Bool,2}) =
invoke(+, Tuple{UniformScaling{Bool},AbstractArray{Bool,2}}, J, A)
invoke(+, Tuple{UniformScaling{Bool},AbstractArray{Union{Bool,NAtype},2}}, J, A)
(-)(A::AbstractDataArray{Bool,2},J::UniformScaling{Bool}) =
invoke(-, Tuple{AbstractArray{Bool,2},UniformScaling{Bool}}, A, J)
invoke(-, Tuple{AbstractArray{Union{Bool,NAtype},2},UniformScaling{Bool}}, A, J)
(-)(J::UniformScaling{Bool},A::AbstractDataArray{Bool,2}) =
invoke(-, Tuple{UniformScaling{Bool},AbstractArray{Bool,2}}, J, A)
invoke(-, Tuple{UniformScaling{Bool},AbstractArray{Union{BoolNAtype},2}}, J, A)

end # if isdefined(Base, :UniformScaling)

Expand Down
13 changes: 6 additions & 7 deletions src/pooleddataarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,11 @@ end
PooledDataArray(d::PooledDataArray) = d

# Constructor from array, w/ pool, missingness, and ref type
function PooledDataArray{T,R<:Integer,N}(d::AbstractArray{T, N},
function PooledDataArray{T,R<:Integer,N}(d::Union{AbstractArray{T, N},
AbstractArray{Union{T,NAtype}, N}},
pool::Vector{T},
m::AbstractArray{Bool, N},
m::Union{AbstractArray{Bool, N},
AbstractArray{Union{Bool,NAtype}, N}},
r::Type{R} = DEFAULT_POOLED_REF_TYPE)
if length(pool) > typemax(R)
throw(ArgumentError("Cannot construct a PooledDataVector with type $R with a pool of size $(length(pool))"))
Expand Down Expand Up @@ -466,7 +468,7 @@ julia> p # has been modified
"B"
```
"""
function setlevels!{T,R}(x::PooledDataArray{T,R}, newpool::AbstractVector{T})
function setlevels!{T,R}(x::PooledDataArray{T,R}, newpool::AbstractVector)
if newpool == myunique(newpool) # no NAs or duplicates
x.pool = newpool
return x
Expand All @@ -483,9 +485,6 @@ function setlevels!{T,R}(x::PooledDataArray{T,R}, newpool::AbstractVector{T})
end
end

setlevels!{T, R}(x::PooledDataArray{T, R},
newpool::AbstractVector) = setlevels!(x, convert(Array{T}, newpool))

function setlevels(x::PooledDataArray, d::Dict)
newpool = copy(DataArray(x.pool))
# An NA in `v` is put in the pool; that will cause it to become NA
Expand Down Expand Up @@ -553,7 +552,7 @@ end
##############################################################################

function Base.similar{T,R}(pda::PooledDataArray{T,R}, S::Type, dims::Dims)
PooledDataArray(RefArray(zeros(R, dims)), S[])
PooledDataArray(RefArray(zeros(R, dims)), extractT(S)[])
end

##############################################################################
Expand Down
2 changes: 1 addition & 1 deletion src/reducedim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ end

function Base.mean!{T}(R::AbstractArray{T}, A::DataArray; skipna::Bool=false,
init::Bool=true)
init && fill!(R, zero(eltype(R)))
init && fill!(R, 0)
if skipna
C = Array{Int}(size(R))
_mapreducedim_skipna_impl!(identity, +, R, C, A)
Expand Down
8 changes: 4 additions & 4 deletions src/statistics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,25 @@ gl(n::Integer, k::Integer) = gl(n, k, n*k)
StatsBase.describe(X::DataVector) = StatsBase.describe(STDOUT, X)

function StatsBase.describe{T<:Real}(io::IO, X::AbstractDataVector{T})
nacount = sum(isna.(X))
nacount = sum(isna, X)
pna = 100nacount/length(X)
if pna != 100 # describe will fail if dropna returns an empty vector
describe(io, dropna(X))
else
println(io, "Summary Stats:")
println(io, "Type: $(eltype(X))")
println(io, "Type: $(T)")
end
println(io, "Number Missing: $(nacount)")
@printf(io, "%% Missing: %.6f\n", pna)
return
end

function StatsBase.describe(io::IO, X::AbstractDataVector)
nacount = sum(isna.(X))
nacount = sum(isna, X)
pna = 100nacount/length(X)
println(io, "Summary Stats:")
println(io, "Length: $(length(X))")
println(io, "Type: $(eltype(X))")
println(io, "Type: $(extractT(eltype(X)))")
println(io, "Number Unique: $(length(unique(X)))")
println(io, "Number Missing: $(nacount)")
@printf(io, "%% Missing: %.6f\n", pna)
Expand Down
6 changes: 3 additions & 3 deletions test/constructors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
@test isequal(dv, convert(DataArray, 1:3))

dv = DataArray(Int, 3)
@test isequal(eltype(dv), Int)
@test isequal(eltype(dv), Union{Int,NAtype})
@test isequal(dv.na, trues(3))

dv = convert(DataArray, zeros(3))
Expand Down Expand Up @@ -67,7 +67,7 @@
@test isequal(pdv, convert(PooledDataArray, PooledDataArray([1, 2, 3])))

pdv = PooledDataArray(Int, 3)
@test isequal(eltype(pdv), Int)
@test isequal(eltype(pdv), Union{Int,NAtype})
@test all(isna.(pdv) .== trues(3))

pdv = convert(PooledDataArray, zeros(3))
Expand Down Expand Up @@ -106,7 +106,7 @@
@test isequal(dm, convert(DataArray, trues(2, 2)))

dm = DataArray(Int, 2, 2)
@test isequal(eltype(dm), Int)
@test isequal(eltype(dm), Union{Int,NAtype})
@test isequal(dm.na, trues(2, 2))

@test_nowarn convert(DataArray, zeros(2, 2))
Expand Down
6 changes: 3 additions & 3 deletions test/data.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@
@test size(dvint) == (4,)
@test length(dvint) == 4
@test sum(isna.(dvint)) == 1
@test eltype(dvint) == Int
@test eltype(dvint) == Union{Int,NAtype}

#test_group("PooledDataVector methods")
@test size(pdvstr) == (7,)
@test length(pdvstr) == 7
@test sum(isna.(pdvstr)) == 1
@test eltype(pdvstr) == String
@test eltype(pdvstr) == Union{String,NAtype}

#test_group("DataVector operations")
@test isequal(dvint .+ 1, DataArray([2, 3, 4, 5], [false, false, true, false]))
Expand All @@ -99,7 +99,7 @@
@test all(convert(Vector{Int}, dvint2) .== [5:8;])
@test all([i + 1 for i in dvint2] .== [6:9;])
@test all([length(x)::Int for x in dvstr] == [3, 3, 1, 4])
@test repr(dvint) == "[1, 2, NA, 4]"
@test repr(dvint) == "Union{DataArrays.NAtype, Int64}[1, 2, NA, 4]"

#test_group("PooledDataVector to something else")
@test all(dropna(pdvstr) .== ["one", "one", "two", "two", "one", "one"])
Expand Down
2 changes: 1 addition & 1 deletion test/dataarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
end

# Inferrability of map (#276)
@test eltype(map(x -> x > 1, @data [1, 2])) == Bool
@test eltype(map(x -> x > 1, @data [1, 2])) == Union{Bool,NAtype}

@testset "Issue #278" begin
x = @data ones(4)
Expand Down
7 changes: 7 additions & 0 deletions test/nas.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,11 @@
@test_throws NAException for v in each_failna(dv); end
@test collect(each_dropna(dv)) == a
@test collect(each_replacena(dv, 4)) == [4, 4, a..., 4]

@testset "promotion" begin
@test promote_type(Int, Union{Float64,NAtype}) == Union{Float64,NAtype}
@test promote_type(Union{Int,NAtype}, Float64) == Union{Float64,NAtype}
@test promote_type(Union{Int,NAtype}, Union{Float64,NAtype}) == Union{Float64,NAtype}
end

end

0 comments on commit 881d5ab

Please sign in to comment.