带有NaN(缺失)值的groupby列
我有一个DataFrame的列中有许多缺less的值,我希望groupby:
import pandas as pd import numpy as np df = pd.DataFrame({'a': ['1', '2', '3'], 'b': ['4', np.NaN, '6']}) In [4]: df.groupby('b').groups Out[4]: {'4': [0], '6': [2]}
看到Pandas已经删除了NaN目标值的行。 (我想包括这些行!)
因为我需要很多这样的操作(许多cols缺less值),并且使用比中位数(通常是随机森林)更复杂的函数,所以我想避免编写太复杂的代码段。
有什么build议么? 我应该为此写一个函数还是有一个简单的解决scheme?
这在文档的缺失数据部分中提到 :
GroupBy中的NA组被自动排除。 例如,此行为与R一致。
一种解决方法是在执行groupby之前使用占位符(例如-1):
In [11]: df.fillna(-1) Out[11]: ab 0 1 4 1 2 -1 2 3 6 In [12]: df.fillna(-1).groupby('b').sum() Out[12]: a b -1 2 4 1 6 3
这就是说,这感觉非常糟糕的黑客…也许应该有一个选项,包括NaN在groupby(见这个github问题 – 它使用相同的占位符黑客)。
由于我没有足够的声望点(只有41个,但需要超过50个评论),所以我无法给M. Kiewisch添加评论。
无论如何,只是想指出,M. Kiewisch解决scheme不工作,可能需要更多的调整。 考虑一下例子
>>> df = pd.DataFrame({'a': [1, 2, 3, 5], 'b': [4, np.NaN, 6, 4]}) >>> df ab 0 1 4.0 1 2 NaN 2 3 6.0 3 5 4.0 >>> df.groupby(['b']).sum() a b 4.0 6 6.0 3 >>> df.astype(str).groupby(['b']).sum() a b 4.0 15 6.0 3 nan 2
这表明对于组b = 4.0,相应的值是15而不是6.这里只是将1和5连接起来而不是将它们作为数字加在一起。
古代的话题,如果有人仍然绊倒了这一点 – 另一个解决方法是在分组之前通过.astype(str)转换为string。 这将保存NaN的。
in:
df = pd.DataFrame({'a': ['1', '2', '3'], 'b': ['4', np.NaN, '6']})
df.astype(str).groupby(['b']).sum()
out: a b 4 1 6 3 nan 2
对安迪·海登的解决scheme的一个小点 – 它不工作(不再?),因为np.nan == np.nan
产生False
,所以replace
函数实际上并没有做任何事情。
这对我有效:
df['b'] = df['b'].apply(lambda x: x if not np.isnan(x) else -1)
(至less这是Pandas 0.19.2的行为,很抱歉把它作为一个不同的答案join,我没有足够的评价。)
虽然默认情况下在组合中没有skipnafunction,但是有一个简单而干净的方法来做到这一点:
def custom_mean(df): return df.mean(skipna=False) group.agg({"your_col_name_to_be_aggregated":custom_mean})
而已!
请注意,我没有对此进行基准testing,但我预计它比以前的答案中讨论的要快。
在文档中find答案
我已经回答了这个问题,但是有些理由把答案转换成了评论。 不过,这是最有效的解决scheme:
NaN在群体中不能包含(并传播)是相当严重的。 引用R并不令人信服,因为这种行为与许多其他事情不一致。 无论如何,虚拟黑客也是相当糟糕的。 但是,如果有NaN,则组的大小(包括NaNs)和计数(忽略NaNs)将会有所不同。
dfgrouped = df.groupby(['b']).a.agg(['sum','size','count']) dfgrouped['sum'][dfgrouped['size']!=dfgrouped['count']] = None
当这些不同时,您可以将该值设置回无为该组的聚合函数的结果。