熊猫系列中的NaN.tolist()的行为与列表中的NaN不同



为什么

>> import pandas as pd
>> import numpy as np
>> list(pd.Series([np.nan, np.nan, 2, np.nan, 2])) == [np.nan, np.nan, 2, np.nan, 2]

是否返回False?我用pd.Series([np.nan, np.nan, 2, np.nan, 2]).tolist()得到了同样的结果。我试图通过以下函数,按对象(所以基本上是熊猫系列(计算熊猫中最常见的元素

def get_most_common(srs):
"""
Returns the most common value in a list. For ties, it returns whatever
value collections.Counter.most_common(1) gives.
"""
from collections import Counter
x = list(srs)
my_counter = Counter(x)
most_common_value = my_counter.most_common(1)[0][0]
return most_common_value

并且刚刚意识到,即使我有一个步骤CCD_ 3,我也会得到多个NaN的错误计数。

编辑:只是为了澄清为什么这对我来说是一个问题:

>>> from collections import Counter
>>> Counter(pd.Series([np.nan, np.nan, np.nan, 2, 2, 1, 5]).tolist())
Counter({nan: 1, nan: 1, nan: 1, 2.0: 2, 1.0: 1, 5.0: 1}) # each nan is counted differently
>>> Counter([np.nan, np.nan, np.nan, 2, 2, 1, 5])
Counter({nan: 3, 2: 2, 1: 1, 5: 1}) # nan count of 3 is correct

正如@emilaz已经指出的,根本问题是在所有情况下都是nan != nan。然而,在你的观察中,物体参考才是最重要的。

观察listpd.Series之间的以下对象引用:

>>> s = pd.Series([np.nan, np.nan, np.nan, 2, 2, 1, 5])
>>> s.apply(id)
0    149706480
1    202463472
2    202462336
3    149706912
4    149706288
5    149708784
6    149707200
dtype: int64
>>> l = [np.nan, np.nan, np.nan, 2, 2, 1, 5]
>>> list(map(id, l))
[68634768, 68634768, 68634768, 1389126848, 1389126848, 1389126832, 1389126896]

np.nan对象与list中导入的np.nan对象共享相同的引用,而为每个Series创建一个新的引用(这对于pandas的使用是有意义的(。

因此,答案不是以这种方式比较CCD_ 12。pandas有自己的方法来处理nan,所以根据你的实际活动,可能有一个比你想象的简单得多的答案(例如df.groupby('some col').count()(。

在python中,等于nan总是返回False。因此,预期会出现以下行为:

import numpy as np
np.nan == np.nan
>>>> False

这就是为什么您的列表比较返回False的原因。

一个可能的解决方法是:

import pandas as pd
import numpy as np
foo= list(pd.Series([np.nan, np.nan, 2, np.nan, 2]))
bar= [np.nan, np.nan, 2, np.nan, 2]
np.allclose(foo,bar, equal_nan=True)
>>>> True

这可能会引起您的兴趣:比较包含NaN的numpy数组。

为了找到最常见的元素,我建议使用panda和value_counts()方法:

pd.Series([np.nan, np.nan, 2, np.nan, 2]).value_counts()
>>>> 2.0  2

如果你关心nan计数,你可以简单地将dropna=False传递给方法:

pd.Series([np.nan, np.nan, 2, np.nan, 2]).value_counts()
>>>> NaN  3
2.0  2