我有一个数据帧,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']
组上的累积总和。
为什么这不起作用?
编辑:我已经将示例数据框创建为字典here(太大,无法粘贴到此处)。
答案 0 :(得分:0)
您要分组的类别列之一可能对于每个观察值都是数字的或唯一的,因此不会进行分组(这就是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
您可以验证的是正确的。
答案 1 :(得分:0)
在这种情况下,我发现最干净的解决方案是
hourly_subset_df['cumsum'] = hourly_subset_df\
.groupby(['metadata.campaignName', 'daily_cap'])\
.agg({'localSpend.amount': 'cumsum'})
这使累积总和适用于每组广告系列名称/日期(小时)。在这种情况下,可能需要按日期/小时的升序对其进行排序。
我的问题是我在组中加入了date
列,因此每个组都是完全唯一的(例如@ALollz指出)。
此外,如果每天提取数据(这就是我的情况),它也可以工作。