144 votes

float64 avec pandas to_csv

Je lis un CSV avec des nombres flottants comme ceci :

Bob,0.085
Alice,0.005

Et importer dans un cadre de données, et écrire ce cadre de données à un nouvel endroit.

df = pd.read_csv(orig)
df.to_csv(pandasfile)

Maintenant, ceci pandasfile a :

Bob,0.085000000000000006
Alice,0.0050000000000000001

Qu'est-ce qui se passe ? Peut-être que je dois faire un cast vers un type différent comme float32 ou autre ?

J'utilise pandas 0.9.0 y numpy 1.6.2 .

251voto

bmu Points 7109

Comme mentionné dans les commentaires, il s'agit d'un problème général de virgule flottante.

Cependant, vous pouvez utiliser le float_format mot clé de to_csv pour le cacher :

df.to_csv('pandasfile.csv', float_format='%.3f')

ou, si vous ne voulez pas que 0,0001 soit arrondi à zéro :

df.to_csv('pandasfile.csv', float_format='%g')

vous donnera :

Bob,0.085
Alice,0.005

dans votre fichier de sortie.

Pour une explication de %g voir Mini-langage de spécification de format .

19voto

Richard Gomes Points 1386

UPDATE : La réponse était exacte au moment de l'écriture, et la précision des virgules flottantes n'est toujours pas obtenue par défaut avec to_csv/read_csv (compromis précision-performance ; les valeurs par défaut favorisent les performances).

De nos jours, il y a le site float_format argument disponible pour pandas.DataFrame.to_csv y le site float_precision argument disponible pour pandas.from_csv .

L'original vaut tout de même la peine d'être lu pour mieux cerner le problème.


Il s'agit d'un bug dans pandas, non seulement dans la fonction "to_csv", mais aussi dans "read_csv". Il ne s'agit pas d'un problème général de virgule flottante, même s'il est vrai que la fonction arithmétique à virgule flottante est un sujet qui exige une certaine attention de la part du programmeur. L'article ci-dessous clarifie un peu ce sujet :

http://docs.python.org/2/tutorial/floatingpoint.html

Une phrase classique qui montre que le "problème" est ...

>>> 0.1 + 0.1 + 0.1
0.30000000000000004

... qui n'affiche pas 0,3 comme on pourrait s'y attendre. D'un autre côté, si vous effectuez le calcul en utilisant arithmétique à virgule fixe et seulement dans la dernière étape vous employez arithmétique à virgule flottante il fonctionnera comme vous le souhaitez. Regardez ça :

>>> (1 + 1 + 1)  * 1.0 / 10
0.3

Si vous avez désespérément besoin de contourner ce problème, je vous recommande de créer un autre fichier CSV qui contient tous les chiffres sous forme d'entiers, par exemple en les multipliant par 100, 1000 ou tout autre facteur qui s'avère pratique. Dans votre application, lisez le fichier CSV comme d'habitude et vous obtiendrez ces chiffres entiers en retour. Ensuite, convertissez ces valeurs en virgule flottante, en les divisant par le même facteur que vous avez multiplié auparavant.

5voto

Lafo_R Points 1

J'ai rencontré ce problème et voici la solution que j'ai trouvée. (J'ai essayé l'autre solution, mais elle n'a pas fonctionné correctement).

Tout d'abord, essayez d'arrondir aux décimales souhaitées, puis exportez au format csv.

Essayez simplement ce qui suit :

df = df.astype(float).round(3)
df.to_csv('pandasfile.csv')

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X