[英]Cumsum with groupby not working in pandas
我有一个数据hourly_subset_df
, 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)
我得到的结果只是支出列('localSpend.amount')的副本,而不是['metadata.campaignName', 'date', 'daily_cap']
唯一组之间的累积总和。
为什么这不起作用?
编辑:我已经在这里创建了示例数据框作为dict(太大而无法粘贴到此处)。
对于每个观察,您要分组的类别列之一可能是数字列,也可能是唯一列,因此不会进行分组(这就是为什么grouped.cumsum()
与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
您可以确认是正确的。
在这种情况下,我发现最干净的解决方案是
hourly_subset_df['cumsum'] = hourly_subset_df\
.groupby(['metadata.campaignName', 'daily_cap'])\
.agg({'localSpend.amount': 'cumsum'})
这使得累积总和可以用于每组广告系列名称/日期(小时)。 可能需要按照日期/小时的升序对其进行排序。
我的问题是我在组中加入了date
col,所以每个组都是完全唯一的(如@ALollz所指出的)。
另外,如果每天都提取数据(这就是我的情况),它也可以工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.