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.
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).
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 )
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.
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.
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.
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.
_ { 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
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.