Python isin()返回不同的结果作为eq()-浮动数据类型依赖项问题

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

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.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的说法,这是“正常工作”的。类似于:虽然您可能已经解决了该用户的问题,但仅使用代码的答案对将来遇到此问题的用户没有多大帮助。请编辑您的答案,解释您的代码解决原始问题的原因。