Pandas int64数据帧中浮点数的成员资格测试会产生意外结果

时间:2014-01-26 19:14:38

标签: python numpy pandas dataframe inclusion

我有一个名为“impression_data”的Pandas数据框,其中包含一个名为“site.id”的列,如下所示:

   >>> impression_data['site.id']

0      62
1     189
2     191
3      62
...

此列中的每个项目都具有数据类型numpy.int64,如下所示:

>>> for i in impression_data['site.id']:
    print type(i)

<type 'numpy.int64'>
<type 'numpy.int64'>
<type 'numpy.int64'>
...

正如预期的那样,只要我测试整数,成员资格测试就能很好地运行:

>>> 62 in impression_data['site.id']
True

但这是意想不到的结果:我的印象是np.int64列不应包含任何小数值。显然我错了。这是怎么回事?

>>> 62.5 in impression_data['site.id']
True

编辑1: 列中的所有值都应该是构造的整数。为了完整起见,我还执行了以下转换操作并且没有遇到任何错误:

impression_data['site.id'] = impression_data['site.id'].astype('int')

根据@ BremBam在评论中的建议,我试过

impression_data['site.id'].map(type).unique()

产生

[<type 'numpy.int64'>]

我正在使用的最小示例和真实数据文件就在这里 https://dl.dropboxusercontent.com/u/28347262/SE%20Pandas%20Int64%20Membership%20Testing/cm_impression.csv

在这里

https://dl.dropboxusercontent.com/u/28347262/SE%20Pandas%20Int64%20Membership%20Testing/ExampleCode.py

2 个答案:

答案 0 :(得分:1)

这是a bug in pandas。在包含测试完成之前,该值将转换为索引的类型,因此62.5将转换为62。 (请注意,系列的in会检查该值是否在索引中,而不是值。)

我相信你可以通过62.5 in impression_data.values获得你想要的东西。

答案 1 :(得分:0)

首先,系列中的成员资格测试是索引,而不是

>>> s = pd.Series([10,20,30])
>>> s
0    10
1    20
2    30
dtype: int64
>>> 0 in s
True
>>> 10 in s
False

但你是对的:

>>> 1.5 in s
True

经过一些工作,这似乎是因为__contains__中的Int64HashTable

cdef class Int64HashTable: #(HashTable):
    [...]
    def __contains__(self, object key):
        cdef khiter_t k
        k = kh_get_int64(self.table, key)
        return k != self.table.n_buckets

key以浮动形式出现,但我们有

inline khint_t kh_get_int64(kh_int64_t*, int64_t)

因此我认为在进行比较之前它会被强制转换为整数。