对分组的熊猫数据框中的行求和并返回 NaN

Posted

技术标签:

【中文标题】对分组的熊猫数据框中的行求和并返回 NaN【英文标题】:Summing rows in grouped pandas dataframe and return NaN 【发布时间】:2017-08-03 20:42:18 【问题描述】:

示例

import pandas as pd
import numpy as np
d = 'l':  ['left', 'right', 'left', 'right', 'left', 'right'],
     'r': ['right', 'left', 'right', 'left', 'right', 'left'],
     'v': [-1, 1, -1, 1, -1, np.nan]
df = pd.DataFrame(d)

问题

当分组数据帧包含 np.NaN 的值时,我希望分组总和为 NaN,正如 pd.Series.sumpd.DataFrame.sumskipna=False 标志所给出的那样,但是,这个

In [235]: df.v.sum(skipna=False)
Out[235]: nan

但是,此行为并未反映在 pandas.DataFrame.groupby 对象中

In [237]: df.groupby('l')['v'].sum()['right']
Out[237]: 2.0

并且不能通过直接应用np.sum 方法来强制

In [238]: df.groupby('l')['v'].apply(np.sum)['right']
Out[238]: 2.0

解决方法

我可以通过这样做来解决这个问题

check_cols = ['v']
df['flag'] = df[check_cols].isnull().any(axis=1)
df.groupby('l')['v', 'flag'].apply(np.sum).apply(
    lambda x: x if not x.flag else np.nan,
    axis=1
)

但这很难看。有没有更好的方法?

【问题讨论】:

【参考方案1】:

我认为这是熊猫固有的。解决方法可以是:

df.groupby('l')['v'].apply(array).apply(sum)

模仿 numpy 的方式,

df.groupby('l')['v'].apply(pd.Series.sum,skipna=False) # for series, or
df.groupby('l')['v'].apply(pd.DataFrame.sum,skipna=False) # for dataframes.

调用好函数。

【讨论】:

值得添加的是,对于多列(即 DataFrame),方法更改为 .apply(pd.DataFrame.sum, skipna=False) 重采样此工作:df['my_column'].resample('1h').apply(pd.Series.sum, skipna=False)【参考方案2】:

我不确定这属于丑陋程度,但它有效:

>>> series_sum = pd.core.series.Series.sum
>>> df.groupby('l')['v'].agg(series_sum, skipna=False)
l
left     -3
right   NaN
Name: v, dtype: float64

我刚刚挖出了你取df.v.sum时使用的sum方法,它支持skipna选项:

>>> help(df.v.sum)
Help on method sum in module pandas.core.generic:

sum(axis=None, skipna=None, level=None, numeric_only=None, **kwargs) method 
of pandas.core.series.Series instance

【讨论】:

【参考方案3】:

这是你想要的吗?

In [24]: df.groupby('l')['v'].agg(lambda x: np.nan if x.isnull().any() else x.sum())
Out[24]:
l
left    -3.0
right    NaN
Name: v, dtype: float64

In [22]: df.groupby('l')['v'].agg(lambda x: x.sum() if x.notnull().all() else np.nan)
Out[22]:
l
left    -3.0
right    NaN
Name: v, dtype: float64

【讨论】:

【参考方案4】:
df.groupby(xxx).yyy.apply(lambda x: x.sum(skipna=False))

【讨论】:

以上是关于对分组的熊猫数据框中的行求和并返回 NaN的主要内容,如果未能解决你的问题,请参考以下文章

Python - 在熊猫数据框中对列表中的行进行分组

熊猫应用函数将多个值返回到熊猫数据框中的行

根据 pandas 中的字典对数据帧的行进行分组并对相应的分子求和

我如何在熊猫中分组然后对值求和? [复制]

对数据框中的一列求和并将结果返回为 int

忽略熊猫 groupby 组中的 NaN 的标准错误