python – 写入Excel(.xlsx)时Numpy.float64发生了变化

我注意到当某些Numpy float64值保存为Excel文件(通过Pandas DataFrame)时,它们会被更改.首先我认为这与Excel中的一些不精确有关,但Excel似乎将浮点数编码为双精度,所以我对这个观察有点困惑.

>>> import numpy as np
>>> import pandas as pd

# Create a floating point number that exhibits the problem.
>>> ba = bytearray(['\x53', '\x2a', '\xb0', '\x49', '\xf3', '\x79', '\x90', '\x40'])
>>> ba
bytearray(b'S*\xb0I\xf3y\x90@')
>>> f = np.frombuffer(ba)
>>> f[0]
1054.4875857854684

# Write to dataframe to save as Excel file.
>>> df = pd.DataFrame({'a': f})
>>> df.to_excel('test.xlsx', engine='xlsxwriter')

# Read excel file (when viewing the file in LibreOffice, the 
# value isn't 1054.4875857854684 any more).
>>> df2 = pd.read_excel('test.xlsx')
>>> df2.ix[0,'a']
1054.4875857854699
>>> df2.ix[0,'a'] == f[0]
False

为什么不能从之前编写的Excel中读取相同的float64?

我还尝试使用Openpyxl(.xlsx格式)和Xlwt(.xls格式)作为引擎.虽然前者产生了与xlsxwriter相同的错误结果,但Xlwt实际上按预期工作并根据确切的变量值编写浮点数.是否有一个我错过的.xlsx格式编写器引擎的参数?

# this uses the xlwt engine
>>> df.to_excel('test.xls')
>>> df2 = pd.read_excel('test.xls')
>>> df2.ix[0,'a'] == f[0]
True

解决方法:

I also tried this with Openpyxl (.xlsx format) and Xlwt (.xls format) as engines. While the former produced the same erroneous result as xlsxwriter, Xlwt was actually working as expected and wrote the float according to the exact variable value.

区别在于.xls是二进制文件格式,IEEE 754 double的64位表示精确写入文件,可以读回相同的64位.

然而,.xlsx文件格式是zip容器中的文本XML文件的集合.因为这样的双精度被写为double的字符串表示(使用类似’%.16g’的格式)并通过将该字符串表示转换回double来读入.这实质上是双打的失败过程,因为绝大多数IEEE 754数字都没有精确的字符串表示.

例如,如果您在示例中使用numpy数字并使用不同的精度对其进行格式化,则会得到不同的表示形式:

>>> '%.16g' % f[0]
'1054.487585785468'

>>> '%.17g' % f[0]
'1054.4875857854684'

>>> '%.18g' % f[0]
'1054.48758578546835'

您还可以通过将1054.4875857854684粘贴到Excel中的单元格中来自行演示,保存文件并检查输出:

所以对于这样的文件:

python  – 写入Excel(.xlsx)时Numpy.float64发生了变化

你会得到这样的东西:

$unzip numpy.xlsx -d numpy

$xmllint --format numpy/xl/worksheets/sheet1.xml | grep 1054
        <v>1054.4875857854599</v>

当您使用Pandas读回文件时,这或多或少是您所看到的.

上一篇:python-xlwt写入excel详解


下一篇:使用xlwt’get_sheet’方法访问工作表