From 4abf776da3b3cf7c352151413da9189686180fe1 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Fri, 23 Apr 2021 22:46:32 +0200 Subject: [PATCH] Add `CategoricalValue(x, source)` and disallow mixed `isless` and `<` (#346) `isless` and `<` between `CategoricalValue` and other types can breaks transitivity. Require converting the value to a `CategoricalValue`, attaching it to a pool, using `CategoricalValue(x, source::Union{CategoricalValue, CategoricalArray)`. Deprecate `CategoricalValue(i::Integer, pool::CategoricalPool)` in favor of `pool[i]` or `CategoricalValue(pool, i)`, as the order is more logical and it avoids a potential ambiguity if `source::CategoricalPool` is allowed in the future. --- src/array.jl | 10 +- src/deprecated.jl | 1 + src/missingarray.jl | 8 +- src/pool.jl | 4 +- src/typedefs.jl | 2 +- src/value.jl | 54 +++++----- test/01_value.jl | 30 ++++-- test/04_constructors.jl | 2 +- test/05_convert.jl | 10 +- test/06_show.jl | 24 ++--- test/07_levels.jl | 26 ++--- test/08_equality.jl | 18 ++-- test/09_hash.jl | 16 +-- test/10_isless.jl | 68 ++++++------ test/11_array.jl | 162 ++++++++++++++-------------- test/12_missingarray.jl | 232 ++++++++++++++++++++-------------------- 16 files changed, 345 insertions(+), 322 deletions(-) diff --git a/src/array.jl b/src/array.jl index 09456ae5..d095c471 100644 --- a/src/array.jl +++ b/src/array.jl @@ -498,7 +498,7 @@ end end Base.fill(v::CategoricalValue{T}, dims::NTuple{N, Integer}) where {T, N} = - CategoricalArray{T, N}(fill(level(v), dims), copy(pool(v))) + CategoricalArray{T, N}(fill(refcode(v), dims), copy(pool(v))) # to avoid ambiguity Base.fill(v::CategoricalValue, dims::Tuple{}) = @@ -953,9 +953,9 @@ end function in(x::CategoricalValue, y::CategoricalArray{T, N, R}) where {T, N, R} if x.pool === y.pool - return x.level in y.refs + return refcode(x) in y.refs else - ref = get(y.pool, levels(x.pool)[x.level], zero(R)) + ref = get(y.pool, levels(x.pool)[refcode(x)], zero(R)) return ref != 0 ? ref in y.refs : false end end @@ -1029,8 +1029,8 @@ function Base.sort!(v::CategoricalVector; seen = counts .> 0 anymissing = eltype(v) >: Missing && seen[1] levs = eltype(v) >: Missing ? - eltype(v)[i == 0 ? missing : CategoricalValue(i, v.pool) for i in 0:length(v.pool)] : - eltype(v)[CategoricalValue(i, v.pool) for i in 1:length(v.pool)] + eltype(v)[i == 0 ? missing : CategoricalValue(v.pool, i) for i in 0:length(v.pool)] : + eltype(v)[CategoricalValue(v.pool, i) for i in 1:length(v.pool)] sortedlevs = sort!(Vector(view(levs, seen)), order=ord) levelsmap = something.(indexin(sortedlevs, levs)) j = 0 diff --git a/src/deprecated.jl b/src/deprecated.jl index 9f29f27c..667b2923 100644 --- a/src/deprecated.jl +++ b/src/deprecated.jl @@ -15,3 +15,4 @@ end import Base: get @deprecate get(x::CategoricalValue) DataAPI.unwrap(x) +@deprecate CategoricalValue(i::Integer, pool::CategoricalPool) pool[i] \ No newline at end of file diff --git a/src/missingarray.jl b/src/missingarray.jl index da04a72b..8383d354 100644 --- a/src/missingarray.jl +++ b/src/missingarray.jl @@ -32,12 +32,12 @@ Base.fill!(A::CategoricalArray{>:Missing}, ::Missing) = (fill!(A.refs, 0); A) in(x::Missing, y::CategoricalArray) = false in(x::Missing, y::CategoricalArray{>:Missing}) = !all(v -> v > 0, y.refs) -function Missings.replace(a::CategoricalArray{S, N, R, V, C}, replacement::V) where {S, N, R, V, C} +function Missings.replace(a::CategoricalArray{T, N, R, V, C}, replacement::V) where {T, N, R, V, C} pool = copy(a.pool) - v = C(get!(pool, replacement), pool) + v = C(pool, get!(pool, replacement)) Missings.replace(a, v) end -function collect(r::Missings.EachReplaceMissing{<:CategoricalArray{S, N, R, C}}) where {S, N, R, C} - CategoricalArray{C,N}(R[v.level for v in r], r.replacement.pool) +function collect(r::Missings.EachReplaceMissing{<:CategoricalArray{T, N, R, V}}) where {T, N, R, V} + CategoricalArray{V,N}(R[refcode(v) for v in r], r.replacement.pool) end diff --git a/src/pool.jl b/src/pool.jl index 71c375b5..812d285d 100644 --- a/src/pool.jl +++ b/src/pool.jl @@ -50,7 +50,7 @@ end Base.length(pool::CategoricalPool) = length(pool.levels) -Base.getindex(pool::CategoricalPool, i::Integer) = CategoricalValue(i, pool) +Base.getindex(pool::CategoricalPool, i::Integer) = CategoricalValue(pool, i) Base.get(pool::CategoricalPool, level::Any) = pool.invindex[level] Base.get(pool::CategoricalPool, level::Any, default::Any) = get(pool.invindex, level, default) @@ -148,7 +148,7 @@ end @inline function Base.get!(pool::CategoricalPool, level::CategoricalValue) if pool === level.pool || pool == level.pool - return level.level + return refcode(level) end if level.pool ⊈ pool if isordered(pool) diff --git a/src/typedefs.jl b/src/typedefs.jl index 83ea9608..7359b4d6 100644 --- a/src/typedefs.jl +++ b/src/typedefs.jl @@ -82,8 +82,8 @@ the order of the pool's [`levels`](@ref DataAPI.levels) is used rather than the ordering of values of type `T`. """ struct CategoricalValue{T <: SupportedTypes, R <: Integer} - level::R pool::CategoricalPool{T, R, CategoricalValue{T, R}} + ref::R end ## Arrays diff --git a/src/value.jl b/src/value.jl index c480dab7..7cb140b8 100644 --- a/src/value.jl +++ b/src/value.jl @@ -1,5 +1,18 @@ -CategoricalValue(level::Integer, pool::CategoricalPool{T, R}) where {T, R} = - CategoricalValue(convert(R, level), pool) +CategoricalValue(pool::CategoricalPool{T, R}, level::Integer) where {T, R} = + CategoricalValue(pool, convert(R, level)) + +""" + CategoricalValue(value, source::Union{CategoricalValue, CategoricalArray}) + +Return a `CategoricalValue` object wrapping `value` and attached to +the [`CategoricalPool`](@ref) of `source`. +""" +function CategoricalValue(value, source::Union{CategoricalValue, CatArrOrSub}) + p = pool(source) + i = get(p, value, nothing) + i === nothing && throw(ArgumentError("level $value not found in source pool")) + return CategoricalValue(p, i) +end leveltype(::Type{<:CategoricalValue{T}}) where {T} = T leveltype(::Type{T}) where {T} = T @@ -12,7 +25,7 @@ reftype(::Type{<:CategoricalValue{<:Any, R}}) where {R} = R reftype(x::Any) = reftype(typeof(x)) pool(x::CategoricalValue) = x.pool -level(x::CategoricalValue) = x.level +refcode(x::CategoricalValue) = x.ref isordered(x::CategoricalValue) = isordered(x.pool) # extract the type of the original value from array eltype `T` @@ -29,7 +42,7 @@ unwrap_catvaluetype(::Type{T}) where {T <: CategoricalValue} = leveltype(T) Get the value wrapped by categorical value `x`. If `x` is `Missing` return `missing`. """ -DataAPI.unwrap(x::CategoricalValue) = levels(x)[level(x)] +DataAPI.unwrap(x::CategoricalValue) = levels(x)[refcode(x)] """ levelcode(x::CategoricalValue) @@ -37,7 +50,7 @@ DataAPI.unwrap(x::CategoricalValue) = levels(x)[level(x)] Get the code of categorical value `x`, i.e. its index in the set of possible values returned by [`levels(x)`](@ref DataAPI.levels). """ -levelcode(x::CategoricalValue) = Signed(widen(level(x))) +levelcode(x::CategoricalValue) = Signed(widen(refcode(x))) """ levelcode(x::Missing) @@ -107,7 +120,7 @@ Base.String(x::CategoricalValue{<:AbstractString}) = String(unwrap(x)) @inline function Base.:(==)(x::CategoricalValue, y::CategoricalValue) if pool(x) === pool(y) || pool(x) == pool(y) - return level(x) == level(y) + return refcode(x) == refcode(y) else return unwrap(x) == unwrap(y) end @@ -118,7 +131,7 @@ Base.:(==)(x::SupportedTypes, y::CategoricalValue) = x == unwrap(y) @inline function Base.isequal(x::CategoricalValue, y::CategoricalValue) if pool(x) === pool(y) || pool(x) == pool(y) - return level(x) == level(y) + return refcode(x) == refcode(y) else return isequal(unwrap(x), unwrap(y)) end @@ -140,8 +153,11 @@ function Base.isless(x::CategoricalValue, y::CategoricalValue) end end -Base.isless(x::CategoricalValue, y::SupportedTypes) = levelcode(x) < levelcode(x.pool[get(x.pool, y)]) -Base.isless(y::SupportedTypes, x::CategoricalValue) = levelcode(x.pool[get(x.pool, y)]) < levelcode(x) +Base.isless(x::CategoricalValue, y::SupportedTypes) = + throw(ArgumentError("cannot compare a `CategoricalValue` to value `v` of type " * + "`$(typeof(x))`: wrap `v` using `CategoricalValue(v, catvalue)` " * + "or `CategoricalValue(v, catarray)` first")) +Base.isless(y::SupportedTypes, x::CategoricalValue) = isless(x, y) function Base.:<(x::CategoricalValue, y::CategoricalValue) poolx = pool(x) @@ -157,21 +173,11 @@ function Base.:<(x::CategoricalValue, y::CategoricalValue) end end -function Base.:<(x::CategoricalValue, y::SupportedTypes) - if !isordered(pool(x)) - throw(ArgumentError("Unordered CategoricalValue objects cannot be tested for order using <. Use isless instead, or call the ordered! function on the parent array to change this")) - else - return levelcode(x) < levelcode(x.pool[get(x.pool, y)]) - end -end - -function Base.:<(y::SupportedTypes, x::CategoricalValue) - if !isordered(pool(x)) - throw(ArgumentError("Unordered CategoricalValue objects cannot be tested for order using <. Use isless instead, or call the ordered! function on the parent array to change this")) - else - return levelcode(x.pool[get(x.pool, y)]) < levelcode(x) - end -end +Base.:<(x::CategoricalValue, y::SupportedTypes) = + throw(ArgumentError("cannot compare a `CategoricalValue` to value `v` of type " * + "`$(typeof(x))`: wrap `v` using `CategoricalValue(v, catvalue)` " * + "or `CategoricalValue(v, catarray)` first")) +Base.:<(y::SupportedTypes, x::CategoricalValue) = x < y # JSON of CategoricalValue is JSON of the value it refers to JSON.lower(x::CategoricalValue) = JSON.lower(unwrap(x)) diff --git a/test/01_value.jl b/test/01_value.jl index 3c03e62c..39f58b67 100644 --- a/test/01_value.jl +++ b/test/01_value.jl @@ -1,7 +1,7 @@ module TestValue using Test using CategoricalArrays -using CategoricalArrays: DefaultRefType, level, reftype, leveltype +using CategoricalArrays: DefaultRefType, refcode, reftype, leveltype @testset "leveltype on non CategoricalValue types" begin @test leveltype("abc") === String @@ -20,7 +20,7 @@ end ) for i in 1:3 - x = CategoricalValue(i, pool) + x = CategoricalValue(pool, i) @test leveltype(x) === String @test leveltype(typeof(x)) === String @@ -28,11 +28,11 @@ end @test reftype(typeof(x)) === DefaultRefType @test x isa CategoricalValue{String, DefaultRefType} - @test level(x) === DefaultRefType(i) + @test refcode(x) === DefaultRefType(i) @test CategoricalArrays.pool(x) === pool @test typeof(x)(x) === x - @test CategoricalValue(UInt8(i), pool) == x + @test CategoricalValue(pool, UInt8(i)) == x end end @@ -46,7 +46,7 @@ end ) for i in 1:3 - x = CategoricalValue(i, pool) + x = CategoricalValue(pool, i) @test leveltype(x) === String @test leveltype(typeof(x)) === String @@ -54,11 +54,27 @@ end @test reftype(typeof(x)) === UInt8 @test x isa CategoricalValue{String, UInt8} - @test level(x) === UInt8(i) + @test refcode(x) === UInt8(i) @test CategoricalArrays.pool(x) === pool @test typeof(x)(x) === x - @test CategoricalValue(UInt32(i), pool) == x + @test CategoricalValue(pool, UInt32(i)) == x + end +end + +@testset "constructor from other value" begin + pool = CategoricalPool([2, 3, 1]) + arr = CategoricalVector{Int}(DefaultRefType[2, 1, 3], pool) + for x in (CategoricalValue(pool, 1), arr, view(arr, 2:3)) + for (i, v) in enumerate(levels(pool)) + @test CategoricalValue(v, x) === + CategoricalValue(float(v), x) === + CategoricalValue(CategoricalValue(pool, i), x) === + CategoricalValue(pool, i) + end + + @test_throws ArgumentError CategoricalValue(4, x) + @test_throws ArgumentError CategoricalValue(missing, x) end end diff --git a/test/04_constructors.jl b/test/04_constructors.jl index a338c044..e7990a07 100644 --- a/test/04_constructors.jl +++ b/test/04_constructors.jl @@ -157,7 +157,7 @@ end pool = CategoricalPool{Float64, UInt8}([1.0, 2.0, 3.0]) @test isa(pool, CategoricalPool{Float64, UInt8, CategoricalValue{Float64, UInt8}}) - @test CategoricalValue(1, pool) isa CategoricalValue{Float64, UInt8} + @test CategoricalValue(pool, 1) isa CategoricalValue{Float64, UInt8} end @testset "Invalid arguments" begin diff --git a/test/05_convert.jl b/test/05_convert.jl index 65a46d39..8558bdf0 100644 --- a/test/05_convert.jl +++ b/test/05_convert.jl @@ -1,7 +1,7 @@ module TestConvert using Test using CategoricalArrays -using CategoricalArrays: DefaultRefType, level, reftype, leveltype +using CategoricalArrays: DefaultRefType, refcode, reftype, leveltype @testset "convert() for CategoricalPool{Int, DefaultRefType} and values" begin pool = CategoricalPool([1, 2, 3]) @@ -12,9 +12,9 @@ using CategoricalArrays: DefaultRefType, level, reftype, leveltype convert(CategoricalPool{Float64}, pool) convert(CategoricalPool, pool) - v1 = CategoricalValue(1, pool) - v2 = CategoricalValue(2, pool) - v3 = CategoricalValue(3, pool) + v1 = CategoricalValue(pool, 1) + v2 = CategoricalValue(pool, 2) + v3 = CategoricalValue(pool, 3) @test eltype(v1) === Any @test eltype(typeof(v1)) === Any @test leveltype(v1) === Int @@ -153,7 +153,7 @@ end @testset "levelcode" begin pool = CategoricalPool{Int,UInt8}([2, 1, 3]) for i in 1:3 - v = CategoricalValue(i, pool) + v = CategoricalValue(pool, i) @test levelcode(v) isa Int16 @test levels(pool)[levelcode(v)] == v end diff --git a/test/06_show.jl b/test/06_show.jl index 0940c6d9..7ca4cf01 100644 --- a/test/06_show.jl +++ b/test/06_show.jl @@ -7,13 +7,13 @@ using CategoricalArrays pool = CategoricalPool(["c", "b", "a"]) opool = CategoricalPool(["c", "b", "a"], true) - nv1 = CategoricalValue(1, pool) - nv2 = CategoricalValue(2, pool) - nv3 = CategoricalValue(3, pool) + nv1 = CategoricalValue(pool, 1) + nv2 = CategoricalValue(pool, 2) + nv3 = CategoricalValue(pool, 3) - ov1 = CategoricalValue(1, opool) - ov2 = CategoricalValue(2, opool) - ov3 = CategoricalValue(3, opool) + ov1 = CategoricalValue(opool, 1) + ov2 = CategoricalValue(opool, 2) + ov3 = CategoricalValue(opool, 3) if VERSION >= v"1.6.0" @test sprint(show, pool) == "$CategoricalPool{String, UInt32}([\"c\", \"b\", \"a\"])" @@ -78,7 +78,7 @@ using JSON @testset "JSON.lower" for pool in (CategoricalPool(["a"]), CategoricalPool([1]), CategoricalPool([1.0])) - v = CategoricalValue(1, pool) + v = CategoricalValue(pool, 1) @test JSON.lower(v) == JSON.lower(unwrap(v)) @test typeof(JSON.lower(v)) == typeof(JSON.lower(unwrap(v))) end @@ -86,22 +86,22 @@ end using JSON3 using StructTypes @testset "JSON3.write" begin - v = CategoricalValue(1, CategoricalPool(["a"])) + v = CategoricalValue(CategoricalPool(["a"]), 1) @test JSON3.write(v) === "\"a\"" - v = CategoricalValue(1, CategoricalPool([1])) + v = CategoricalValue(CategoricalPool([1]), 1) @test JSON3.write(v) === "1" @test StructTypes.numbertype(typeof(v)) === Int - v = CategoricalValue(1, CategoricalPool([2.0])) + v = CategoricalValue(CategoricalPool([2.0]), 1) @test JSON3.write(v) === "2.0" @test StructTypes.numbertype(typeof(v)) === Float64 - v = CategoricalValue(1, CategoricalPool([BigFloat(3.0,10)])) + v = CategoricalValue(CategoricalPool([BigFloat(3.0,10)]), 1) @test JSON3.write(v) === "3.0" @test StructTypes.numbertype(typeof(v)) === BigFloat - v = CategoricalValue(2, CategoricalPool([true,false])) + v = CategoricalValue(CategoricalPool([true,false]), 2) @test JSON3.write(v) == "false" @test StructTypes.numbertype(typeof(v)) === Bool end diff --git a/test/07_levels.jl b/test/07_levels.jl index b3149fbb..7704d99a 100644 --- a/test/07_levels.jl +++ b/test/07_levels.jl @@ -9,7 +9,7 @@ using CategoricalArrays: DefaultRefType, levels!, hashlevels @test isa(levels(pool), Vector{Int}) @test length(pool) === 3 @test levels(pool) == [2, 1, 3] - @test all([levels(CategoricalValue(i, pool)) for i in 1:3] .=== Ref(levels(pool))) + @test all([levels(CategoricalValue(pool, i)) for i in 1:3] .=== Ref(levels(pool))) @test pool.invindex == Dict(2=>1, 1=>2, 3=>3) @test pool.hash === nothing @test pool.equalto == C_NULL @@ -26,7 +26,7 @@ using CategoricalArrays: DefaultRefType, levels!, hashlevels @test pool.equalto == C_NULL @test pool.subsetof == C_NULL @test get(pool, 4) === DefaultRefType(4) - @test pool[4] === CategoricalValue(4, pool) + @test pool[4] === CategoricalValue(pool, 4) end for rep in 1:3 @@ -40,7 +40,7 @@ using CategoricalArrays: DefaultRefType, levels!, hashlevels @test pool.equalto == C_NULL @test pool.subsetof == C_NULL @test get(pool, 0) === DefaultRefType(5) - @test pool[5] === CategoricalValue(5, pool) + @test pool[5] === CategoricalValue(pool, 5) end for rep in 1:3 @@ -55,8 +55,8 @@ using CategoricalArrays: DefaultRefType, levels!, hashlevels @test pool.subsetof == C_NULL @test get(pool, 10) === DefaultRefType(6) @test get(pool, 11) === DefaultRefType(7) - @test pool[6] === CategoricalValue(6, pool) - @test pool[7] === CategoricalValue(7, pool) + @test pool[6] === CategoricalValue(pool, 6) + @test pool[7] === CategoricalValue(pool, 7) end for rep in 1:3 @@ -71,8 +71,8 @@ using CategoricalArrays: DefaultRefType, levels!, hashlevels @test pool.subsetof == C_NULL @test get(pool, 12) === DefaultRefType(8) @test get(pool, 13) === DefaultRefType(9) - @test pool[8] === CategoricalValue(8, pool) - @test pool[9] === CategoricalValue(9, pool) + @test pool[8] === CategoricalValue(pool, 8) + @test pool[9] === CategoricalValue(pool, 9) end # Removing levels @@ -100,8 +100,8 @@ using CategoricalArrays: DefaultRefType, levels!, hashlevels @test pool.subsetof == C_NULL @test get(pool, 15) === DefaultRefType(10) @test get(pool, 14) === DefaultRefType(11) - @test pool[10] === CategoricalValue(10, pool) - @test pool[11] === CategoricalValue(11, pool) + @test pool[10] === CategoricalValue(pool, 10) + @test pool[11] === CategoricalValue(pool, 11) # get! ordered!(pool, true) @@ -121,11 +121,11 @@ using CategoricalArrays: DefaultRefType, levels!, hashlevels @test get(pool, 20) === DefaultRefType(12) # get! with CategoricalValue adding new levels in conflicting order - v = CategoricalValue(2, CategoricalPool([100, 99, 4, 2])) + v = CategoricalValue(CategoricalPool([100, 99, 4, 2]), 2) @test_throws ArgumentError get!(pool, v) # get! with CategoricalValue adding new levels in compatible order - v = CategoricalValue(4, CategoricalPool([2, 4, 100, 99])) + v = CategoricalValue(CategoricalPool([2, 4, 100, 99]), 4) ordered!(pool, true) @test_throws OrderedLevelsException get!(pool, v) @@ -145,7 +145,7 @@ using CategoricalArrays: DefaultRefType, levels!, hashlevels @test get(pool, 99) === DefaultRefType(14) # get! with CategoricalValue not adding new levels - v = CategoricalValue(1, CategoricalPool([100, 2])) + v = CategoricalValue(CategoricalPool([100, 2]), 1) @test get!(pool, v) === DefaultRefType(13) @test isa(pool.levels, Vector{Int}) @@ -170,7 +170,7 @@ using CategoricalArrays: DefaultRefType, levels!, hashlevels @test pool.subsetof == C_NULL # get! with CategoricalValue conversion error - v = CategoricalValue(1, CategoricalPool(["a", "b"])) + v = CategoricalValue(CategoricalPool(["a", "b"]), 1) @test_throws MethodError get!(pool, v) # get! with ordered CategoricalValue marks unordered empty pool as ordered diff --git a/test/08_equality.jl b/test/08_equality.jl index 523e1a20..7abf9e58 100644 --- a/test/08_equality.jl +++ b/test/08_equality.jl @@ -113,10 +113,10 @@ end @test (pool2 == opool2) === true @test (pool1 == opool2) === false - nv1a = CategoricalValue(1, pool1) - nv2a = CategoricalValue(1, pool2) - nv1b = CategoricalValue(2, pool1) - nv2b = CategoricalValue(2, pool2) + nv1a = CategoricalValue(pool1, 1) + nv2a = CategoricalValue(pool2, 1) + nv1b = CategoricalValue(pool1, 2) + nv2b = CategoricalValue(pool2, 2) @test isequal(nv1a, nv1a) == true @test isequal(nv1a, nv2a) == false @@ -148,10 +148,10 @@ end @test isequal(nv1b, 2) == true @test isequal(nv2b, 2) == false - ov1a = CategoricalValue(1, opool1) - ov2a = CategoricalValue(1, opool2) - ov1b = CategoricalValue(2, opool1) - ov2b = CategoricalValue(2, opool2) + ov1a = CategoricalValue(opool1, 1) + ov2a = CategoricalValue(opool2, 1) + ov1b = CategoricalValue(opool1, 2) + ov2b = CategoricalValue(opool2, 2) @test isequal(ov1a, ov1a) == true @test isequal(ov1a, ov2a) == false @@ -240,7 +240,7 @@ end @testset "in()" begin pool = CategoricalPool([5, 1, 3]) - nv = CategoricalValue(2, pool) + nv = CategoricalValue(pool, 2) @test (nv in 1:3) === true @test (nv in [1, 2, 3]) === true diff --git a/test/09_hash.jl b/test/09_hash.jl index 4bb6367d..3ad38a04 100644 --- a/test/09_hash.jl +++ b/test/09_hash.jl @@ -17,10 +17,10 @@ using CategoricalArrays @test (hash(opool1) == hash(opool2)) === false @test (hash(opool2) == hash(opool2)) === true - nv1a = CategoricalValue(1, pool1) - nv2a = CategoricalValue(1, pool2) - nv1b = CategoricalValue(2, pool1) - nv2b = CategoricalValue(2, pool2) + nv1a = CategoricalValue(pool1, 1) + nv2a = CategoricalValue(pool2, 1) + nv1b = CategoricalValue(pool1, 2) + nv2b = CategoricalValue(pool2, 2) @test (hash(nv1a) == hash(nv1a)) === true @test (hash(nv1a) == hash(nv2a)) === false @@ -42,10 +42,10 @@ using CategoricalArrays @test (hash(nv2b) == hash(nv1b)) === false @test (hash(nv2b) == hash(nv2b)) === true - ov1a = CategoricalValue(1, opool1) - ov2a = CategoricalValue(1, opool2) - ov1b = CategoricalValue(2, opool1) - ov2b = CategoricalValue(2, opool2) + ov1a = CategoricalValue(opool1, 1) + ov2a = CategoricalValue(opool2, 1) + ov1b = CategoricalValue(opool1, 2) + ov2b = CategoricalValue(opool2, 2) @test (hash(ov1a) == hash(ov1a)) === true @test (hash(ov1a) == hash(ov2a)) === false diff --git a/test/10_isless.jl b/test/10_isless.jl index 4e08dfaa..5c247cef 100644 --- a/test/10_isless.jl +++ b/test/10_isless.jl @@ -4,9 +4,9 @@ using CategoricalArrays pool = CategoricalPool([1, 2, 3]) -v1 = CategoricalValue(1, pool) -v2 = CategoricalValue(2, pool) -v3 = CategoricalValue(3, pool) +v1 = CategoricalValue(pool, 1) +v2 = CategoricalValue(pool, 2) +v3 = CategoricalValue(pool, 3) @testset "values from unordered CategoricalPool" begin @test isordered(v1) === false @@ -64,12 +64,12 @@ v3 = CategoricalValue(3, pool) @test isless(v3, v3) === false @testset "comparison with values of different types" begin - @test isless(v1, 1) === false - @test isless(v1, 2) === true - @test_throws KeyError isless(v1, 10) - @test_throws KeyError isless(v1, "a") - @test isless(1, v1) === false - @test_throws KeyError isless("a", v1) + @test_throws ArgumentError isless(v1, 1) + @test_throws ArgumentError isless(v1, 2) + @test_throws ArgumentError isless(v1, 10) + @test_throws ArgumentError isless(v1, "a") + @test_throws ArgumentError isless(1, v1) + @test_throws ArgumentError isless("a", v1) @test_throws ArgumentError v1 < 1 @test_throws ArgumentError v1 < 10 @test_throws ArgumentError v1 < 2 @@ -157,32 +157,32 @@ end @test isless(v3, v3) === false @testset "comparison with values of different types" begin - @test isless(v1, 1) === false - @test isless(v1, 2) === true - @test_throws KeyError isless(v1, 10) - @test_throws KeyError isless(v1, "a") - @test isless(1, v1) === false - @test_throws KeyError isless("a", v1) - @test (v1 < 1) === false - @test (v1 < 2) === true - @test_throws KeyError v1 < 10 - @test_throws KeyError v1 < "a" - @test (v1 <= 1) === true - @test (v1 <= 2) === true - @test_throws KeyError v1 <= "a" - @test (v1 > 1) === false - @test (v1 > 2) === false - @test_throws KeyError v1 > "a" - @test (v1 >= 1) === true - @test (v1 >= 2) === false - @test_throws KeyError v1 >= "a" + @test_throws ArgumentError isless(v1, 1) + @test_throws ArgumentError isless(v1, 2) + @test_throws ArgumentError isless(v1, 10) + @test_throws ArgumentError isless(v1, "a") + @test_throws ArgumentError isless(1, v1) + @test_throws ArgumentError isless("a", v1) + @test_throws ArgumentError (v1 < 1) + @test_throws ArgumentError (v1 < 2) + @test_throws ArgumentError v1 < 10 + @test_throws ArgumentError v1 < "a" + @test_throws ArgumentError (v1 <= 1) + @test_throws ArgumentError (v1 <= 2) + @test_throws ArgumentError v1 <= "a" + @test_throws ArgumentError (v1 > 1) + @test_throws ArgumentError (v1 > 2) + @test_throws ArgumentError v1 > "a" + @test_throws ArgumentError (v1 >= 1) + @test_throws ArgumentError (v1 >= 2) + @test_throws ArgumentError v1 >= "a" end @testset "comparison with values from different pools" begin poolb = copy(pool) - v1b = CategoricalValue(1, poolb) - v2b = CategoricalValue(2, poolb) - v3b = CategoricalValue(3, poolb) + v1b = CategoricalValue(poolb, 1) + v2b = CategoricalValue(poolb, 2) + v3b = CategoricalValue(poolb, 3) @test (v1 < v1b) === false @test (v1 < v2b) === true @@ -206,7 +206,7 @@ end poolc = copy(poolb) @test poolb == poolc # To set subsetof field - v1c = CategoricalValue(1, poolc) + v1c = CategoricalValue(poolc, 1) push!(poolc, 4) @test_throws ArgumentError v1b < v1c @@ -214,7 +214,7 @@ end poolc = copy(poolb) @test poolb == poolc # To set subsetof field - v1c = CategoricalValue(1, poolc) + v1c = CategoricalValue(poolc, 1) push!(poolc, 4) @test_throws ArgumentError v1b < v1c @@ -222,7 +222,7 @@ end poolc = copy(poolb) @test poolb == poolc # To set subsetof field - v1c = CategoricalValue(1, poolc) + v1c = CategoricalValue(poolc, 1) levels!(poolc, collect(1:4)) @test_throws ArgumentError v1b < v1c diff --git a/test/11_array.jl b/test/11_array.jl index 71026d63..570ca3be 100644 --- a/test/11_array.jl +++ b/test/11_array.jl @@ -124,9 +124,9 @@ using CategoricalArrays: DefaultRefType, leveltype @test_throws Exception x[1] > x[2] @test_throws Exception x[3] > x[2] - @test x[1] === CategoricalValue(2, x.pool) - @test x[2] === CategoricalValue(1, x.pool) - @test x[3] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) + @test x[2] === CategoricalValue(x.pool, 1) + @test x[3] === CategoricalValue(x.pool, 2) @test_throws BoundsError x[4] x2 = x[:] @@ -159,33 +159,33 @@ using CategoricalArrays: DefaultRefType, leveltype @test isordered(x2) == isordered(x) x[1] = x[2] - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(1, x.pool) - @test x[3] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 1) + @test x[3] === CategoricalValue(x.pool, 2) x[3] = "c" @test levels(x) == ["a", "b", "c"] - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(1, x.pool) - @test x[3] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 1) + @test x[3] === CategoricalValue(x.pool, 3) x[2:3] .= "b" @test levels(x) == ["a", "b", "c"] - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 2) @test droplevels!(x) === x @test levels(x) == ["a", "b"] - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 2) @test levels!(x, ["b", "a"]) === x @test levels(x) == ["b", "a"] - @test x[1] === CategoricalValue(2, x.pool) - @test x[2] === CategoricalValue(1, x.pool) - @test x[3] === CategoricalValue(1, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) + @test x[2] === CategoricalValue(x.pool, 1) + @test x[3] === CategoricalValue(x.pool, 1) @test_throws ArgumentError levels!(x, ["a"]) @test_throws ArgumentError levels!(x, ["e", "b"]) @@ -193,14 +193,14 @@ using CategoricalArrays: DefaultRefType, leveltype @test levels!(x, ["e", "a", "b"]) === x @test levels(x) == ["e", "a", "b"] - @test x[1] === CategoricalValue(2, x.pool) - @test x[2] === CategoricalValue(3, x.pool) - @test x[3] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) + @test x[2] === CategoricalValue(x.pool, 3) + @test x[3] === CategoricalValue(x.pool, 3) x[1] = "c" - @test x[1] === CategoricalValue(4, x.pool) - @test x[2] === CategoricalValue(3, x.pool) - @test x[3] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 4) + @test x[2] === CategoricalValue(x.pool, 3) + @test x[3] === CategoricalValue(x.pool, 3) @test levels(x) == ["e", "a", "b", "c"] push!(x, "a") @@ -361,10 +361,10 @@ using CategoricalArrays: DefaultRefType, leveltype @test isordered(x2) === isordered(x) @test levels(x2) == levels(x) - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(3, x.pool) - @test x[4] === CategoricalValue(4, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 3) + @test x[4] === CategoricalValue(x.pool, 4) @test_throws BoundsError x[5] x2 = x[:] @@ -396,10 +396,10 @@ using CategoricalArrays: DefaultRefType, leveltype @test isordered(x2) == isordered(x) x[2] = 1 - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(3, x.pool) - @test x[3] === CategoricalValue(3, x.pool) - @test x[4] === CategoricalValue(4, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 3) + @test x[3] === CategoricalValue(x.pool, 3) + @test x[4] === CategoricalValue(x.pool, 4) @test levels(x) == unique(a) @test unique(x) == unique(collect(x)) @@ -408,10 +408,10 @@ using CategoricalArrays: DefaultRefType, leveltype levels!(x, [levels(x); -1]) end x[1:2] .= -1 - @test x[1] === CategoricalValue(5, x.pool) - @test x[2] === CategoricalValue(5, x.pool) - @test x[3] === CategoricalValue(3, x.pool) - @test x[4] === CategoricalValue(4, x.pool) + @test x[1] === CategoricalValue(x.pool, 5) + @test x[2] === CategoricalValue(x.pool, 5) + @test x[3] === CategoricalValue(x.pool, 3) + @test x[4] === CategoricalValue(x.pool, 4) @test levels(x) == vcat(unique(a), -1) @test unique(x) == unique(collect(x)) @@ -536,20 +536,20 @@ using CategoricalArrays: DefaultRefType, leveltype @test isordered(x2) === isordered(x) @test levels(x2) == levels(x) - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(2, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(3, x.pool) - @test x[6] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 2) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 3) + @test x[6] === CategoricalValue(x.pool, 3) @test_throws BoundsError x[7] - @test x[1,1] === CategoricalValue(1, x.pool) - @test x[2,1] === CategoricalValue(2, x.pool) - @test x[1,2] === CategoricalValue(2, x.pool) - @test x[2,2] === CategoricalValue(1, x.pool) - @test x[1,3] === CategoricalValue(3, x.pool) - @test x[2,3] === CategoricalValue(3, x.pool) + @test x[1,1] === CategoricalValue(x.pool, 1) + @test x[2,1] === CategoricalValue(x.pool, 2) + @test x[1,2] === CategoricalValue(x.pool, 2) + @test x[2,2] === CategoricalValue(x.pool, 1) + @test x[1,3] === CategoricalValue(x.pool, 3) + @test x[2,3] === CategoricalValue(x.pool, 3) @test_throws BoundsError x[1,4] @test_throws BoundsError x[4,1] @test_throws BoundsError x[4,4] @@ -591,39 +591,39 @@ using CategoricalArrays: DefaultRefType, leveltype levels!(x, [levels(x); "z"]) end x[1] = "z" - @test x[1] === CategoricalValue(4, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(2, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(3, x.pool) - @test x[6] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 4) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 2) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 3) + @test x[6] === CategoricalValue(x.pool, 3) @test levels(x) == ["a", "b", "c", "z"] x[1,:] .= "a" - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(1, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(1, x.pool) - @test x[6] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 1) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 1) + @test x[6] === CategoricalValue(x.pool, 3) @test levels(x) == ["a", "b", "c", "z"] x[1,1:2] .= "z" - @test x[1] === CategoricalValue(4, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(4, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(1, x.pool) - @test x[6] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 4) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 4) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 1) + @test x[6] === CategoricalValue(x.pool, 3) @test levels(x) == ["a", "b", "c", "z"] x[1,2] = "b" - @test x[1] === CategoricalValue(4, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(2, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(1, x.pool) - @test x[6] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 4) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 2) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 1) + @test x[6] === CategoricalValue(x.pool, 3) @test levels(x) == ["a", "b", "c", "z"] end @@ -664,7 +664,7 @@ using CategoricalArrays: DefaultRefType, leveltype levels!(x, [levels(x); "c"]) end x[1] = "c" - @test x[1] === CategoricalValue(1, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) @test !isassigned(x, 2) && isdefined(x, 2) @test_throws UndefRefError x[2] @test levels(x) == ["c"] @@ -674,15 +674,15 @@ using CategoricalArrays: DefaultRefType, leveltype levels!(x, [levels(x); "a"]) end x[1] = "a" - @test x[1] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) @test !isassigned(x, 2) && isdefined(x, 2) @test_throws UndefRefError x[2] @test isordered(x) === ordered @test levels(x) == ["c", "a"] x[2] = "c" - @test x[1] === CategoricalValue(2, x.pool) - @test x[2] === CategoricalValue(1, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) + @test x[2] === CategoricalValue(x.pool, 1) @test levels(x) == ["c", "a"] if ordered @@ -690,18 +690,18 @@ using CategoricalArrays: DefaultRefType, leveltype levels!(x, [levels(x); "b"]) end x[1] = "b" - @test x[1] === CategoricalValue(3, x.pool) - @test x[2] === CategoricalValue(1, x.pool) + @test x[1] === CategoricalValue(x.pool, 3) + @test x[2] === CategoricalValue(x.pool, 1) @test levels(x) == ["c", "a", "b"] - v = CategoricalValue(2, CategoricalPool(["xyz", "b"])) + v = CategoricalValue(CategoricalPool(["xyz", "b"]), 2) if ordered @test_throws OrderedLevelsException x[1] = v levels!(x, ["c", "a", "xyz", "b"]) end x[1] = v - @test x[1] === CategoricalValue(4, x.pool) - @test x[2] === CategoricalValue(1, x.pool) + @test x[1] === CategoricalValue(x.pool, 4) + @test x[2] === CategoricalValue(x.pool, 1) @test levels(x) == ["c", "a", "xyz", "b"] end end diff --git a/test/12_missingarray.jl b/test/12_missingarray.jl index 74d78183..551049e4 100644 --- a/test/12_missingarray.jl +++ b/test/12_missingarray.jl @@ -134,9 +134,9 @@ const ≅ = isequal @test_throws Exception x[1] > x[2] @test_throws Exception x[3] > x[2] - @test x[1] === CategoricalValue(2, x.pool) - @test x[2] === CategoricalValue(1, x.pool) - @test x[3] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) + @test x[2] === CategoricalValue(x.pool, 1) + @test x[3] === CategoricalValue(x.pool, 2) @test_throws BoundsError x[4] x2 = x[:] @@ -169,34 +169,34 @@ const ≅ = isequal @test isordered(x2) == isordered(x) x[1] = x[2] - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(1, x.pool) - @test x[3] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 1) + @test x[3] === CategoricalValue(x.pool, 2) x[3] = "c" - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(1, x.pool) - @test x[3] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 1) + @test x[3] === CategoricalValue(x.pool, 3) @test levels(x) == ["a", "b", "c"] x[2:3] .= "b" - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 2) @test levels(x) == ["a", "b", "c"] @test droplevels!(x) === x @test levels(x) == ["a", "b"] - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 2) @test levels(x) == ["a", "b"] @test levels!(x, ["b", "a"]) === x @test levels(x) == ["b", "a"] - @test x[1] === CategoricalValue(2, x.pool) - @test x[2] === CategoricalValue(1, x.pool) - @test x[3] === CategoricalValue(1, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) + @test x[2] === CategoricalValue(x.pool, 1) + @test x[3] === CategoricalValue(x.pool, 1) @test levels(x) == ["b", "a"] @test_throws ArgumentError levels!(x, ["a"]) @@ -205,21 +205,21 @@ const ≅ = isequal @test levels!(x, ["e", "a", "b"]) === x @test levels(x) == ["e", "a", "b"] - @test x[1] === CategoricalValue(2, x.pool) - @test x[2] === CategoricalValue(3, x.pool) - @test x[3] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) + @test x[2] === CategoricalValue(x.pool, 3) + @test x[3] === CategoricalValue(x.pool, 3) @test levels(x) == ["e", "a", "b"] x[1] = "c" - @test x[1] === CategoricalValue(4, x.pool) - @test x[2] === CategoricalValue(3, x.pool) - @test x[3] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 4) + @test x[2] === CategoricalValue(x.pool, 3) + @test x[3] === CategoricalValue(x.pool, 3) @test levels(x) == ["e", "a", "b", "c"] @test_throws ArgumentError levels!(x, ["e", "c"]) @test levels!(x, ["e", "c"], allowmissing=true) === x @test levels(x) == ["e", "c"] - @test x[1] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) @test x[2] === missing @test x[3] === missing @test levels(x) == ["e", "c"] @@ -334,8 +334,8 @@ const ≅ = isequal @test typeof(x2) === typeof(x) @test levels(x2) == levels(x) - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) @test x[3] === missing @test_throws BoundsError x[4] @@ -369,8 +369,8 @@ const ≅ = isequal @test isordered(x2) == isordered(x) x[1] = "b" - @test x[1] === CategoricalValue(2, x.pool) - @test x[2] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) + @test x[2] === CategoricalValue(x.pool, 2) @test x[3] === missing if ordered @@ -378,15 +378,15 @@ const ≅ = isequal levels!(x, [levels(x); "c"]) end x[3] = "c" - @test x[1] === CategoricalValue(2, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 3) @test levels(x) == ["a", "b", "c"] x[1] = missing @test x[1] === missing - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(3, x.pool) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 3) @test levels(x) == ["a", "b", "c"] x[2:3] .= missing @@ -539,10 +539,10 @@ const ≅ = isequal @test typeof(x2) === typeof(x) @test levels(x2) == levels(x) - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(3, x.pool) - @test x[4] === CategoricalValue(4, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 3) + @test x[4] === CategoricalValue(x.pool, 4) @test_throws BoundsError x[5] x2 = x[:] @@ -575,10 +575,10 @@ const ≅ = isequal @test isordered(x2) == isordered(x) x[2] = 1 - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(3, x.pool) - @test x[3] === CategoricalValue(3, x.pool) - @test x[4] === CategoricalValue(4, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 3) + @test x[3] === CategoricalValue(x.pool, 3) + @test x[4] === CategoricalValue(x.pool, 4) @test levels(x) == unique(a) @test unique(x) == unique(collect(x)) @@ -587,10 +587,10 @@ const ≅ = isequal levels!(x, [levels(x); -1]) end x[1:2] .= -1 - @test x[1] === CategoricalValue(5, x.pool) - @test x[2] === CategoricalValue(5, x.pool) - @test x[3] === CategoricalValue(3, x.pool) - @test x[4] === CategoricalValue(4, x.pool) + @test x[1] === CategoricalValue(x.pool, 5) + @test x[2] === CategoricalValue(x.pool, 5) + @test x[3] === CategoricalValue(x.pool, 3) + @test x[4] === CategoricalValue(x.pool, 4) @test levels(x) == vcat(unique(a), -1) @test unique(x) == unique(collect(x)) @@ -725,20 +725,20 @@ const ≅ = isequal @test isordered(x2) === isordered(x) @test levels(x2) == levels(x) - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(2, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(3, x.pool) - @test x[6] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 2) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 3) + @test x[6] === CategoricalValue(x.pool, 3) @test_throws BoundsError x[7] - @test x[1,1] === CategoricalValue(1, x.pool) - @test x[2,1] === CategoricalValue(2, x.pool) - @test x[1,2] === CategoricalValue(2, x.pool) - @test x[2,2] === CategoricalValue(1, x.pool) - @test x[1,3] === CategoricalValue(3, x.pool) - @test x[2,3] === CategoricalValue(3, x.pool) + @test x[1,1] === CategoricalValue(x.pool, 1) + @test x[2,1] === CategoricalValue(x.pool, 2) + @test x[1,2] === CategoricalValue(x.pool, 2) + @test x[2,2] === CategoricalValue(x.pool, 1) + @test x[1,3] === CategoricalValue(x.pool, 3) + @test x[2,3] === CategoricalValue(x.pool, 3) @test_throws BoundsError x[1,4] @test_throws BoundsError x[4,1] @test_throws BoundsError x[4,4] @@ -753,30 +753,30 @@ const ≅ = isequal levels!(x, [levels(x); "z"]) end x[1] = "z" - @test x[1] === CategoricalValue(4, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(2, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(3, x.pool) - @test x[6] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 4) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 2) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 3) + @test x[6] === CategoricalValue(x.pool, 3) @test levels(x) == ["a", "b", "c", "z"] x[1,:] .= "a" - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(1, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(1, x.pool) - @test x[6] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 1) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 1) + @test x[6] === CategoricalValue(x.pool, 3) @test levels(x) == ["a", "b", "c", "z"] x[1,1:2] .= "z" - @test x[1] === CategoricalValue(4, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(4, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(1, x.pool) - @test x[6] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 4) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 4) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 1) + @test x[6] === CategoricalValue(x.pool, 3) @test levels(x) == ["a", "b", "c", "z"] end @@ -858,19 +858,19 @@ const ≅ = isequal @test isordered(x2) === isordered(x) @test levels(x2) == levels(x) - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) @test x[3] === missing - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(3, x.pool) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 3) @test x[6] === missing @test_throws BoundsError x[7] - @test x[1,1] === CategoricalValue(1, x.pool) - @test x[2,1] === CategoricalValue(2, x.pool) + @test x[1,1] === CategoricalValue(x.pool, 1) + @test x[2,1] === CategoricalValue(x.pool, 2) @test x[1,2] === missing - @test x[2,2] === CategoricalValue(1, x.pool) - @test x[1,3] === CategoricalValue(3, x.pool) + @test x[2,2] === CategoricalValue(x.pool, 1) + @test x[1,3] === CategoricalValue(x.pool, 3) @test x[2,3] === missing @test_throws BoundsError x[1,4] @test_throws BoundsError x[4,1] @@ -913,74 +913,74 @@ const ≅ = isequal levels!(x, [levels(x); "z"]) end x[1] = "z" - @test x[1] === CategoricalValue(4, x.pool) - @test x[2] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 4) + @test x[2] === CategoricalValue(x.pool, 2) @test x[3] === missing - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(3, x.pool) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 3) @test x[6] === missing @test levels(x) == ["a", "b", "c", "z"] x[1,:] .= "a" - @test x[1] === CategoricalValue(1, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(1, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(1, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 1) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 1) @test x[6] === missing @test levels(x) == ["a", "b", "c", "z"] x[1,1:2] .= "z" - @test x[1] === CategoricalValue(4, x.pool) - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(4, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(1, x.pool) + @test x[1] === CategoricalValue(x.pool, 4) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 4) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 1) @test x[6] === missing @test levels(x) == ["a", "b", "c", "z"] x[1] = missing @test x[1] === missing - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(4, x.pool) - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(1, x.pool) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 4) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 1) @test x[6] === missing @test levels(x) == ["a", "b", "c", "z"] x[1,1:2] .= missing @test x[1] === missing - @test x[2] === CategoricalValue(2, x.pool) + @test x[2] === CategoricalValue(x.pool, 2) @test x[3] === missing - @test x[4] === CategoricalValue(1, x.pool) - @test x[5] === CategoricalValue(1, x.pool) + @test x[4] === CategoricalValue(x.pool, 1) + @test x[5] === CategoricalValue(x.pool, 1) @test x[6] === missing @test levels(x) == ["a", "b", "c", "z"] x[:,2] .= missing @test x[1] === missing - @test x[2] === CategoricalValue(2, x.pool) + @test x[2] === CategoricalValue(x.pool, 2) @test x[3] === missing @test x[4] === missing - @test x[5] === CategoricalValue(1, x.pool) + @test x[5] === CategoricalValue(x.pool, 1) @test x[6] === missing @test levels(x) == ["a", "b", "c", "z"] x[1,2] = "a" @test x[1] === missing - @test x[2] === CategoricalValue(2, x.pool) - @test x[3] === CategoricalValue(1, x.pool) + @test x[2] === CategoricalValue(x.pool, 2) + @test x[3] === CategoricalValue(x.pool, 1) @test x[4] === missing - @test x[5] === CategoricalValue(1, x.pool) + @test x[5] === CategoricalValue(x.pool, 1) @test x[6] === missing @test levels(x) == ["a", "b", "c", "z"] x[2,1] = missing @test x[1] === missing @test x[2] === missing - @test x[3] === CategoricalValue(1, x.pool) + @test x[3] === CategoricalValue(x.pool, 1) @test x[4] === missing - @test x[5] === CategoricalValue(1, x.pool) + @test x[5] === CategoricalValue(x.pool, 1) @test x[6] === missing @test levels(x) == ["a", "b", "c", "z"] end @@ -1020,7 +1020,7 @@ const ≅ = isequal levels!(x, [levels(x); "c"]) end x[1] = "c" - @test x[1] === CategoricalValue(1, x.pool) + @test x[1] === CategoricalValue(x.pool, 1) @test ismissing(x[2]) @test levels(x) == ["c"] @@ -1029,12 +1029,12 @@ const ≅ = isequal levels!(x, [levels(x); "a"]) end x[1] = "a" - @test x[1] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) @test ismissing(x[2]) @test levels(x) == ["c", "a"] x[2] = missing - @test x[1] === CategoricalValue(2, x.pool) + @test x[1] === CategoricalValue(x.pool, 2) @test x[2] === missing @test levels(x) == ["c", "a"] @@ -1043,7 +1043,7 @@ const ≅ = isequal levels!(x, [levels(x); "b"]) end x[1] = "b" - @test x[1] === CategoricalValue(3, x.pool) + @test x[1] === CategoricalValue(x.pool, 3) @test x[2] === missing @test levels(x) == ["c", "a", "b"] end