pandas isin()返回不同的结果,为eq() - 浮动dtype依赖性问题



pandas的 isin方法似乎具有dtype依赖关系(使用python 3.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

但是,当将dtype施加到 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

这是So。

的类似帖子

编辑

我了解浮点并发症。但是,从一个想将isin用作col1 == 1 | col1 == 3 | col1 == 5的便利函数的用户来看(简单地编写col1.isin([1, 3, 5])),当DTypes不同时,可能会导致未识别的错误,并且对DTYPE偏差没有任何警告。

此外,isindf.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

这绝对是不必要的行为。正如Johne指出的那样,df.eq似乎使用np.isclose,而df.isin不使用。

也许这会使它更加清楚:

>>> '%20.18f' % df[0].astype(np.float64)
'1.199999999999999956'
>>> '%20.18f' % df[0].astype(np.float32)
'1.200000047683715820'

通常,您不想看到18个小数点位置,因此Pandas会对要显示多少小数的合理选择做出合理的选择 - 但差异仍然存在,尽管看不到。因此,您需要确保将Float64与Float64和Float32与Float32进行比较。那就是我们为自己选择的浮点生活...

另外,如果您一次与一个值进行比较,则可以使用np.iscloseimport 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)
#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)

最新更新