Python isin()返回不同的结果作为eq()-浮动数据类型依赖项问题
pandas的方法似乎具有数据类型依赖性(使用Python3.5和pandas 0.19.2)。我只是在一个相关的网站上偶然发现了这个问题,我们无法解释isin的非工作行为。以下是一个例子:Python isin()返回不同的结果作为eq()-浮动数据类型依赖项问题,python,pandas,Python,Pandas,pandas的方法似乎具有数据类型依赖性(使用Python3.5和pandas 0.19.2)。我只是在一个相关的网站上偶然发现了这个问题,我们无法解释isin的非工作行为。以下是一个例子: df = pd.DataFrame([[1.2, 0.3, 1.5, 1.4, 1.7, 4.2]]) print(df) 0 1 2 3 4 5 0 1.2 0.3 1.5 1.4 1.7 4
df = pd.DataFrame([[1.2, 0.3, 1.5, 1.4, 1.7, 4.2]])
print(df)
0 1 2 3 4 5
0 1.2 0.3 1.5 1.4 1.7 4.2
print(df.dtypes)
0 float64
1 float64
2 float64
3 float64
4 float64
5 float64
dtype: object
# everything works as expected until here
print(df.isin([1.2, 1.4]))
0 1 2 3 4 5
0 True False False True False False
但是,当数据类型被强制转换为float32
时,isin开始失败:
df = df.apply(lambda x: x.astype("float32"))
print(df.dtypes)
0 float32
1 float32
2 float32
3 float32
4 float32
5 float32
dtype: object
print(df.isin([1.2, 1.4]))
0 1 2 3 4 5
0 False False False False False False
这里有一个类似的例子
编辑
我理解浮点运算的复杂性。然而,从希望使用isin
作为col1==1 | col1==3 | col1==5
(简单地写col1.isin([1,3,5])
)的方便函数的用户的角度来看,当数据类型不同并且没有给出关于数据类型偏差的警告时,它可能会导致无法识别的错误
更重要的是,isin
与df.eq
相比返回不同的结果:
print(df.isin([1.2]))
0 1 2 3 4 5
0 False False False False False False
print(df.eq(1.2))
0 1 2 3 4 5
0 True False False False False False
这绝对是一种不受欢迎的行为。正如所指出的那样,
df.eq
似乎使用了np.isclose,而df.isin
则没有使用。
#try this:
import numpy as np
df = df.apply(lambda x: x.astype(np.float32))
test=[1.2,1.4]
test=test.apply(lambda x: x.astype(np.float32))
df.isin(test)
>>> '%20.18f' % df[0].astype(np.float64)
'1.199999999999999956'
>>> '%20.18f' % df[0].astype(np.float32)
'1.200000047683715820'
一般来说,你不希望看到18位小数,这样熊猫们就可以合理地选择显示多少位小数了——但差别仍然存在,尽管看不见。因此,您需要确保比较float64和float64,以及float32和float32。这就是我们为自己选择的浮点生活
或者,如果一次比较一个值,可以使用np.isclose
(在import numpy as np
之后)来确定近似相等:
>>> np.isclose( df.astype(np.float64), 1.2 )
array([[ True, False, False, False, False, False]], dtype=bool)
>>> np.isclose( df.astype(np.float32), 1.2 )
array([[ True, False, False, False, False, False]], dtype=bool)
(当然,您不需要使用astype()
,这只是为了证明对于float32和float64都可以得到相同的答案。)
我不知道是否有办法使isin
以类似的方式工作,因此您可能需要执行以下操作:
>>> np.isclose( df, 1.2 ) | np.isclose( df, 1.4 )
array([[ True, False, False, True, False, False]], dtype=bool)
试试这个:
打印(1.1+.1==1.2)
;-)好的,很好的例子,它似乎与isin无关,而是与浮点数的存储方式有关?尽管如此,在使用isin时,您可能会在没有注意到的情况下遇到错误的结果。这就是浮点数比较“起作用”(或不起作用)…是的。我同意@MaxU的说法,这是“正常工作”的。类似于:虽然您可能已经解决了该用户的问题,但仅使用代码的答案对将来遇到此问题的用户没有多大帮助。请编辑您的答案,解释您的代码解决原始问题的原因。