float64 z pandami to_csv

88

Czytam plik CSV z liczbami zmiennoprzecinkowymi takimi:

Bob,0.085
Alice,0.005

Zaimportuj do ramki danych i zapisz tę ramkę danych w nowym miejscu

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

Teraz to pandasfilema:

Bob,0.085000000000000006
Alice,0.0050000000000000001

Co się stało? może muszę rzucić na inny typ jak float32 czy coś takiego?

Używam pand 0.9.0 i numpy 1.6.2 .

avances123
źródło
26
Witamy w liczbach zmiennoprzecinkowych.
Ignacio Vazquez-Abrams
1
Duplikat stackoverflow.com/questions/1778368/…
Nathan Villaescusa,
1
Stworzyłem problem, aby zbadać go bardziej szczegółowo tutaj: github.com/pydata/pandas/issues/2069 EDYCJA: Jeśli możesz, umieść samodzielną kopię problemu na stronie GitHub. Nie jestem w stanie tego odtworzyć.
Wes McKinney,

Odpowiedzi:

165

Jak wspomniano w komentarzach, jest to ogólny problem zmiennoprzecinkowy.

Możesz jednak użyć float_formatsłowa kluczowego, to_csvaby je ukryć:

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

lub, jeśli nie chcesz, aby 0.0001 zostało zaokrąglone do zera:

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

da tobie:

Bob,0.085
Alice,0.005

w pliku wyjściowym.

Aby uzyskać wyjaśnienie %g, zobacz Mini-język specyfikacji formatu .

bmu
źródło
TypeError: __init__() got an unexpected keyword argument 'float_format'
Wystąpił
Jeśli ktoś ma ten sam błąd co @ wander95, prawdopodobnie musisz zaktualizować pandasdo nowszej wersji.
driftcatcher
10

AKTUALIZACJA: Odpowiedź była dokładna w momencie pisania, a precyzja zmiennoprzecinkowa nadal nie jest czymś, co domyślnie uzyskujesz za pomocą to_csv / read_csv (kompromis między precyzją a wydajnością; domyślne wartości sprzyjają wydajności).

W dzisiejszych czasach istnieje argumentem dostępne i argumentem dostępne .float_formatpandas.DataFrame.to_csvfloat_precisionpandas.from_csv

Oryginał jest nadal wart przeczytania, aby lepiej zrozumieć problem.


To był błąd w pandach, nie tylko w funkcji „to_csv”, ale także w „read_csv”. Nie jest to ogólna kwestia zmiennoprzecinkowa, mimo że prawdą jest, że arytmetyka zmiennoprzecinkowa jest tematem wymagającym pewnej uwagi od programisty. Poniższy artykuł wyjaśnia nieco ten temat:

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

Klasyczny jednolinijkowy, który pokazuje „problem”, to ...

>>> 0.1 + 0.1 + 0.1
0.30000000000000004

... który nie wyświetla 0,3, jak można by się spodziewać. Z drugiej strony, jeśli wykonujesz obliczenia za pomocą arytmetyki stałoprzecinkowej i dopiero w ostatnim kroku zastosujesz arytmetykę zmiennoprzecinkową , będzie to działać zgodnie z oczekiwaniami. Zobacz:

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

Jeśli desperacko potrzebujesz obejść ten problem, polecam utworzenie innego pliku CSV, który zawiera wszystkie liczby jako liczby całkowite, na przykład mnożenie przez 100, 1000 lub inny współczynnik, który okazuje się wygodny. W aplikacji przeczytaj plik CSV w zwykły sposób, a odzyskasz te liczby całkowite. Następnie przekonwertuj te wartości na zmiennoprzecinkowe, dzieląc przez ten sam współczynnik, który pomnożyłeś wcześniej.

Richard Gomes
źródło