Qu'est-ce que NaN? NaN Zoya (Python) (394 jours de retard)

update1 25/01/2020: correction de faute de frappe ʻIEEE745-> ʻIEEE 754

In [1]: from datetime import datetime  
In [2]: (datetime(2020, 1, 11) - datetime(2018, 12, 13)).days                           
Out[2]: 394

Je vais vous expliquer la manipulation de nan en Python. Dans ce qui suit, la notation de nan en tant que concept est appelée NaN.

Disclaimer: Ce message est pour justInCase Advent Calendar 2018 et a été publié après une période d'environ 400 jours, mais en raison de la période de maturité, le contenu N'est pas satisfaisant.

emballer

--NaN en Python suit NaN dans IEEE 754, mais il y a quelques points addictifs ici et là.

[L'environnement de vérification est décrit à la fin](# Environnement de vérification)

Gestion de NaN dans IEEE754

Veuillez vous référer à l'article précédent Qu'est-ce que NaN? NaN Zoya (R).

Notez que NaN silencieux se propage dans les opérations numériques générales, mais que pensez-vous que les deux valeurs suivantes devraient renvoyer? En fait, le traitement du NaN aux valeurs min et max change entre IEEE 754-2008 et IEEE 754-2019. L'explication de est dans un autre article.

min(1.0, float('nan'))
max(1.0, float('nan'))

Comment appeler NaN en Python

Il n'y a pas de langage littéral. Si vous appelez float ('nan') ou numpy, ce qui ne nécessite pas d'appel de module, np.nan a tendance à être beaucoup utilisé.

import math
import decimal
import numpy as np
import pandas as pd

float('nan')
math.nan
0.0 * math.inf
math.inf / math.inf
# 0.0/0.0 ZeroDivisionError en Python. C, R,De nombreuses langues, comme Julia, renvoient NaN
np.nan
np.core.numeric.NaN
pd.np.nan

Tous les objets flottants. Les objets référencés par «numpy» pandas »sont les mêmes, bien qu'ils ne soient pas des objets singleton.

nans = [float('nan'), math.nan, 0 * math.inf, math.inf / math.inf, np.nan, np.core.numeric.NaN, pd.np.nan]

import pprint
pprint.pprint([(type(n), id(n)) for n in nans])
# [(<class 'float'>, 4544450768),
#  (<class 'float'>, 4321186672),
#  (<class 'float'>, 4544450704),
#  (<class 'float'>, 4544450832),
#  (<class 'float'>, 4320345936),
#  (<class 'float'>, 4320345936),
#  (<class 'float'>, 4320345936)]

float ('nan') lui-même est un objet immuable de la classe float, donc hachable. Cela peut donc être une clé de dictionnaire, mais étrangement, cela vous permet d'ajouter plusieurs nans. Et si vous ne liez pas la clé à une variable à l'avance, vous ne pouvez pas la récupérer à nouveau. On pense que cela est dû au fait que tous les résultats de l'opérateur de comparaison de NaN sont False, c'est-à-direfloat ('nan') == float ('nan')-> False.

>>> d = {float('nan'): 1, float('nan'): 2, float('nan'): 3}
>>> d
{nan: 1, nan: 2, nan: 3}
>>> d[float('nan')]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: nan

Notez l'existence d'objets avec des propriétés de type NaN qui ne sont pas des classes flottantes. En particulier, «pd.NaT» et «np.datetime64 (« NaT »)» sont des classes différentes.

decimal.Decimal('nan')
pd.NaT
np.datetime64("NaT")

# >>> type(decimal.Decimal('nan'))
# <class 'decimal.Decimal'>

# >>> type(pd.NaT)
# <class 'pandas._libs.tslibs.nattype.NaTType'>

# >>> type(np.datetime64("NaT"))
# <class 'numpy.datetime64'>

Par conséquent, les précautions suivantes sont nécessaires lors de l'utilisation de np.isnat.

>>> np.isnat(pd.NaT)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: ufunc 'isnat' is only defined for datetime and timedelta.

>>> np.isnat(np.datetime64("NaT"))
True

Vérification NaN

math.isnan
np.isnan
pd.isna

La situation actuelle de «math.isnan» est ici. https://github.com/python/cpython/blob/e42b705188271da108de42b55d9344642170aa2b/Include/pymath.h#L88-L103 https://github.com/python/cpython/blob/34fd4c20198dea6ab2fe8dc6d32d744d9bde868d/Lib/_pydecimal.py#L713-L726

/* Py_IS_NAN(X)
 * Return 1 if float or double arg is a NaN, else 0.
 * Caution:
 *     X is evaluated more than once.
 *     This may not work on all platforms.  Each platform has *some*
 *     way to spell this, though -- override in pyconfig.h if you have
 *     a platform where it doesn't work.
 * Note: PC/pyconfig.h defines Py_IS_NAN as _isnan
 */
#ifndef Py_IS_NAN
#if defined HAVE_DECL_ISNAN && HAVE_DECL_ISNAN == 1
#define Py_IS_NAN(X) isnan(X)
#else
#define Py_IS_NAN(X) ((X) != (X))
#endif
#endif
def _isnan(self):
    """Returns whether the number is not actually one.
    0 if a number
    1 if NaN
    2 if sNaN
    """
    if self._is_special:
        exp = self._exp
        if exp == 'n':
            return 1
        elif exp == 'N':
            return 2
    return 0

Notez que la méthode «isna» de pandas (et aussi «isnull») renvoie «True» comme valeurs manquantes pour «None» et «pd.NaT» ainsi que «float nan». Si pandas.options.mode.use_inf_as_na = True, il y a une astuce qui np.inf est également considérée comme une valeur manquante.

>>> pd.isna(math.nan)
True
>>> pd.isna(None)
True
>>> pd.isna(math.inf)
False
>>> pandas.options.mode.use_inf_as_na = True
>>> pd.isna(math.inf)
True

À propos de la méthode pandas

La méthode directe de l'objet pandas prend comme argument un scalaire ou un tableau et la valeur de retour est un booléen de la même taille que l'argument. D'autre part, la méthode directe de pd.DataFrame est un DataFrame pour l'argument et la valeur de retour.

pd.isna # for scalar or array-like
pd.DataFrame.isna # for DataFrame

L'objet de type tableau fait spécifiquement référence à l'objet suivant. (https://github.com/pandas-dev/pandas/blob/v0.25.3/pandas/core/dtypes/missing.py#L136-L147)

ABCSeries,
np.ndarray,
ABCIndexClass,
ABCExtensionArray,
ABCDatetimeArray,
ABCTimedeltaArray,

Il convient de noter, peut être soit pour «pd.isna» et «pd.isnull» est exactement le même (une utilisation unifiée du point de vue de la lisibilité est souhaitable).

# https://github.com/pandas-dev/pandas/blob/v0.25.3/pandas/core/dtypes/missing.py#L125
>>> id(pd.isnull)
4770964688
>>> id(pd.isna)
4770964688

est un résumé de la méthode

Si vous ne voulez pas rencontrer d'erreur inattendue, pd.isna est sûr, mais soyez prudent car il se fuira au jugement de Decimal ('nan').

math.nan decimal.Decimal('nan') np.datetime64("NaT") pd.NaT math.inf None
math.isnan True True error error False error
decimal.Decimal.is_nan error True error error error error
np.isnan True error True error False error
pd.isna True False True True False True
np.isnat error error True error error error

Autre

Confirmez l'expression binaire. Vous pouvez voir que c'est NaN calme.

>>> import struct
>>> xs = struct.pack('>d', math.nan)
>>> xs
b'\x7f\xf8\x00\x00\x00\x00\x00\x00'
>>> xn = struct.unpack('>Q', xs)[0]
>>> xn
9221120237041090560
>>> bin(xn)
'0b111111111111000000000000000000000000000000000000000000000000000'

Résumé (republication)

--NaN en Python suit NaN dans IEEE754, mais il y a quelques points addictifs ici et là.

finalement Si vous aimez ce genre d'histoire maniaque, venez nous rendre visite à justInCase. https://www.wantedly.com/companies/justincase

c'est tout

Environnement de vérification

$ uname -a
Darwin MacBook-Pro-3.local 18.7.0 Darwin Kernel Version 18.7.0: Sat Oct 12 00:02:19 PDT 2019; root:xnu-4903.278.12~1/RELEASE_X86_64 x86_64

$ python
Python 3.7.4 (default, Nov 17 2019, 08:06:12) 
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin

$ pip list | grep -e numpy -e pandas
numpy                    1.18.0     
pandas                   0.25.3   

Recommended Posts

Qu'est-ce que NaN? NaN Zoya (Python) (394 jours de retard)
Qu'est-ce que python
Qu'est-ce que Python
[Python] Qu'est-ce que Pipeline ...
[Python] Qu'est-ce que virtualenv
[Python] Python et sécurité-① Qu'est-ce que Python?
[Python] * args ** Qu'est-ce que kwrgs?
Cours de base Python (1 Qu'est-ce que Python)
[Python] Qu'est-ce que @? (À propos des décorateurs)
[python] Quelle est la clé triée?
Python pour la déclaration ~ Qu'est-ce qui est itérable ~
À quoi sert le trait de soulignement Python (_)?
Python> Qu'est-ce qu'une tranche étendue?
[Python] Qu'est-ce que la série pandas et DataFrame?
[Python] Qu'est-ce qui est hérité par l'héritage multiple?
Quel type de langage de programmation est Python?
Qu'est-ce que "mahjong" dans la bibliothèque Python? ??
Qu'est-ce qu'un chien? Volume d'installation Python
Qu'est-ce que l'espace de noms
Qu'est-ce qu'un algorithme? Introduction à l'algorithme de recherche] ~ Python ~
Qu'est-ce que copy.copy ()
Qu'est-ce que la «programmation fonctionnelle» et «orientée objet»? Édition Python
Python est facile
Qu'est-ce que Django? .. ..
Qu'est-ce que dotenv?
Qu'est-ce que POSIX
Qu'est-ce que wheezy dans l'image Docker Python?
Qu'est-ce que Linux
Qu'est-ce que le klass?
J'ai essayé Python! ] Diplômé aujourd'hui de "Tout le monde Python! Qu'est-ce que Python!"!
Qu'est-ce que SALOME?
Qu'est-ce que Linux?
Que comparez-vous avec Python et ==?
Qu'est-ce que l'hyperopt?
Python est une instance
Qu'est-ce que Linux
[Introduction à l'application Udemy Python3 +] 54. Qu'est-ce que Docstrings?
Qu'est-ce que pyvenv
Qu'est-ce que __call__
Qu'est-ce que Linux
Dites-moi ce qu'est une cartographie équiangulaire, Python!
Qu'est-ce que l'algorithme [Ruby / Python / Java / Swift / JS]?
[Python] Calender Heatmap [Plotly] Memo
Qu'est-ce que Dieu? Créez un chatbot simple avec python
python int est infini
Qu'est-ce qu'une distribution?
Qu'est-ce que le F-Score de Piotroski?
Qu'est-ce que Raspberry Pi?
Qu'est-ce que Calmar Ratio?
Qu'est-ce qu'un terminal?
[Tutoriel PyTorch ①] Qu'est-ce que PyTorch?
Qu'est-ce que le réglage des hyper paramètres?
Qu'est-ce qu'un hacker?
Qu'est-ce que JSON? .. [Remarque]
À quoi sert Linux?
Qu'est-ce qu'un pointeur?