Na

Nada en Julia

1 ejercicio

Acerca de Nada

Muchos lenguajes tienen una forma como null o none de indicar un valor inexistente. Como Julia está diseñada para manejar grandes volúmenes de datos (a menudo desordenados), tiene varias formas de nada.

El objetivo general es señalar los valores ausentes o sospechosos a medida que se encuentran, y luego continuar sin lanzar una excepción.

nothing

Si un valor realmente no existe, se representa con nothing. Esto es probablemente lo más parecido a lo que harían C (NULL) o Python (None).

julia> n = nothing

julia> isnothing(n)
true

julia> typeof(n)
Nothing

Así pues, nothing es un valor singleton de tipo Nothing, y podemos comprobarlo.

Un uso habitual de nothing es como valor (no) devuelto de funciones que solo se usan por sus efectos secundarios (imprimir, configurar la red, lo que sea).

missing

Para situaciones en las que un valor existe en teoría pero no sabemos cuál es, se usa missing. Por ejemplo, al contar los vehículos que circulan por una carretera, puede que los observadores humanos necesiten un descanso o que los sensores automáticos se averíen, pero el tráfico sigue fluyendo.

Por tanto, missing es un marcador de posición que avisa a las personas de que tienen que decidir cómo tratar ese hueco en los datos.

julia> mv = [1, 2, missing]
3-element Vector{Union{Missing, Int64}}:
 1
 2
  missing

julia> typeof(mv)
Vector{Union{Missing, Int64}} (alias for Array{Union{Missing, Int64}, 1})

julia> ismissing.(mv)  # broadcast function, displays as 1 for true, 0 for false
3-element BitVector:
 0
 0
 1

Pocos lenguajes más incorporan esta funcionalidad de serie, pero hay equivalentes cercanos en NA de R o NULL de SQL.

El tipo del vector del ejemplo anterior es Union{Missing, Int64}, que guarda cierta similitud con tipos como Option o Maybe de otros lenguajes.

Por defecto, las expresiones suelen devolver missing si hay valores missing presentes. Si quieres que se ignoren estos valores, usa la función skipmissing() para dejarlo explícito:

julia> mv = [1, 2, missing]
3-element Vector{Union{Missing, Int64}}:
 1
 2
  missing

julia> sum(mv)  # missing in, missing out
missing

julia> skipmissing(mv)
skipmissing(Union{Missing, Int64}[1, 2, missing])

julia> collect(skipmissing(mv))
2-element Vector{Int64}:
 1
 2

julia> sum(skipmissing(mv))  # functions like sum() can work with iterators
3

Como skipmissing crea un iterador, envuélvelo en collect() si necesitas un vector.

A veces resulta útil sustituir los valores missing por algún valor predeterminado. La macro @coalesce() es útil para esto, ya que devuelve el primer valor que no sea missing (o missing si no hay nada más).

julia> str = ["I", "exist", missing]
3-element Vector{Union{Missing, String}}:
 "I"
 "exist"
 missing

julia> [@coalesce(s, "-") for  s in str]
3-element Vector{String}:
 "I"
 "exist"
 "-"

NaN

Abreviatura de «Not a Number», NaN señala un problema de cálculo en situaciones en las que se esperaba un número.

julia> v = [0, 1, -1]
3-element Vector{Int64}:
  0
  1
 -1

julia> v / 0
3-element Vector{Float64}:
 NaN
  Inf
 -Inf
 
julia> sum(v / 0)
NaN

Cualquier cálculo sobre datos que incluyan un NaN dará como resultado NaN.

Actualmente no hay ninguna función especial para eliminar valores NaN, pero la función estándar filter() puede hacerlo de forma bastante sencilla. Solo se copiarán al array resultante los valores para los que se cumpla una condición dada (true):

julia> filter(!isnan, [1, 2, NaN])
2-element Vector{Float64}:
 1.0
 2.0

Datos sin definir

Es algo que probablemente uses con menos frecuencia. Entre las excepciones se incluyen:

  • Hay formas de crear tipos compuestos (como struct) con campos sin inicializar. Julia suele intentar usar valores predeterminados, pero solo puede hacerlo si tiene suficiente información para inferir el tipo del campo.
  • En algunos casos, inicializar un vector como undef puede ser un enfoque flexible y eficiente. Esto se ha usado, por ejemplo, en soluciones de la comunidad al ejercicio búfer circular (una técnica avanzada, pero está clasificado como ejercicio difícil).

Obtener un resultado undef al intentar acceder a un valor es un estado de error, que normalmente se señala con un UndefRefError.

Editar en GitHub El enlace se abre en una nueva ventana o pestaña

Aprende Nada