Skip to content

Commit 99ae870

Browse files
committed
Add more user-friendly message
1 parent 0c8722d commit 99ae870

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

src/array.jl

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,34 @@ function reftype(sz::Int)
1919
end
2020
end
2121

22+
# This check is only there to print a user-friendly warning before
23+
# a TypeError is thrown due to restrictions in the type signature
24+
function check_supported_eltype(::Type{T}, ::Type{U}) where {T, U}
25+
T === Symbol &&
26+
throw(ArgumentError("CategoricalArray no longer supports Symbol as element type "*
27+
"as that forces recompiling too many Julia Base methods: " *
28+
"use strings instead, e.g. via categorical(string.(x))"))
29+
T <: Union{SupportedTypes, Missing} ||
30+
throw(ArgumentError("CategoricalArray only supports " *
31+
"AbstractString, AbstractChar and Number element types " *
32+
"(got element type $U)"))
33+
end
34+
2235
fixstringtype(T::Type) = T <: SubString || T === AbstractString ? String : T
2336
fixstringtype(T::Union) = Union{fixstringtype(T.a), fixstringtype(T.b)}
2437
fixstringtype(::Type{Union{}}) = Union{}
2538

39+
# Find a narrow type that is supported to hold all elements if possible
40+
function fixtype(A::AbstractArray{T}) where T
41+
if T <: Union{SupportedTypes, Missing}
42+
return fixstringtype(T)
43+
else
44+
U = fixstringtype(mapreduce(typeof, Base.promote_typejoin, A))
45+
check_supported_eltype(U, T)
46+
return U
47+
end
48+
end
49+
2650
"""
2751
CategoricalArray{T}(undef, dims::Dims; levels=nothing, ordered=false)
2852
CategoricalArray{T}(undef, dims::Int...; levels=nothing, ordered=false)
@@ -135,6 +159,7 @@ function CategoricalArray{T, N, R}(::UndefInitializer, dims::NTuple{N,Int};
135159
ordered::Bool=false) where {T, N, R}
136160
U = leveltype(nonmissingtype(T))
137161
S = T >: Missing ? Union{U, Missing} : U
162+
check_supported_eltype(S, T)
138163
V = CategoricalValue{U, R}
139164
levs = levels === nothing ? U[] : collect(U, levels)
140165
CategoricalArray{S, N}(zeros(R, dims), CategoricalPool{U, R, V}(levs, ordered))
@@ -230,13 +255,6 @@ end
230255

231256
# From AbstractArray
232257

233-
# Find a narrow type that is supported to hold all elements if possible
234-
function fixtype(A::AbstractArray{T}) where T
235-
U = T <: Union{SupportedTypes, Missing} ?
236-
T : mapreduce(typeof, Base.promote_typejoin, A)
237-
return fixstringtype(U)
238-
end
239-
240258
CategoricalArray{T, N}(A::AbstractArray{S, N};
241259
levels::Union{AbstractVector, Nothing}=nothing,
242260
ordered::Bool=_isordered(A)) where {S, T, N} =
@@ -319,6 +337,8 @@ convert(::Type{CategoricalArray{T, N, R}}, A::AbstractArray{S, N}) where {S, T,
319337

320338
function _convert(::Type{CategoricalArray{T, N, R}}, A::AbstractArray{S, N};
321339
levels::Union{AbstractVector, Nothing}=nothing) where {S, T, N, R}
340+
check_supported_eltype(T, T)
341+
322342
res = CategoricalArray{T, N, R}(undef, size(A), levels=levels)
323343
copyto!(res, A)
324344

test/13_arraycommon.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,25 @@ end
11831183
@test x isa CT{Union{Int, Missing}}
11841184
@test x categorical(a)
11851185
end
1186+
1187+
for f in (categorical, CategoricalArray, CategoricalVector,
1188+
x -> convert(CategoricalArray, x),
1189+
x -> convert(CategoricalVector, x))
1190+
@test_throws ArgumentError f([:a])
1191+
@test_throws ArgumentError f(Any[:a])
1192+
@test_throws ArgumentError f([nothing])
1193+
@test_throws ArgumentError f(Any[nothing])
1194+
@test_throws ArgumentError f([1, nothing])
1195+
end
1196+
for f in (categorical, CategoricalArray, CategoricalMatrix,
1197+
x -> convert(CategoricalArray, x),
1198+
x -> convert(CategoricalMatrix, x))
1199+
@test_throws ArgumentError f([:a :a])
1200+
@test_throws ArgumentError f(Any[:a :a])
1201+
@test_throws ArgumentError f([nothing nothing])
1202+
@test_throws ArgumentError f(Any[nothing nothing])
1203+
@test_throws ArgumentError f([1 nothing])
1204+
end
11861205
end
11871206

11881207
@testset "converting from array with missings to array without missings CategoricalArray fails with missings" begin

0 commit comments

Comments
 (0)