web-dev-qa-db-fra.com

NumPy ou Pandas: Conserver le type de tableau sous forme d'entier tout en ayant une valeur NaN

Existe-t-il un moyen privilégié de conserver le type de données d'un tableau numpy fixé en tant que int (ou int64 ou autre), tout en ayant toujours un élément répertorié en tant que numpy.NaN

En particulier, je convertis une structure de données interne en un Pandas DataFrame. Dans notre structure, nous avons des colonnes de type entier qui ont toujours des NaN (mais le type de la colonne est int). Il semble que tout soit reformulé comme un float si nous en faisons un DataFrame, mais nous aimerions vraiment être int.

Pensées?

Les choses essayées:

J'ai essayé d'utiliser la fonction from_records() sous pandas.DataFrame, avec coerce_float=False et cela n'a pas aidé. J'ai également essayé d'utiliser des tableaux masqués NumPy, avec NaN fill_value, qui ne fonctionnaient pas non plus. Tous ces facteurs ont amené le type de données de la colonne à devenir un float.

108
ely

Cette fonctionnalité a été ajoutée aux pandas (à partir de la version 0.24): https://pandas.pydata.org/pandas-docs/version/0.24/whatsnew/v0.24.0.html#optional-integer-na -soutien

À ce stade, il nécessite l'utilisation de l'extension dtype Int64 (en majuscule), plutôt que du type par défaut int64 (en minuscule).

20
techvslife

NaN ne peut pas être stocké dans un tableau entier. C'est une limitation connue des pandas pour le moment; J'attendais que des progrès soient réalisés avec les valeurs de NA dans NumPy (similaires aux NA dans R), mais il faudra au moins 6 mois à un an avant que NumPy obtienne ces caractéristiques, il semble:

http://pandas.pydata.org/pandas-docs/stable/gotchas.html#support-for-integer-na

(Cette fonctionnalité a été ajoutée à partir de la version 0.24 de pandas, mais notez qu’elle nécessite l’utilisation de l’extension dtype Int64 (en majuscule), plutôt que du type par défaut int64 (en minuscule): https: //. pandas.pydata.org/pandas-docs/version/0.24/whatsnew/v0.24.0.html#optional-integer-na-support )

92
Wes McKinney

Si les performances ne sont pas le problème principal, vous pouvez stocker des chaînes.

df.col = df.col.dropna().apply(lambda x: str(int(x)) )

Ensuite, vous pouvez mélanger avec NaN autant que vous le souhaitez. Si vous voulez vraiment avoir des entiers, selon votre application, vous pouvez utiliser -1, ou 0, ou 1234567890, ou une autre valeur dédiée pour représenter NaN

Vous pouvez également dupliquer temporairement les colonnes: une comme vous l’avez, avec des flottants; l'autre expérimental, avec des entiers ou des chaînes. Ensuite, insère asserts à chaque endroit raisonnable en vérifiant que les deux sont synchronisés. Après suffisamment de tests, vous pouvez abandonner les flotteurs. 

7
osa

Ce n'est pas une solution pour tous les cas, mais le mien (coordonnées génomiques) j'ai eu recours à utiliser 0 comme NaN

a3['MapInfo'] = a3['MapInfo'].fillna(0).astype(int)

Cela permet au moins d'utiliser le type de colonne 'natif' approprié, des opérations telles que la soustraction, la comparaison, etc. fonctionnent comme prévu.

3
pufferfish

Pandas v0.24 +

La fonctionnalité permettant de prendre en charge NaN dans les séries entières sera disponible à partir de la v0.24. Il y a informations à ce sujet dans la section "Quoi de neuf" v0.24, bien que les documents officiels soient en cours de traitement } à être mis à jour.

Pandas v0.23 et versions antérieures

En général, il est préférable de travailler avec la série float lorsque cela est possible, même lorsque la série est upcast de int à float en raison de l'inclusion des valeurs NaN Cela permet des calculs basés sur NumPy vectorisés où, sinon, les boucles au niveau Python seraient traitées.

Les docs font suggèrent : "Une possibilité consiste à utiliser des tableaux dtype=object à la place." Par exemple:

s = pd.Series([1, 2, 3, np.nan])

print(s.astype(object))

0      1
1      2
2      3
3    NaN
dtype: object

Pour des raisons esthétiques, par exemple sortie dans un fichier, ceci peut être préférable.

Pandas v0.23 et versions antérieures: arrière-plan

_ { NaN EST CONSIDÉRÉ COMME UN float . Les docs actuellement (à partir de v0.23) spécifient la raison pour laquelle les séries entières sont converties en float:

En l'absence d'un support NA hautes performances intégré à NumPy de bas en haut, la principale victime est la capacité de représenter NA dans les tableaux de nombres entiers.

Ce compromis est fait principalement pour des raisons de mémoire et de performances, et afin que la série résultante continue d’être «numérique».

Les documents contiennent également fournir les règles pour la conversion en amont en raison de l'inclusion de NaN:

Typeclass   Promotion dtype for storing NAs
floating    no change
object      no change
integer     cast to float64
boolean     cast to object
1
jpp

Je voulais juste ajouter que si vous essayez de convertir un vecteur float (1.143) en entier (1) dont NA convertit le nouveau type de type 'Int64', vous obtiendrez une erreur. Afin de résoudre ce problème, vous devez arrondir les nombres puis faire ".astype ('Int64')"

s1 = pd.Series([1.434, 2.343, np.nan])
#without round() the next line returns an error 
s1.astype('Int64')
#cannot safely cast non-equivalent float64 to int64
##with round() it works
s1.round().astype('Int64')
0      1
1      2
2    NaN
dtype: Int64

Mon cas d'utilisation est que j'ai une série float que je veux arrondir à int, mais quand vous faites .round () il reste un '* .0' à la fin du nombre, vous pouvez donc supprimer ce 0 de la fin. conversion en int.

C’est maintenant possible, puisque pandas v 0.24.0

Notes de publication de pandas 0.24.x Citation: "Pandas est désormais capable de contenir des types entiers avec des valeurs manquantes.

0
mork