Pandas聚合忽略NaN值

16

我汇总了我的Pandas数据框:data。具体而言,我想通过元组 [origintype] 来获取 amount 的平均值和总和。为了求平均值和总和,我尝试了以下 numpy 函数:

import numpy as np
import pandas as pd
result = data.groupby(groupbyvars).agg({'amount': [ pd.Series.sum, pd.Series.mean]}).reset_index() 

我的问题是amount列包含了NaN,这导致以上代码的结果有很多NaN平均值和总和。

我知道pd.Series.sumpd.Series.mean默认情况下都有skipna=True,那么为什么我在这里仍然会得到NaN

我也尝试了这个方法,显然没有起作用:

data.groupby(groupbyvars).agg({'amount': [ pd.Series.sum(skipna=True), pd.Series.mean(skipna=True)]}).reset_index() 

编辑:根据@Korem的建议,我也尝试使用了下面的 partial

s_na_mean = partial(pd.Series.mean, skipna = True)    
data.groupby(groupbyvars).agg({'amount': [ np.nansum, s_na_mean ]}).reset_index() 

但是会收到以下错误:

error: 'functools.partial' object has no attribute '__name__'

1
你能发布一些示例数据吗?另外,刚开始时,不要使用 pd.Series.sum,而是使用 'sum' - 代码应该采用更快的路径。 - chrisb
谢谢,我决定使用pd.Series.sum,因为它有一个skipna选项。阅读@Korem的答案后,我现在使用np.nansum。但是我的numpy版本(1.7.1)中没有np.nanmean。我将尝试发布代表性数据,这可能需要一些时间。 - Zhubarb
2个回答

17

使用 NumPy 的 nansumnanmean 函数:

from numpy import nansum
from numpy import nanmean
data.groupby(groupbyvars).agg({'amount': [ nansum, nanmean]}).reset_index() 

对于较旧版本的numpy的解决方法,也是修复您上次尝试的方法:

当你执行pd.Series.sum(skipna=True)时,你实际上调用了该方法。如果你想这样使用它,你需要定义一个partial。所以如果你没有nanmean,让我们定义s_na_mean并使用它:

from functools import partial
s_na_mean = partial(pd.Series.mean, skipna = True)

谢谢,我使用的是numpy-1.7.1-py2.7-win32.egg,它不支持nanmean,会报错:'module' object has no attribute 'nanmean'。(我刚刚查了一下,nanmean 是在版本1.8.0中新增的)。 - Zhubarb
但是np.nansum似乎也在1.8.0版本中添加了。奇怪的是,我对此没有得到相同的错误... - Zhubarb
谢谢Korem,我尝试了这个方法但是没有成功,我编辑了我的问题并提供了错误信息。另外,skipna=True不是默认情况下适用于pd.Series.mean吗? - Zhubarb
@Zhubarb 它默认是开启的,这意味着你看到的问题不在你认为的地方。 - Korem
你是正确的,我尝试了这个:data.groupby(groupbyvars).agg({'amount': [ np.nansum, lambda x: pd.Series.mean(x,skipna=True)]}).reset_index() ,但仍然得到 NaN。我会进一步调查。也许那些情况下我只有NaN值。 - Zhubarb
1
pandas文档:“skipna:布尔值,默认为True”,“排除NA / null值。如果整个行/列都是NA,则结果将为NA”。 - user3226167

3
可能已经晚了,但对其他人可能仍有用处。
尝试使用apply函数:
import numpy as np
import pandas as pd

def nan_agg(x):
    res = {}

    res['nansum'] = x.loc[ not x['amount'].isnull(), :]['amount'].sum()
    res['nanmean'] = x.loc[ not x['amount'].isnull(), :]['amount'].mean()

    return pd.Series(res, index=['nansum', 'nanmean'])

result = data.groupby(groupbyvars).apply(nan_agg).reset_index() 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接