繁体   English   中英

与groupby的求和不适用于熊猫

[英]Cumsum with groupby not working in pandas

我有一个数据hourly_subset_dfhourly_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(太大而无法粘贴到此处)。

对于每个观察,您要分组的类别列之一可能是数字列,也可能是唯一列,因此不会进行分组(这就是为什么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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM