【问题标题】:Cumsum with groupby not working in pandas与 groupby 的 Cumsum 不在熊猫中工作
【发布时间】:2019-05-01 19:43:22
【问题描述】:

我有一个数据框,hourly_subset_df 在哪里

hourly_subset_df.columns = ['date', 'metadata.campaignName', 'localSpend.amount', 'daily_cap']

它包含不同的广告活动及其相应的一天中每小时的支出值。

我想计算每个组的累积总和,这样我就可以看到每个广告系列全天的支出变化。

我已经尝试过:

hourly_subset_df['cumsum'] = hourly_subset_df.groupby(['metadata.campaignName', 'date', 'daily_cap'])['localSpend.amount'].cumsum()

hourly_subset_df.groupby(['metadata.campaignName', 'date', 'daily_cap'])['localSpend.amount'].transform(pd.Series.cumsum)

基于我在这里找到的其他答案(thisthis)。

我得到的结果只是支出列 ('localSpend.amount') 的副本,而不是 ['metadata.campaignName', 'date', 'daily_cap'] 唯一组的累积总和。

为什么这不起作用?

编辑:我已将示例数据框创建为 dict here(太大,无法粘贴到此处)。

【问题讨论】:

  • 您能否提供一小部分数据框和您的预期输出,以便我们重现您的问题?
  • 您没有告诉我们hourly_subset_df.daily_cap 是什么,但可能是该列的值与每一行的值之间存在一对一的映射,因此df.groupby 对象不会'实际上没有分组任何东西?模拟数据会有所帮助。
  • 我的猜测是您正确计算了cumsum,但您的组不正确。您的分组列包括date,这可能是完整的日期时间,这意味着每一行基本上都属于它自己的组,因此cumsum aross 组与原始系列相同。您可能只需要提取hourly_subset_df.date.dt.date 作为分组列的日期
  • 我会尝试获取示例数据集。我相信这些组是正确的,因为我已经分别检查了 groupby 并且它看起来应该是正确的。每日上限是整数,每个日期、广告系列名称组合都相同。
  • 我第二个@ALollz。试试 hourly_subset_df.groupby(['metadata.campaignName', hourly_subset_df['date'].dt.date, 'daily_cap'])['localSpend.amount'].cumsum()

标签: python pandas pandas-groupby cumsum


【解决方案1】:

您作为分组依据的一个分类列对于每个观察可能是数字的或唯一的,因此不会进行分组(这就是为什么您的 grouped.cumsum() 给您提供与 df.cumsum() 相同的东西的原因)。例如,我们可以像您的数据一样复制正确的结果...

import numpy  as  np
import pandas  as pd 

n_rows = int(1e5)
n_cats = (24, 11, 7)
randcats = lambda ln: np.random.choice(np.arange(ln).astype(int), size=n_rows) 

cols = np.array(['date',
                 'metadata.campaignName', 
                 'localSpend.amount', 
                 'daily_cap'])
groupcols = cols[[0, 1, 3]]

x = np.random.uniform(420.0, 1100.37, size=n_rows)
hrs, camps, caps = map(randcats, n_cats)
df = pd.DataFrame(np.vstack([hrs, camps, x, caps]).T, columns=cols)
df = df.sort_values(by=cols[[1,0,-1]], kind='mergesort')
df['cum_sums'] = df.groupby(groupcols.tolist()).cumsum()
df[groupcols] = df[groupcols].astype(int)
grouped = list(df.groupby(groupcols.tolist()))

所以我们配置的数据看起来像......

      date  metadata.campaignName  localSpend.amount  daily_cap
396      0                      0             526.14          0
2502     0                      0             777.32          0
2587     0                      0             777.40          0
7198     0                      0             423.22          0

然后,您可以检查各个组的值...

In [11]: grouped[0][-1].head(4).round(2)
Out[11]:
      date  metadata.campaignName  localSpend.amount  daily_cap  cum_sums
396      0                      0             526.14          0    526.14
2502     0                      0             777.32          0   1303.46
2587     0                      0             777.40          0   2080.86
7198     0                      0             423.22          0   2504.08

In [12]: grouped[1][-1].head(4).round(2)
Out[12]:
      date  metadata.campaignName  localSpend.amount  daily_cap  cum_sums
1382     0                      0             798.77          1    798.77
1430     0                      0             682.32          1   1481.09
1990     0                      0            1083.74          1   2564.83
2870     0                      0             775.08          1   3339.91

In [13]: grouped[int(len(grouped)/2)][-1].head(4).round(2)
Out[13]:
      date  metadata.campaignName  localSpend.amount  daily_cap  cum_sums
1045    12                      0             624.18          0    624.18
3708    12                      0             657.94          0   1282.12
4890    12                      0             595.12          0   1877.23
5326    12                      0             891.11          0   2768.34

您可以验证是正确的。

【讨论】:

    【解决方案2】:

    在这种特定情况下,我发现最干净的解决方案是

    hourly_subset_df['cumsum'] = hourly_subset_df\
    .groupby(['metadata.campaignName', 'daily_cap'])\
    .agg({'localSpend.amount': 'cumsum'})
    

    这使得累积总和适用于每组广告系列名称/日期(小时)。在这种情况下,它可能需要按升序对日期/时间进行排序。

    我的问题是我将date col 包含在组中,所以每个组都是完全独特的(就像@ALollz 指出的那样)。

    此外,如果每天提取数据(这是我的情况),它也可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-05
      • 2021-07-16
      • 2019-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-23
      • 2022-12-16
      相关资源
      最近更新 更多