2014-05-08 2 views
1

Je voudrais demander des conseils sur les mesures correctives pour un problème que j'ai remarqué dans la routine pandas.read_csv. Quand je stocke un long entier dans un fichier en utilisant pd.to_csv, il stocke les données correctement - mais quand je le relis en utilisant pd.read_csv, il dérange avec les 3 derniers chiffres. Lorsque j'essaie de le sauvegarder à nouveau en utilisant to_csv (sans aucune modification), les numéros du fichier CSV résultant sont différents du fichier CSV d'origine. J'ai illustré le problème ci-dessous (remarquez comment 4321113141090630389 devient 4321113141090630400 et devient 4321583677327450765 4321583677327450880):problème de troncature avec pd.read_csv

fichier CSV original créé par pd.to_csv:

grep -e 321583677327450 -e 321113141090630 orig.piece 
orig.piece:1,1;0;0;0;1;1;3844;3844;3844;1;1;1;1;1;1;0;0;1;1;0;0,,,4321583677327450765 
orig.piece:5,1;0;0;0;1;1;843;843;843;1;1;1;1;1;1;0;0;1;1;0;0,64.0,;,4321113141090630389 

import pandas as pd 
import numpy as np 

orig = pd.read_csv('orig.piece') 
orig.dtypes 
Unnamed: 0 int64 
aa object 
act float64 
... 
... 
s_act float64 
dtype: object 

>orig['s_act'].head(6) 
0 NaN 
1 4.321584e+18 
2 4.321974e+18 
3 4.321494e+18 
4 4.321283e+18 
5 4.321113e+18 
Name: s_act, dtype: float64 

>orig['s_act'].fillna(0).astype(int).head(6) 
0 0 
1 4321583677327450880 
2 4321973950881710336 
3 4321493786516159488 
4 4321282586859217408 
5 4321113141090630400 

>orig.to_csv('convert.piece') 

grep -e 321583677327450 -e 321113141090630 orig.piece convert.piece 
orig.piece:1,1;0;0;0;1;1;3844;3844;3844;1;1;1;1;1;1;0;0;1;1;0;0,,,4321583677327450765 
orig.piece:5,1;0;0;0;1;1;843;843;843;1;1;1;1;1;1;0;0;1;1;0;0,64.0,;,4321113141090630389 
convert.piece:1,1;0;0;0;1;1;3844;3844;3844;1;1;1;1;1;1;0;0;1;1;0;0,,,4.321583677327451e+18 
convert.piece:5,1;0;0;0;1;1;843;843;843;1;1;1;1;1;1;0;0;1;1;0;0,64.0,;,4.3211131410906304e+18 

pourriez-vous s'il vous plaît me aider à comprendre pourquoi le dernier read_csv brouille trois chiffres? Ce n'est même pas un problème d'arrondi, les chiffres sont totalement différents (comme 4321583677327450765 devient 4321583677327450880 ci-dessus) Est-ce à cause de la notation scientifique qui vient à l'esprit - comment pouvons-nous le désactiver et laisser les pandas traiter ces données comme des objets? nombre entier/flottant?

+0

BTW, quand je dis orig = pd.read_csv ('orig.piece', DTYPE = str) ', le problème disparaît. Mais, y a-t-il un inconvénient à cela? aussi, cela ressemble à une solution de contournement et non une solution. – user3615154

Répondre

3

C'est une erreur en virgule flottante. Parce que la colonne s_act a une valeur manquante (pandas n'a pas de valeurs manquantes entières), il lit s_act avec dtype = float (les types sont définis au niveau de la colonne dans pandas). Donc, vous voyez essentiellement les éléments suivants:

>>> x = 4321113141090630389 
>>> float(x) 
4.32111314109063e+18 
>>> int(float(x)) 
4321113141090630144 

En termes d'une solution, vous pouvez changer le DTYPE de s_act à une chaîne quand vous lisez dans (le DTYPE résultant sera ojet). Pour, par exemple:

data = """ 
id,val,x 
1,4321113141090630389,4 
2,,5 
3,200,4 
""" 

df = pd.read_csv(StringIO(data),header=True,dtype={'val':str}) 
print df 

    id     val x 
0 1 4321113141090630389 4 
1 2     NaN 5 
2 3     200 4 

print df.info() 

<class 'pandas.core.frame.DataFrame'> 
Int64Index: 3 entries, 0 to 2 
Data columns (total 3 columns): 
id  3 non-null int64 
val 2 non-null object 
x  3 non-null int64 

df['val'] = df['val'].fillna(0).astype(int) 
print df 

    id     val x 
0 1 4321113141090630389 4 
1 2     0 5 
2 3     200 4