Eltype changed during broadcast with missing

How do I tell julia to use the original eltype when broadcasting over a vector and a scalar?

In the following example I would like (and expected) the eltype of the result to be in all three cases Union{Missing,Float64}. However, the eltype depends on which subsets of the vector I take.

x = [1.0, 2.0, missing, missing]
y = 1.0
typeof(x.*y), typeof(x[1:2].*y), typeof(x[3:4].*y)
# (Vector{Union{Missing, Float64}}, Vector{Float64}, Vector{Missing})

This leads to complicated inferred types and further down to type instability when I use this kind of broadcasting. Especially harmful is the third case of accidentally only selecting Missings.

Currently, I use the cumbersome and case-specific:

res = x[1:2].*y
res_eltype = Union{eltype(x),typeof(y)}
convert(Vector{res_eltype}, res)::Vector{res_eltype}

What is the recommended way of telling Julia to use a type-stable expected broadcast type?
Is there a solution to generalize to more complicated broadcasts?

2 Likes

Another option is to create the destination vector first and then use broadcast! (Julia 1.5.3):

julia> newx = Vector{Union{Missing,Float64}}(undef,2)
2-element Array{Union{Missing, Float64},1}:
 missing
 missing
julia> broadcast!(*,newx,x[1:2],y)
2-element Array{Union{Missing, Float64},1}:
 4.0
 8.0
julia> newx
2-element Array{Union{Missing, Float64},1}:
 4.0
 8.0

Thanks,
The disadvantage, here, is that I need to provide the size of the vector in addition to the eltype.

Is there a method where I just state the eltype? Or a method where I can tell the broadcast to type-infer Vector{Union{...}} instead of Union{Vector{...}}?

1 Like