我知道使用==
进行浮动通常是不安全的。但它是否适用于以下情况?
==
检查数据是否与上半场的所有位置匹配。这些都是用熊猫完成的。 A.csv中的列具有datetime,string和float类型。显然==
适用于datetime和string,所以如果==
适用于float,在这种情况下,它可以节省大量的工作。
它似乎适用于我的所有测试,但我能否认为它会一直有效?
答案 0 :(得分:3)
当通过相同的解析例程时,相同的字符串表示将成为相同的浮点表示。当对值执行数学运算或使用高精度表示时,会出现浮点不准确问题,但是低精度值的相等性无需担心。
答案 1 :(得分:3)
不,你不能认为这会一直有效。
要使其工作,您需要知道Pandas在写入CSV文件时写出的文本值在读回时(再次使用Pandas)恢复完全相同的值。但默认情况下,Pandas read_csv
函数牺牲了速度的准确性,因此解析操作不会自动恢复相同的浮动。
为了演示这一点,请尝试以下操作:我们将创建一些随机值,将它们写入CSV文件,然后使用Pandas将其读回。首先是必要的进口:
>>> import pandas as pd
>>> import numpy as np
现在创建一些随机值,并将它们放入Pandas Series
对象中:
>>> test_values = np.random.rand(10000)
>>> s = pd.Series(test_values, name='test_values')
现在我们使用to_csv
方法将这些值写入文件,然后将该文件的内容读回DataFrame
:
>>> s.to_csv('test.csv', header=True)
>>> df = pd.read_csv('test.csv')
最后,让我们从df
的相关列中提取值并进行比较。我们将对==
操作的结果求和,以找出确切恢复了多少10000
个输入值。
>>> sum(test_values == df['test_values'])
7808
因此大约78%的值被正确恢复;其他人则没有。
此行为被认为是Pandas的一个功能,而不是一个bug。但是,有一种解决方法:Pandas 0.15为CSV阅读器添加了一个新的float_precision
参数。通过向float_precision='round_trip'
操作提供read_csv
,Pandas使用更慢但更准确的解析器。试试上面的例子,我们得到了完美的恢复值:
>>> df = pd.read_csv('test.csv', float_precision='round_trip')
>>> sum(test_values == df['test_values'])
10000
这是第二个例子,朝另一个方向发展。前面的例子表明,写入然后读取不会返回相同的数据。此示例显示读取和写入也不保留数据。设置与您在问题中描述的设置非常匹配。首先,我们将创建A.csv
,这次使用常规值而不是随机值:
>>> import pandas as pd, numpy as np
>>> s = pd.Series(np.arange(10**4) / 1e3, name='test_values')
>>> s.to_csv('A.csv', header=True)
现在我们阅读A.csv
,并将数据的前半部分再次写回B.csv
,与第1步一样。
>>> recovered_s = pd.read_csv('A.csv').test_values
>>> recovered_s[:5000].to_csv('B.csv', header=True)
然后我们同时阅读A.csv
和B.csv
,并将A
的前半部分与B
进行比较,与第2步一样。
>>> a = pd.read_csv('A.csv').test_values
>>> b = pd.read_csv('B.csv').test_values
>>> (a[:5000] == b).all()
False
>>> (a[:5000] == b).sum()
4251
因此,有几个值无法正确比较。打开文件,A.csv
看起来就像我期望的那样。以下是A.csv
中的前15个条目:
,test_values
0,0.0
1,0.001
2,0.002
3,0.003
4,0.004
5,0.005
6,0.006
7,0.007
8,0.008
9,0.009
10,0.01
11,0.011
12,0.012
13,0.013
14,0.014
15,0.015
以下是B.csv
中的相应条目:
,test_values
0,0.0
1,0.001
2,0.002
3,0.003
4,0.004
5,0.005
6,0.006
7,0.006999999999999999
8,0.008
9,0.009000000000000001
10,0.01
11,0.011000000000000001
12,0.012
13,0.013000000000000001
14,0.013999999999999999
15,0.015
有关将float_precision
关键字引入read_csv
的更多信息,请参阅此bug report。