@@ -239,7 +239,7 @@ function CategoricalArray{T, N, R}(A::CategoricalArray{S, N, Q};
239
239
catch err
240
240
err isa LevelsException || rethrow (err)
241
241
throw (ArgumentError (" encountered value(s) not in specified `levels`: " *
242
- " $(setdiff (CategoricalArrays . levels (res), levels)) " ))
242
+ " $(setdiff (_levels (res), levels)) " ))
243
243
end
244
244
end
245
245
return res
@@ -358,18 +358,18 @@ function _convert(::Type{CategoricalArray{T, N, R}}, A::AbstractArray{S, N};
358
358
copyto! (res, A)
359
359
360
360
if levels != = nothing
361
- CategoricalArrays . levels (res) == levels ||
361
+ _levels (res) == levels ||
362
362
throw (ArgumentError (" encountered value(s) not in specified `levels`: " *
363
- " $(setdiff (CategoricalArrays . levels (res), levels)) " ))
363
+ " $(setdiff (_levels (res), levels)) " ))
364
364
else
365
365
# if order is defined for level type, automatically apply it
366
366
L = leveltype (res)
367
367
if Base. OrderStyle (L) isa Base. Ordered
368
- levels! (res, sort (CategoricalArrays . levels (res)))
368
+ levels! (res, sort (_levels (res)))
369
369
elseif hasmethod (isless, (L, L))
370
370
# isless may throw an error, e.g. for AbstractArray{T} of unordered T
371
371
try
372
- levels! (res, sort (CategoricalArrays . levels (res)))
372
+ levels! (res, sort (_levels (res)))
373
373
catch e
374
374
e isa MethodError || rethrow (e)
375
375
end
382
382
# From CategoricalArray (preserve levels, ordering and R)
383
383
function convert (:: Type{CategoricalArray{T, N, R}} , A:: CategoricalArray{S, N} ) where {S, T, N, R}
384
384
if length (A. pool) > typemax (R)
385
- throw (LevelsException {T, R} (levels (A)[typemax (R)+ 1 : end ]))
385
+ throw (LevelsException {T, R} (_levels (A)[typemax (R)+ 1 : end ]))
386
386
end
387
387
388
388
if ! (T >: Missing ) && S >: Missing && any (iszero, A. refs)
@@ -460,7 +460,7 @@ size(A::CategoricalArray) = size(A.refs)
460
460
Base. IndexStyle (:: Type{<:CategoricalArray} ) = IndexLinear ()
461
461
462
462
function update_refs! (A:: CategoricalArray , newlevels:: AbstractVector )
463
- oldlevels = levels (A)
463
+ oldlevels = _levels (A)
464
464
levelsmap = similar (A. refs, length (oldlevels)+ 1 )
465
465
# 0 maps to a missing value
466
466
levelsmap[1 ] = 0
@@ -478,7 +478,7 @@ function merge_pools!(A::CatArrOrSub,
478
478
updaterefs:: Bool = true ,
479
479
updatepool:: Bool = true )
480
480
newlevels, ordered = merge_pools (pool (A), pool (B))
481
- oldlevels = levels (A)
481
+ oldlevels = _levels (A)
482
482
pA = A isa SubArray ? parent (A) : A
483
483
ordered! (pA, ordered)
484
484
# If A's levels are an ordered superset of new (merged) pool, no need to recompute refs
@@ -537,8 +537,8 @@ function copyto!(dest::CatArrOrSub{T, N, R}, dstart::Integer,
537
537
538
538
# try converting src to dest type to avoid partial copy corruption of dest
539
539
# in the event that the src cannot be copied into dest
540
- slevs = convert (Vector{T}, levels (src))
541
- dlevs = levels (dest)
540
+ slevs = convert (Vector{T}, _levels (src))
541
+ dlevs = _levels (dest)
542
542
if eltype (src) >: Missing && ! (eltype (dest) >: Missing ) && ! all (x -> x > 0 , srefs)
543
543
throw (MissingException (" cannot copy array with missing values to an array with element type $T " ))
544
544
end
@@ -591,7 +591,7 @@ function copyto!(dest::CatArrOrSub{T1, N, R}, dstart::Integer,
591
591
return invoke (copyto!, Tuple{AbstractArray, Integer, AbstractArray, Integer, Integer},
592
592
dest, dstart, src, sstart, n)
593
593
end
594
- newdestlevs = destlevs = copy (levels (dest)) # copy since we need original levels below
594
+ newdestlevs = destlevs = copy (_levels (dest)) # copy since we need original levels below
595
595
srclevsnm = T2 >: Missing ? setdiff (srclevs, [missing ]) : srclevs
596
596
if ! (srclevsnm ⊆ destlevs)
597
597
# if order is defined for level type, automatically apply it
@@ -701,7 +701,7 @@ While this will reduce memory use, this function is type-unstable, which can aff
701
701
performance inside the function where the call is made. Therefore, use it with caution.
702
702
"""
703
703
function compress (A:: CategoricalArray{T, N} ) where {T, N}
704
- R = reftype (length (levels (A. pool)))
704
+ R = reftype (length (_levels (A. pool)))
705
705
convert (CategoricalArray{T, N, R}, A)
706
706
end
707
707
@@ -719,11 +719,11 @@ decompress(A::CategoricalArray{T, N}) where {T, N} =
719
719
convert (CategoricalArray{T, N, DefaultRefType}, A)
720
720
721
721
function vcat (A:: CategoricalArray... )
722
- ordered = any (isordered, A) && all (a-> isordered (a) || isempty (levels (a)), A)
723
- newlevels, ordered = mergelevels (ordered, map (levels , A)... )
722
+ ordered = any (isordered, A) && all (a-> isordered (a) || isempty (_levels (a)), A)
723
+ newlevels, ordered = mergelevels (ordered, map (_levels , A)... )
724
724
725
725
refsvec = map (A) do a
726
- ii = convert (Vector{Int}, indexin (levels (a. pool), newlevels))
726
+ ii = convert (Vector{Int}, indexin (_levels (a. pool), newlevels))
727
727
[x== 0 ? 0 : ii[x] for x in a. refs]:: Array{Int,ndims(a)}
728
728
end
729
729
@@ -761,23 +761,25 @@ This may include levels which do not actually appear in the data
761
761
`missing` will be included only if it appears in the data and
762
762
`skipmissing=false` is passed.
763
763
764
- The returned vector is an internal field of `x` which must not be mutated
764
+ The returned vector is owned by `x` and must not be mutated
765
765
as doing so would corrupt it.
766
766
"""
767
- @inline function DataAPI. levels (A:: CatArrOrSub{T} ; skipmissing:: Bool = true ) where T
767
+ @inline function DataAPI. levels (A:: CatArrOrSub ; skipmissing:: Bool = true )
768
768
if eltype (A) >: Missing && ! skipmissing
769
769
if any (== (0 ), refs (A))
770
- T [levels (pool (A)); missing ]
770
+ eltype (A) [levels (pool (A)); missing ]
771
771
else
772
- convert (Vector{T}, levels ( pool (A) ))
772
+ levels_missing ( pool (A))
773
773
end
774
774
else
775
775
levels (pool (A))
776
776
end
777
777
end
778
778
779
+ _levels (A:: CatArrOrSub ) = _levels (pool (A))
780
+
779
781
"""
780
- levels!(A::CategoricalArray, newlevels::Vector ; allowmissing::Bool=false)
782
+ levels!(A::CategoricalArray, newlevels::AbstractVector ; allowmissing::Bool=false)
781
783
782
784
Set the levels categorical array `A`. The order of appearance of levels will be respected
783
785
by [`levels`](@ref DataAPI.levels), which may affect display of results in some operations; if `A` is
@@ -791,7 +793,7 @@ Else, `newlevels` must include all levels which appear in the data.
791
793
"""
792
794
function levels! (A:: CategoricalArray{T, N, R} , newlevels:: AbstractVector ;
793
795
allowmissing:: Bool = false ) where {T, N, R}
794
- (levels (A) == newlevels) && return A # nothing to do
796
+ (_levels (A) == newlevels) && return A # nothing to do
795
797
796
798
# map each new level to its ref code
797
799
newlv2ref = Dict {eltype(newlevels), Int} ()
@@ -806,7 +808,7 @@ function levels!(A::CategoricalArray{T, N, R}, newlevels::AbstractVector;
806
808
end
807
809
808
810
# map each old ref code to new ref code (or 0 if no such level)
809
- oldlevels = levels (pool (A))
811
+ oldlevels = _levels (pool (A))
810
812
oldref2newref = fill (0 , length (oldlevels) + 1 )
811
813
for (i, lv) in enumerate (oldlevels)
812
814
oldref2newref[i + 1 ] = get (newlv2ref, lv, 0 )
867
869
function _uniquerefs (A:: CatArrOrSub{T} ) where T
868
870
arefs = refs (A)
869
871
res = similar (arefs, 0 )
870
- nlevels = length (levels (A))
872
+ nlevels = length (_levels (A))
871
873
maxunique = nlevels + (T >: Missing ? 1 : 0 )
872
874
seen = fill (false , nlevels + 1 ) # always +1 for 0 (missing ref)
873
875
@inbounds for ref in arefs
@@ -900,7 +902,7 @@ returned by [`levels`](@ref DataAPI.levels)).
900
902
"""
901
903
function droplevels! (A:: CategoricalArray )
902
904
arefs = refs (A)
903
- nlevels = length (levels (A)) + 1 # +1 for missing
905
+ nlevels = length (_levels (A)) + 1 # +1 for missing
904
906
seen = fill (false , nlevels)
905
907
seen[1 ] = true # assume that missing is always observed to simplify checks
906
908
nseen = 1
@@ -913,7 +915,7 @@ function droplevels!(A::CategoricalArray)
913
915
end
914
916
915
917
# replace the pool
916
- A. pool = typeof (pool (A))(@inbounds (levels (A)[view (seen, 2 : nlevels)]), isordered (A))
918
+ A. pool = typeof (pool (A))(@inbounds (_levels (A)[view (seen, 2 : nlevels)]), isordered (A))
917
919
# recode refs to keep only the seen ones (optimized version of update_refs!())
918
920
seen[1 ] = false # to start levelsmap from 0
919
921
levelsmap = cumsum (seen)
@@ -1030,7 +1032,7 @@ end
1030
1032
ordered= _isordered (A),
1031
1033
compress:: Bool = false ) where {T, N, R}
1032
1034
# @inline is needed so that return type is inferred when compress is not provided
1033
- RefType = compress ? reftype (length (CategoricalArrays . levels (A))) : R
1035
+ RefType = compress ? reftype (length (_levels (A))) : R
1034
1036
CategoricalArray {T, N, RefType} (A, levels= levels, ordered= ordered)
1035
1037
end
1036
1038
@@ -1043,7 +1045,7 @@ function in(x::CategoricalValue, y::CategoricalArray{T, N, R}) where {T, N, R}
1043
1045
if x. pool === y. pool
1044
1046
return refcode (x) in y. refs
1045
1047
else
1046
- ref = get (y. pool, levels (x. pool)[refcode (x)], zero (R))
1048
+ ref = get (y. pool, _levels (x. pool)[refcode (x)], zero (R))
1047
1049
return ref != 0 ? ref in y. refs : false
1048
1050
end
1049
1051
end
0 commit comments