Skip to content

Commit 8d086f6

Browse files
authored
Add special case for single missing RHS in recode() (JuliaData#103)
When a single pair appears and the RHS is 'missing', it is very unlikely that the caller would want an Array{Missing} result. Instead, return an Array{Union{T, Missing}}, with T the original array's eltype. This is useful to transform some values into missing values.
1 parent e07a9a4 commit 8d086f6

File tree

2 files changed

+25
-4
lines changed

2 files changed

+25
-4
lines changed

src/recode.jl

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,14 @@ function recode(a::AbstractArray, default::Any, pairs::Pair...)
322322
# whether it matters at compile time (all levels recoded or not)
323323
# and using a wider type than necessary would be annoying
324324
T = default === nothing ? V : promote_type(typeof(default), V)
325-
# Exception: if original array accepted missing values and missing does not appear
325+
# Exception 1: if T === Missing and default not missing,
326+
# assume the caller wants to recode only some values to missing,
327+
# but accept original values
328+
if T === Missing && default !== missing
329+
dest = Array{Union{eltype(a), Missing}}(size(a))
330+
# Exception 2: if original array accepted missing values and missing does not appear
326331
# in one of the pairs' LHS, result must accept missing values
327-
if T >: Missing || default === missing || (eltype(a) >: Missing && !keytype_hasmissing(pairs...))
332+
elseif T >: Missing || default === missing || (eltype(a) >: Missing && !keytype_hasmissing(pairs...))
328333
dest = Array{Union{T, Missing}}(size(a))
329334
else
330335
dest = Array{Missings.T(T)}(size(a))
@@ -338,9 +343,14 @@ function recode(a::CategoricalArray{S, N, R}, default::Any, pairs::Pair...) wher
338343
# whether it matters at compile time (all levels recoded or not)
339344
# and using a wider type than necessary would be annoying
340345
T = default === nothing ? V : promote_type(typeof(default), V)
341-
# Exception: if original array accepted missing values and missing does not appear
346+
# Exception 1: if T === Missing and default not missing,
347+
# assume the caller wants to recode only some values to missing,
348+
# but accept original values
349+
if T === Missing && default !== missing
350+
dest = CategoricalArray{Union{S, Missing}, N, R}(size(a))
351+
# Exception 2: if original array accepted missing values and missing does not appear
342352
# in one of the pairs' LHS, result must accept missing values
343-
if T >: Missing || default === missing || (eltype(a) >: Missing && !keytype_hasmissing(pairs...))
353+
elseif T >: Missing || default === missing || (eltype(a) >: Missing && !keytype_hasmissing(pairs...))
344354
dest = CategoricalArray{Union{T, Missing}, N, R}(size(a))
345355
else
346356
dest = CategoricalArray{Missings.T(T), N, R}(size(a))

test/16_recode.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,17 @@ end
335335
else
336336
@test typeof(y) === Vector{Union{Int, Missing}}
337337
end
338+
339+
# Recoding from Int to Union{Int, Missing} with single missing RHS
340+
y = @inferred recode(x, 1=>missing)
341+
@test y [missing, 2, 3, 4, 5, 6, 7, 8, 9, 10]
342+
if isa(x, CategoricalArray)
343+
@test isa(y, CategoricalVector{Union{Int, Missing}, DefaultRefType})
344+
@test levels(y) == collect(2:10)
345+
@test !isordered(y)
346+
else
347+
@test typeof(y) === Vector{Union{Int, Missing}}
348+
end
338349
end
339350

340351
@testset "Recoding from $(typeof(x)) to $(typeof(x))" for

0 commit comments

Comments
 (0)