# Julia NaN check for NamedTuple

**URL:** <https://discourse.julialang.org/t/julia-nan-check-for-namedtuple/102583>\
**Category:** General Usage\
**Tags:** nan, namedtuple\
**Created:** [August 8, 2023, 1:58am UTC](https://discourse.julialang.org/t/julia-nan-check-for-namedtuple/102583 "2023-08-08T01:58:45Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)\
**Post date:** [August 8, 2023, 1:58am UTC](https://discourse.julialang.org/t/julia-nan-check-for-namedtuple/102583/1 "2023-08-08T01:58:45Z")

</div>

How to check if `NaN` is in a given NamedTuple?

For example,

```julia
julia> myarray = [0, 1, 2, NaN]
4-element Vector{Float64}:
   0.0
   1.0
   2.0
 NaN

julia> isnan.(myarray)
4-element BitVector:
 0
 0
 0
 1

julia> mynt = (; a = 0, b = (; b1=1, b2=2), c=NaN)
(a = 0, b = (b1 = 1, b2 = 2), c = NaN)

julia> isnan.(mynt)
ERROR: ArgumentError: broadcasting over dictionaries and `NamedTuple`s is reserved
Stacktrace:
 [1] broadcastable(#unused#::NamedTuple{(:a, :b, :c), Tuple{Int64, NamedTuple{(:b1, :b2), Tuple{Int64, Int64}}, Float64}})
   @ Base.Broadcast ./broadcast.jl:718
 [2] broadcasted(::Function, ::NamedTuple{(:a, :b, :c), Tuple{Int64, NamedTuple{(:b1, :b2), Tuple{Int64, Int64}}, Float64}})
   @ Base.Broadcast ./broadcast.jl:1309
 [3] top-level scope
   @ REPL[15]:1
 [4] top-level scope
   @ ~/.julia/packages/Infiltrator/LtFao/src/Infiltrator.jl:726

```

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [August 8, 2023, 2:36am UTC](https://discourse.julialang.org/t/julia-nan-check-for-namedtuple/102583/2 "2023-08-08T02:36:47Z")

</div>

if you do not need to search more than one level of nesting

```julia
function findnan(x::NamedTuple)
   isnan.(Iterators.flatten(values(x)))
end

nt0 = (; a = 0, b = (; b1=1, b2=2), c=5)
nt1 = (; a = 0, b = (; b1=1, b2=2), c=NaN)
nt2 = (; a = 0, b = (; b1=1, b2=NaN), c=3)
nt3 = (; a = 0, b = (; b1=1, b2=NaN), c=NaN)

```

```julia
julia> findnan(nt0), any(findnan(nt0))
(Bool[0, 0, 0, 0], false)

julia> findnan(nt1), any(findnan(nt3))
(Bool[0, 0, 0, 1], true)

julia> findnan(nt2), any(findnan(nt3))
(Bool[0, 0, 1, 0], true)

julia> findnan(nt3), any(findnan(nt3))
(Bool[0, 0, 1, 1], true)

```

---

<div class="post-metadata">

**Author:** ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)\
**Post date:** [August 8, 2023, 2:38am UTC](https://discourse.julialang.org/t/julia-nan-check-for-namedtuple/102583/3 "2023-08-08T02:38:46Z")

</div>

Ah, thank you! Didn’t think of `flatten`.

Actually, nesting is required in my case. I’ll figure it out and please let me know if you know how to extend this for nesting!

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [August 8, 2023, 6:51am UTC](https://discourse.julialang.org/t/julia-nan-check-for-namedtuple/102583/4 "2023-08-08T06:51:11Z")

</div>

Much more efficient than `Iterators.flatten`, more generic, and supports arbitrary nesting:

```julia
julia> using AccessorsExtra

# get all numbers from anywhere in the object:
julia> getall(mynt, RecursiveOfType(Number))
(0, 1, 2, NaN)

# check that there are nans among them:
julia> any(isnan, getall(mynt, RecursiveOfType(Number)))
true

```

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [August 8, 2023, 7:00am UTC](https://discourse.julialang.org/t/julia-nan-check-for-namedtuple/102583/5 "2023-08-08T07:00:39Z")

</div>

```julia
julia> isnan_rec(n::NamedTuple) = any(isnan_rec, n)
isnan_rec (generic function with 1 method)

julia> isnan_rec(n::Number) = isnan(n)
isnan_rec (generic function with 2 methods)

julia> isnan_rec((; a = 1, b = (; c = 2, d = (; e = NaN))))
true

julia> isnan_rec((; a = 1, b = (; c = 2, d = (; e = 4.0))))
false

```

Edit: this one doesn’t allocate (not sure why `any` does, probably doesn’t unroll automatically even though I would have assumed that for short `NamedTuple`s)

```julia
@generated function isnan_rec(n::NamedTuple)
    quote
        Base.Cartesian.@nany $(fieldcount(n)) i -> isnan_rec(n[i])
    end
end

```
