Groupby & Sum 从一个特定值的出现到另一个特定值或相同值的出现

Posted

技术标签:

【中文标题】Groupby & Sum 从一个特定值的出现到另一个特定值或相同值的出现【英文标题】:Groupby & Sum from occurance of a particular value till the occurance of another particular value or the same value 【发布时间】:2020-04-04 11:46:32 【问题描述】:

我有一个如下的数据框。 我想 groupby 'user' & 'eve' 和 sum 'Ses' 直到 100/200 和从 100 到 200。 此外,返回出现 100/200 的“名称”列的值。

如果在一百之后,没有 100 或 200(如 a & 123 或 a & 456 组中的最后一行),请忽略它。

User    eve Ses ID  Name
a   123 1   10  a
a   123 2   11  a
a   123 3   12  a
a   123 4   13  a
a   123 3   100 xyz
a   123 6   10  a
a   456 1   11  a
a   456 2   12  a
a   456 3   13  a
a   456 4   40  a
a   456 1   100 mno
a   456 14  10  a
a   456 7   20  a
a   456 8   30  a
a   456 12  200 pqr
a   456 10  10  a
b   123 1   20  a
b   123 2   30  a
b   123 3   40  a
b   123 4   50  a
b   123 1   70  a
b   123 6   100 abc
b   888 1   20  a
b   888 1   200 jkl
b   888 3   10  a
b   888 4   20  a
b   888 5   30  a
b   888 1   100 rrr
b   888 7   50  a
b   888 8   70  a

上述输入 df 的预期输出是下面的 df。

User    eve Ses Name
a   123 13  xyz
a   456 11  mno
a   456 41  pqr
b   123 17  abc
b   888 2   jkl
b   888 13  rrr

【问题讨论】:

有人否决了这个问题。那个人能解释一下为什么吗?它会帮助我提高。 我没有投反对票,但您尝试了什么? 我不知道从哪里开始。我试过df.groupby(['User','eve'],sort=False).apply(lambda x: x[x['ID'].isin([100,200]),'ses'].sum()),但我得到一个错误(这不会得到我想要的答案,但它仍然是一个开始)。 如果我这样做 df.index[(df['ID']==100) | (df['ID']==200)] 我得到了 100 和 200 所在位置的索引,谁能指导我可以使用它来获得我想要的输出? 【参考方案1】:

这是我的方法:

# valid IDs
df['valids'] = df['ID'].isin([100,200])

# mask the trailing non-hundred ids
heads = (df['ID'].where(df['valids'])
             .groupby([df['User'],df['eve']])
             .bfill().notnull()
        )
df = df[heads]

# groupby and output:
(df.groupby(['User','eve', df['valids'].shift(fill_value=0).cumsum()],
           as_index=False)
   .agg('Ses':'sum', 'Name':'last')
)

输出:

  User  eve  Ses Name
0    a  123   13  xyz
1    a  456   11  mno
2    a  456   41  pqr
3    b  123   17  abc
4    b  888    2  jkl
5    b  888   13  rrr

【讨论】:

谢谢。这有效:-)。这也快吗?在我的实际数据框中,大约有 1000 万行。谢谢。 取决于您的数据。通常几个列上的groupby 不会那么快。但这是我能想到的最优化的。 Quang,你能解释一下 bfill 是如何找到和 # 屏蔽尾随的非百个 id 的吗?这对我有帮助,我被困在那部分了。 @oppressionslayer 基本上,where 将所有非百人屏蔽为nan。然后bfill() 用后面的一百个id 填充之前的所有nan,除了尾随的nan 是的,这很有帮助,bfill 上的文档很简单(不存在),所以它肯定有助于我了解您是如何完成它的。

以上是关于Groupby & Sum 从一个特定值的出现到另一个特定值或相同值的出现的主要内容,如果未能解决你的问题,请参考以下文章

LINQ:从列表中选择项目(Group By/Select/Sum & Max!)

使用 pandas groupby 根据另一个分类列对两个分类列应用 sum & count

Pandas GroupBy 并选择特定列中具有最小值的行

SQL Sumif 函数/GROUP BY & SUM?

为啥select 子句中的字段一定要出现在Groupby子句中

使用 sum 函数从 groupby 数据框中排除日期列