@@ -239,7 +239,7 @@ function CategoricalArray{T, N, R}(A::CategoricalArray{S, N, Q};
239239 catch err
240240 err isa LevelsException || rethrow (err)
241241 throw (ArgumentError (" encountered value(s) not in specified `levels`: " *
242- " $(setdiff (CategoricalArrays . levels (res), levels)) " ))
242+ " $(setdiff (_levels (res), levels)) " ))
243243 end
244244 end
245245 return res
@@ -358,18 +358,18 @@ function _convert(::Type{CategoricalArray{T, N, R}}, A::AbstractArray{S, N};
358358 copyto! (res, A)
359359
360360 if levels != = nothing
361- CategoricalArrays . levels (res) == levels ||
361+ _levels (res) == levels ||
362362 throw (ArgumentError (" encountered value(s) not in specified `levels`: " *
363- " $(setdiff (CategoricalArrays . levels (res), levels)) " ))
363+ " $(setdiff (_levels (res), levels)) " ))
364364 else
365365 # if order is defined for level type, automatically apply it
366366 L = leveltype (res)
367367 if Base. OrderStyle (L) isa Base. Ordered
368- levels! (res, sort (CategoricalArrays . levels (res)))
368+ levels! (res, sort (_levels (res)))
369369 elseif hasmethod (isless, (L, L))
370370 # isless may throw an error, e.g. for AbstractArray{T} of unordered T
371371 try
372- levels! (res, sort (CategoricalArrays . levels (res)))
372+ levels! (res, sort (_levels (res)))
373373 catch e
374374 e isa MethodError || rethrow (e)
375375 end
382382# From CategoricalArray (preserve levels, ordering and R)
383383function convert (:: Type{CategoricalArray{T, N, R}} , A:: CategoricalArray{S, N} ) where {S, T, N, R}
384384 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 ]))
386386 end
387387
388388 if ! (T >: Missing ) && S >: Missing && any (iszero, A. refs)
@@ -460,7 +460,7 @@ size(A::CategoricalArray) = size(A.refs)
460460Base. IndexStyle (:: Type{<:CategoricalArray} ) = IndexLinear ()
461461
462462function update_refs! (A:: CategoricalArray , newlevels:: AbstractVector )
463- oldlevels = levels (A)
463+ oldlevels = _levels (A)
464464 levelsmap = similar (A. refs, length (oldlevels)+ 1 )
465465 # 0 maps to a missing value
466466 levelsmap[1 ] = 0
@@ -478,7 +478,7 @@ function merge_pools!(A::CatArrOrSub,
478478 updaterefs:: Bool = true ,
479479 updatepool:: Bool = true )
480480 newlevels, ordered = merge_pools (pool (A), pool (B))
481- oldlevels = levels (A)
481+ oldlevels = _levels (A)
482482 pA = A isa SubArray ? parent (A) : A
483483 ordered! (pA, ordered)
484484 # 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,
537537
538538 # try converting src to dest type to avoid partial copy corruption of dest
539539 # 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)
542542 if eltype (src) >: Missing && ! (eltype (dest) >: Missing ) && ! all (x -> x > 0 , srefs)
543543 throw (MissingException (" cannot copy array with missing values to an array with element type $T " ))
544544 end
@@ -591,7 +591,7 @@ function copyto!(dest::CatArrOrSub{T1, N, R}, dstart::Integer,
591591 return invoke (copyto!, Tuple{AbstractArray, Integer, AbstractArray, Integer, Integer},
592592 dest, dstart, src, sstart, n)
593593 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
595595 srclevsnm = T2 >: Missing ? setdiff (srclevs, [missing ]) : srclevs
596596 if ! (srclevsnm ⊆ destlevs)
597597 # 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
701701performance inside the function where the call is made. Therefore, use it with caution.
702702"""
703703function compress (A:: CategoricalArray{T, N} ) where {T, N}
704- R = reftype (length (levels (A. pool)))
704+ R = reftype (length (_levels (A. pool)))
705705 convert (CategoricalArray{T, N, R}, A)
706706end
707707
@@ -719,11 +719,11 @@ decompress(A::CategoricalArray{T, N}) where {T, N} =
719719 convert (CategoricalArray{T, N, DefaultRefType}, A)
720720
721721function 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)... )
724724
725725 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))
727727 [x== 0 ? 0 : ii[x] for x in a. refs]:: Array{Int,ndims(a)}
728728 end
729729
@@ -761,23 +761,25 @@ This may include levels which do not actually appear in the data
761761`missing` will be included only if it appears in the data and
762762`skipmissing=false` is passed.
763763
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
765765as doing so would corrupt it.
766766"""
767- @inline function DataAPI. levels (A:: CatArrOrSub{T} ; skipmissing:: Bool = true ) where T
767+ @inline function DataAPI. levels (A:: CatArrOrSub ; skipmissing:: Bool = true )
768768 if eltype (A) >: Missing && ! skipmissing
769769 if any (== (0 ), refs (A))
770- T [levels (pool (A)); missing ]
770+ eltype (A) [levels (pool (A)); missing ]
771771 else
772- convert (Vector{T}, levels ( pool (A) ))
772+ levels_missing ( pool (A))
773773 end
774774 else
775775 levels (pool (A))
776776 end
777777end
778778
779+ _levels (A:: CatArrOrSub ) = _levels (pool (A))
780+
779781"""
780- levels!(A::CategoricalArray, newlevels::Vector ; allowmissing::Bool=false)
782+ levels!(A::CategoricalArray, newlevels::AbstractVector ; allowmissing::Bool=false)
781783
782784Set the levels categorical array `A`. The order of appearance of levels will be respected
783785by [`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.
791793"""
792794function levels! (A:: CategoricalArray{T, N, R} , newlevels:: AbstractVector ;
793795 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
795797
796798 # map each new level to its ref code
797799 newlv2ref = Dict {eltype(newlevels), Int} ()
@@ -806,7 +808,7 @@ function levels!(A::CategoricalArray{T, N, R}, newlevels::AbstractVector;
806808 end
807809
808810 # 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))
810812 oldref2newref = fill (0 , length (oldlevels) + 1 )
811813 for (i, lv) in enumerate (oldlevels)
812814 oldref2newref[i + 1 ] = get (newlv2ref, lv, 0 )
867869function _uniquerefs (A:: CatArrOrSub{T} ) where T
868870 arefs = refs (A)
869871 res = similar (arefs, 0 )
870- nlevels = length (levels (A))
872+ nlevels = length (_levels (A))
871873 maxunique = nlevels + (T >: Missing ? 1 : 0 )
872874 seen = fill (false , nlevels + 1 ) # always +1 for 0 (missing ref)
873875 @inbounds for ref in arefs
@@ -900,7 +902,7 @@ returned by [`levels`](@ref DataAPI.levels)).
900902"""
901903function droplevels! (A:: CategoricalArray )
902904 arefs = refs (A)
903- nlevels = length (levels (A)) + 1 # +1 for missing
905+ nlevels = length (_levels (A)) + 1 # +1 for missing
904906 seen = fill (false , nlevels)
905907 seen[1 ] = true # assume that missing is always observed to simplify checks
906908 nseen = 1
@@ -913,7 +915,7 @@ function droplevels!(A::CategoricalArray)
913915 end
914916
915917 # 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))
917919 # recode refs to keep only the seen ones (optimized version of update_refs!())
918920 seen[1 ] = false # to start levelsmap from 0
919921 levelsmap = cumsum (seen)
@@ -1030,7 +1032,7 @@ end
10301032 ordered= _isordered (A),
10311033 compress:: Bool = false ) where {T, N, R}
10321034 # @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
10341036 CategoricalArray {T, N, RefType} (A, levels= levels, ordered= ordered)
10351037end
10361038
@@ -1043,7 +1045,7 @@ function in(x::CategoricalValue, y::CategoricalArray{T, N, R}) where {T, N, R}
10431045 if x. pool === y. pool
10441046 return refcode (x) in y. refs
10451047 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))
10471049 return ref != 0 ? ref in y. refs : false
10481050 end
10491051end
0 commit comments