float64 com pandas to_csv

88

Estou lendo um CSV com números flutuantes como este:

Bob,0.085
Alice,0.005

E importe para um dataframe e grave este dataframe em um novo lugar

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

Agora isso pandasfiletem:

Bob,0.085000000000000006
Alice,0.0050000000000000001

O que acontece? talvez eu tenha que lançar para um tipo diferente, como float32 ou algo assim?

Estou usando o pandas 0.9.0 e o numpy 1.6.2 .

avances123
fonte
26
Bem-vindo aos números de ponto flutuante.
Ignacio Vazquez-Abrams
1
Duplicado de stackoverflow.com/questions/1778368/…
Nathan Villaescusa
1
Criei um problema para examinar um pouco mais detalhadamente aqui: github.com/pydata/pandas/issues/2069 EDITAR: Se puder, coloque uma reprodução independente do problema no problema do GitHub. Não consigo reproduzi-lo.
Wes McKinney

Respostas:

165

Conforme mencionado nos comentários, é um problema geral de ponto flutuante.

No entanto, você pode usar a float_formatpalavra-chave de to_csvpara ocultá-lo:

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

ou, se você não quiser que 0,0001 seja arredondado para zero:

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

Darei à você:

Bob,0.085
Alice,0.005

em seu arquivo de saída.

Para obter uma explicação %g, consulte Minilinguagem de especificação de formato .

bmu
fonte
Recebi um erroTypeError: __init__() got an unexpected keyword argument 'float_format'
wander95
Se alguém tiver o mesmo erro que @ wander95, provavelmente você precisará atualizar pandaspara uma versão mais recente.
driftcatcher
10

ATUALIZAÇÃO: a resposta estava correta no momento da escrita, e a precisão do ponto flutuante ainda não é algo que você obtém por padrão com to_csv / read_csv (compensação precisão-desempenho; padrões favorecem o desempenho).

Hoje em dia existe o float_formatargumento disponível parapandas.DataFrame.to_csv e o float_precisionargumento disponível parapandas.from_csv .

Vale a pena ler o original para entender melhor o problema.


Era um bug no pandas, não só na função "to_csv", mas também no "read_csv". Não é um problema geral de ponto flutuante, apesar de ser verdade que a aritmética de ponto flutuante é um assunto que exige alguns cuidados do programador. O artigo abaixo esclarece um pouco esse assunto:

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

Um clássico que mostra o "problema" é ...

>>> 0.1 + 0.1 + 0.1
0.30000000000000004

... que não exibe 0,3 como seria de esperar. Por outro lado, se você lidar com o cálculo usando aritmética de ponto fixo e apenas na última etapa empregar aritmética de ponto flutuante , funcionará como você espera. Veja isso:

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

Se você precisa desesperadamente de contornar este problema, recomendo que você crie outro arquivo CSV que contenha todas as figuras como inteiros, por exemplo, multiplicando por 100, 1000 ou outro fator que seja conveniente. Dentro de seu aplicativo, leia o arquivo CSV normalmente e você receberá de volta os números inteiros. Em seguida, converta esses valores em ponto flutuante, dividindo pelo mesmo fator que você multiplicou antes.

Richard gomes
fonte