Parcours
/
Julia
Julia
/
Programme
/
Absence de valeur
Ab

Absence de valeur en Julia

1 exercice

À propos de Absence de valeur

De nombreux langages disposent d'un moyen comme null ou none pour indiquer une valeur inexistante. Comme Julia est conçu pour traiter de grands volumes de données (souvent désordonnées), il possède plusieurs formes de l'absence de valeur.

L'objectif général est de signaler les valeurs manquantes ou douteuses au fur et à mesure qu'on les rencontre, puis de continuer sans lever d'exception.

nothing

Si une valeur n'existe vraiment pas, elle est représentée par nothing. C'est probablement ce qui se rapproche le plus de ce que font le NULL du C ou le None de Python.

julia> n = nothing

julia> isnothing(n)
true

julia> typeof(n)
Nothing

nothing est donc une valeur singleton de type Nothing, et on peut tester sa présence.

L'un des usages courants de nothing est de servir de valeur de retour (ou plutôt de non-valeur) pour les fonctions qu'on n'utilise que pour leurs effets de bord (afficher des choses, configurer le réseau, ou autre).

missing

Pour les situations où une valeur existe en théorie, mais où on ne sait pas ce qu'elle vaut, on utilise missing. Par exemple, quand on compte les véhicules qui circulent sur une route, les observateurs humains ont parfois besoin de faire une pause, ou bien les capteurs automatiques tombent en panne, alors que le trafic continue de s'écouler.

Ainsi, missing est une valeur de remplacement qui avertit qu'il faut décider comment gérer cette lacune dans les données.

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

Peu d'autres langages intègrent cette fonctionnalité nativement, mais il existe des équivalents proches : NA en R ou NULL en SQL.

Le type du vecteur dans l'exemple ci-dessus est Union{Missing, Int64}, ce qui n'est pas sans rappeler des types comme Option ou Maybe dans d'autres langages.

Les expressions renvoient généralement missing par défaut lorsque des valeurs missing sont présentes. Si tu veux que ces valeurs soient ignorées, utilise la fonction skipmissing() pour que ce soit explicite :

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

Comme skipmissing crée un itérateur, enveloppe-le dans collect() si tu as besoin d'un vecteur.

Il est parfois utile de remplacer les valeurs missing par une valeur par défaut. La macro @coalesce() est pratique pour cela, car elle renvoie la première valeur qui n'est pas missing (ou missing s'il n'y a rien d'autre).

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

Abréviation de « Not a Number », NaN signale un problème de calcul dans les situations où un nombre était attendu.

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

Tout calcul effectué sur des données contenant un NaN donnera un résultat NaN.

Il n'existe actuellement aucune fonction dédiée pour supprimer les valeurs NaN, mais la fonction standard filter() peut s'en charger très simplement. Seules les valeurs pour lesquelles une condition donnée vaut true sont copiées dans le tableau final :

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

Données non définies

C'est une situation que tu rencontreras sans doute moins souvent. Elle se présente notamment dans les cas suivants :

  • Il est possible de créer des types composites (comme struct) avec des champs non initialisés. Julia essaie généralement d'utiliser des valeurs par défaut, mais ne peut le faire que s'il dispose d'assez d'informations pour inférer le type du champ.
  • Dans certains cas, initialiser un vecteur avec undef peut être une approche souple et performante. C'est ce qui a été fait, par exemple, dans des solutions de la communauté à l'exercice Circular Buffer (une technique avancée, mais l'exercice est classé comme difficile).

Obtenir un résultat undef en essayant d'accéder à une valeur est un état d'erreur, généralement signalé par une UndefRefError.

Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet

Apprends Absence de valeur