首页 > 解决方案 > 使用 groupby-specific 过滤条件进行 groupby 后的 pandas 过滤?

问题描述

我已经看到了许多“在 groupby 之后过滤”的出色解决方案,其中过滤条件是固定的(“嘿,按名称分组,然后查找 21 岁以上的每个人”,其中 21 是固定的。我是寻找一种基于 groupby 的结果进行过滤的方法。

例子:

df = pd.DataFrame({'person':['Sue', 'Sue', 'Sue', 'Bill', 'Alfonso'],
               'date': ['2019-01-01','2019-01-02', '2019-01-03','2019-02-01', '2019-03-01'],
               'my_value': [5,10,20,10,5],
               'my_other_value': [3,2,9,6,8]})

我希望能够按照以下方式提出一个问题:“从一个人第一次的 my_value 为 10 开始,告诉我所有连续记录的 my_other_value 的平均值”。

在示例中,Sue 具有 my_value == 10 的第一个日期是 2019-01-02,因此她对 my_other_value 的均值是 (2+9)/2 = 5.5,它来自 2019-01-02 和 2019- 01-03。比尔只有一个条目,但它的 my_value 确实为 10,因此他的 my_other_value 平均值为 6。可悲的是,阿方索的 my_value 从未为 10,因此他甚至没有被包括在最终计数中

所以,我开始

df2 = df.query('my_value == 10').groupby('person').first().reset_index()

这让我第一次有一个人的 my_value 为 10。由此我知道这个人和它发生的日期。所以用英语,我现在想为那个人过滤这些结果,这样我就可以做一个 .mean() 但只包括那个人的行 >= 我从调用 first() 中学到的日期。当然,我被困住了。

我有点希望这样的事情会起作用:

df3 = df.groupby('person').apply( lambda x: x['date'] >= df2['date']).mean()

但我知道这不能真正起作用,因为 lambda 怎么知道将 df.groupby() 中的正确人与 df2 分组中的同一人匹配?

另一种选择是想“嘿,也许有一个版本的扩展()可以从第一条记录以外的东西开始”

我的手指交叉着上面的方法之一是方向正确的,一些英雄出现说“哦,你是如此接近,只需添加这个额外的小部分!”

标签: pandaspandas-groupby

解决方案


“哦,你这么近,就加上这个小额外部分!”

请参阅下面的额外部分。

df = pd.DataFrame({'person':['Sue', 'Sue', 'Sue', 'Bill', 'Alfonso'],
               'date': ['2019-01-01','2019-01-02', '2019-01-03','2019-02-01', '2019-03-01'],
               'my_value': [5,10,20,10,5],
               'my_other_value': [3,2,9,6,8]})
df = df.sort_values(['person', 'date']).reset_index(drop=True)

>>> df

    person  date        my_value    my_other_value
0   Alfonso 2019-03-01  5           8
1   Bill    2019-02-01  10          6
2   Sue     2019-01-01  5           3
3   Sue     2019-01-02  10          2
4   Sue     2019-01-03  20          9

查找第一个日期 my_value == 10

df2 = df.query('my_value == 10').groupby('person').first()['date'].reset_index()
df2 = df2.rename(columns={'date': 'first_date'})
>>> df2

    person  first_date
0   Bill    2019-02-01
1   Sue     2019-01-02

合并数据框

df_merged = pd.merge(df, df2, how='left', on=['person'])
>>> df_merged

    person  date        my_value    my_other_value  first_date
0   Alfonso 2019-03-01  5           8               NaN
1   Bill    2019-02-01  10          6               2019-02-01
2   Sue     2019-01-01  5           3               2019-01-02
3   Sue     2019-01-02  10          2               2019-01-02
4   Sue     2019-01-03  20          9               2019-01-02

计算平均值 my_other_value

grouped = df_merged[df_merged['date'] >= df_merged['first_date']].groupby('person')
>>> grouped['my_other_value'].mean()

person
Bill    6.0
Sue     5.5
Name: my_other_value, dtype: float64

推荐阅读