@@ -240,7 +240,7 @@ function CategoricalArray{T, N, R}(A::CategoricalArray{S, N, Q};
240
240
catch err
241
241
err isa LevelsException || rethrow (err)
242
242
throw (ArgumentError (" encountered value(s) not in specified `levels`: " *
243
- " $(setdiff (CategoricalArrays . levels (res), levels)) " ))
243
+ " $(setdiff (_levels (res), levels)) " ))
244
244
end
245
245
end
246
246
return res
@@ -359,18 +359,18 @@ function _convert(::Type{CategoricalArray{T, N, R}}, A::AbstractArray{S, N};
359
359
copyto! (res, A)
360
360
361
361
if levels != = nothing
362
- CategoricalArrays . levels (res) == levels ||
362
+ _levels (res) == levels ||
363
363
throw (ArgumentError (" encountered value(s) not in specified `levels`: " *
364
- " $(setdiff (CategoricalArrays . levels (res), levels)) " ))
364
+ " $(setdiff (_levels (res), levels)) " ))
365
365
else
366
366
# if order is defined for level type, automatically apply it
367
367
L = leveltype (res)
368
368
if Base. OrderStyle (L) isa Base. Ordered
369
- levels! (res, sort (CategoricalArrays . levels (res)))
369
+ levels! (res, sort (_levels (res)))
370
370
elseif hasmethod (isless, (L, L))
371
371
# isless may throw an error, e.g. for AbstractArray{T} of unordered T
372
372
try
373
- levels! (res, sort (CategoricalArrays . levels (res)))
373
+ levels! (res, sort (_levels (res)))
374
374
catch e
375
375
e isa MethodError || rethrow (e)
376
376
end
383
383
# From CategoricalArray (preserve levels, ordering and R)
384
384
function convert (:: Type{CategoricalArray{T, N, R}} , A:: CategoricalArray{S, N} ) where {S, T, N, R}
385
385
if length (A. pool) > typemax (R)
386
- throw (LevelsException {T, R} (levels (A)[typemax (R)+ 1 : end ]))
386
+ throw (LevelsException {T, R} (_levels (A)[typemax (R)+ 1 : end ]))
387
387
end
388
388
389
389
if ! (T >: Missing ) && S >: Missing && any (iszero, A. refs)
@@ -467,7 +467,7 @@ size(A::CategoricalArray) = size(A.refs)
467
467
Base. IndexStyle (:: Type{<:CategoricalArray} ) = IndexLinear ()
468
468
469
469
function update_refs! (A:: CategoricalArray , newlevels:: AbstractVector )
470
- oldlevels = levels (A)
470
+ oldlevels = _levels (A)
471
471
levelsmap = similar (A. refs, length (oldlevels)+ 1 )
472
472
# 0 maps to a missing value
473
473
levelsmap[1 ] = 0
@@ -485,7 +485,7 @@ function merge_pools!(A::CatArrOrSub,
485
485
updaterefs:: Bool = true ,
486
486
updatepool:: Bool = true )
487
487
newlevels, ordered = merge_pools (pool (A), pool (B))
488
- oldlevels = levels (A)
488
+ oldlevels = _levels (A)
489
489
pA = A isa SubArray ? parent (A) : A
490
490
ordered! (pA, ordered)
491
491
# If A's levels are an ordered superset of new (merged) pool, no need to recompute refs
@@ -544,8 +544,8 @@ function copyto!(dest::CatArrOrSub{T, N, R}, dstart::Integer,
544
544
545
545
# try converting src to dest type to avoid partial copy corruption of dest
546
546
# in the event that the src cannot be copied into dest
547
- slevs = convert (Vector{T}, levels (src))
548
- dlevs = levels (dest)
547
+ slevs = convert (Vector{T}, _levels (src))
548
+ dlevs = _levels (dest)
549
549
if eltype (src) >: Missing && ! (eltype (dest) >: Missing ) && ! all (x -> x > 0 , srefs)
550
550
throw (MissingException (" cannot copy array with missing values to an array with element type $T " ))
551
551
end
@@ -598,7 +598,7 @@ function copyto!(dest::CatArrOrSub{T1, N, R}, dstart::Integer,
598
598
return invoke (copyto!, Tuple{AbstractArray, Integer, AbstractArray, Integer, Integer},
599
599
dest, dstart, src, sstart, n)
600
600
end
601
- newdestlevs = destlevs = copy (levels (dest)) # copy since we need original levels below
601
+ newdestlevs = destlevs = copy (_levels (dest)) # copy since we need original levels below
602
602
srclevsnm = T2 >: Missing ? setdiff (srclevs, [missing ]) : srclevs
603
603
if ! (srclevsnm ⊆ destlevs)
604
604
# if order is defined for level type, automatically apply it
@@ -708,7 +708,7 @@ While this will reduce memory use, this function is type-unstable, which can aff
708
708
performance inside the function where the call is made. Therefore, use it with caution.
709
709
"""
710
710
function compress (A:: CategoricalArray{T, N} ) where {T, N}
711
- R = reftype (length (levels (A. pool)))
711
+ R = reftype (length (_levels (A. pool)))
712
712
convert (CategoricalArray{T, N, R}, A)
713
713
end
714
714
@@ -726,11 +726,11 @@ decompress(A::CategoricalArray{T, N}) where {T, N} =
726
726
convert (CategoricalArray{T, N, DefaultRefType}, A)
727
727
728
728
function vcat (A:: CategoricalArray... )
729
- ordered = any (isordered, A) && all (a-> isordered (a) || isempty (levels (a)), A)
730
- newlevels, ordered = mergelevels (ordered, map (levels , A)... )
729
+ ordered = any (isordered, A) && all (a-> isordered (a) || isempty (_levels (a)), A)
730
+ newlevels, ordered = mergelevels (ordered, map (_levels , A)... )
731
731
732
732
refsvec = map (A) do a
733
- ii = convert (Vector{Int}, indexin (levels (a. pool), newlevels))
733
+ ii = convert (Vector{Int}, indexin (_levels (a. pool), newlevels))
734
734
[x== 0 ? 0 : ii[x] for x in a. refs]:: Array{Int,ndims(a)}
735
735
end
736
736
@@ -768,23 +768,25 @@ This may include levels which do not actually appear in the data
768
768
`missing` will be included only if it appears in the data and
769
769
`skipmissing=false` is passed.
770
770
771
- The returned vector is an internal field of `x` which must not be mutated
771
+ The returned vector is owned by `x` and must not be mutated
772
772
as doing so would corrupt it.
773
773
"""
774
- @inline function DataAPI. levels (A:: CatArrOrSub{T} ; skipmissing:: Bool = true ) where T
774
+ @inline function DataAPI. levels (A:: CatArrOrSub ; skipmissing:: Bool = true )
775
775
if eltype (A) >: Missing && ! skipmissing
776
776
if any (== (0 ), refs (A))
777
- T [levels (pool (A)); missing ]
777
+ eltype (A) [levels (pool (A)); missing ]
778
778
else
779
- convert (Vector{T}, levels ( pool (A) ))
779
+ levels_missing ( pool (A))
780
780
end
781
781
else
782
782
levels (pool (A))
783
783
end
784
784
end
785
785
786
+ _levels (A:: CatArrOrSub ) = _levels (pool (A))
787
+
786
788
"""
787
- levels!(A::CategoricalArray, newlevels::Vector ; allowmissing::Bool=false)
789
+ levels!(A::CategoricalArray, newlevels::AbstractVector ; allowmissing::Bool=false)
788
790
789
791
Set the levels categorical array `A`. The order of appearance of levels will be respected
790
792
by [`levels`](@ref DataAPI.levels), which may affect display of results in some operations; if `A` is
@@ -798,7 +800,7 @@ Else, `newlevels` must include all levels which appear in the data.
798
800
"""
799
801
function levels! (A:: CategoricalArray{T, N, R} , newlevels:: AbstractVector ;
800
802
allowmissing:: Bool = false ) where {T, N, R}
801
- (levels (A) == newlevels) && return A # nothing to do
803
+ (_levels (A) == newlevels) && return A # nothing to do
802
804
803
805
# map each new level to its ref code
804
806
newlv2ref = Dict {eltype(newlevels), Int} ()
@@ -813,7 +815,7 @@ function levels!(A::CategoricalArray{T, N, R}, newlevels::AbstractVector;
813
815
end
814
816
815
817
# map each old ref code to new ref code (or 0 if no such level)
816
- oldlevels = levels (pool (A))
818
+ oldlevels = _levels (pool (A))
817
819
oldref2newref = fill (0 , length (oldlevels) + 1 )
818
820
for (i, lv) in enumerate (oldlevels)
819
821
oldref2newref[i + 1 ] = get (newlv2ref, lv, 0 )
874
876
function _uniquerefs (A:: CatArrOrSub{T} ) where T
875
877
arefs = refs (A)
876
878
res = similar (arefs, 0 )
877
- nlevels = length (levels (A))
879
+ nlevels = length (_levels (A))
878
880
maxunique = nlevels + (T >: Missing ? 1 : 0 )
879
881
seen = fill (false , nlevels + 1 ) # always +1 for 0 (missing ref)
880
882
@inbounds for ref in arefs
@@ -907,7 +909,7 @@ returned by [`levels`](@ref DataAPI.levels)).
907
909
"""
908
910
function droplevels! (A:: CategoricalArray )
909
911
arefs = refs (A)
910
- nlevels = length (levels (A)) + 1 # +1 for missing
912
+ nlevels = length (_levels (A)) + 1 # +1 for missing
911
913
seen = fill (false , nlevels)
912
914
seen[1 ] = true # assume that missing is always observed to simplify checks
913
915
nseen = 1
@@ -920,7 +922,7 @@ function droplevels!(A::CategoricalArray)
920
922
end
921
923
922
924
# replace the pool
923
- A. pool = typeof (pool (A))(@inbounds (levels (A)[view (seen, 2 : nlevels)]), isordered (A))
925
+ A. pool = typeof (pool (A))(@inbounds (_levels (A)[view (seen, 2 : nlevels)]), isordered (A))
924
926
# recode refs to keep only the seen ones (optimized version of update_refs!())
925
927
seen[1 ] = false # to start levelsmap from 0
926
928
levelsmap = cumsum (seen)
@@ -1037,7 +1039,7 @@ end
1037
1039
ordered= _isordered (A),
1038
1040
compress:: Bool = false ) where {T, N, R}
1039
1041
# @inline is needed so that return type is inferred when compress is not provided
1040
- RefType = compress ? reftype (length (CategoricalArrays . levels (A))) : R
1042
+ RefType = compress ? reftype (length (_levels (A))) : R
1041
1043
CategoricalArray {T, N, RefType} (A, levels= levels, ordered= ordered)
1042
1044
end
1043
1045
@@ -1050,7 +1052,7 @@ function in(x::CategoricalValue, y::CategoricalArray{T, N, R}) where {T, N, R}
1050
1052
if x. pool === y. pool
1051
1053
return refcode (x) in y. refs
1052
1054
else
1053
- ref = get (y. pool, levels (x. pool)[refcode (x)], zero (R))
1055
+ ref = get (y. pool, _levels (x. pool)[refcode (x)], zero (R))
1054
1056
return ref != 0 ? ref in y. refs : false
1055
1057
end
1056
1058
end
0 commit comments