在python/pandas中先按用户ID分组再按月分组每日数据

7 投票
2 回答
6869 浏览
提问于 2025-04-18 00:44

我在一个Pandas数据框中有下面这个表格:

date                 user_id  whole_cost  cost1             
02/10/2012 00:00:00        1       1790      12         
07/10/2012 00:00:00        1        364      15         
30/01/2013 00:00:00        1        280      10         
02/02/2013 00:00:00        1        259      24         
05/03/2013 00:00:00        1        201      39         
02/10/2012 00:00:00        3        623       1          
07/12/2012 00:00:00        3         90       0          
30/01/2013 00:00:00        3        312      90         
02/02/2013 00:00:00        5        359      45         
05/03/2013 00:00:00        5        301      34         
02/02/2013 00:00:00        5        359       1          
05/03/2013 00:00:00        5        801      12         
..

这个表格是通过以下查询从一个csv文件中提取出来的:

import pandas as pd

newnames = ['date','user_id', 'whole_cost', 'cost1']
df = pd.read_csv('expenses.csv', names = newnames, index_col = 'date')

我需要分析我的用户的资料,为此:

我想把每个用户(他们有成千上万)按月份分组,计算每个月的查询总费用,也就是说,如果user_id=1在2012年10月2日的总费用是1790,10月7日的总费用是364,那么在新表中应该有一条记录显示在2012年10月31日的总费用为2154(这是整个月的费用)。在转换后的表中,所有的日期都将是每个月的最后一天,代表与之相关的整个月份。

2 个回答

3

由于timegrouper这个功能要被淘汰了,你可以用Grouper来替代它,这样就能得到相同的结果。

df.groupby(['user_id', pd.Grouper(key='date', freq='M')]).agg({'whole_cost':sum})

df.groupby(['user_id', df['date'].dt.dayofweek]).agg({'whole_cost':sum})
9

在0.14版本中,你可以同时按月份和另一个列进行分组:

In [11]: df
Out[11]:
            user_id  whole_cost  cost1
2012-10-02        1        1790     12
2012-10-07        1         364     15
2013-01-30        1         280     10
2013-02-02        1         259     24
2013-03-05        1         201     39
2012-10-02        3         623      1
2012-12-07        3          90      0
2013-01-30        3         312     90
2013-02-02        5         359     45
2013-03-05        5         301     34
2013-02-02        5         359      1
2013-03-05        5         801     12

In [12]: df1 = df.sort_index()  # requires sorted DatetimeIndex

In [13]: df1.groupby([pd.TimeGrouper(freq='M'), 'user_id'])['whole_cost'].sum()
Out[13]:
            user_id
2012-10-31  1          2154
            3           623
2012-12-31  3            90
2013-01-31  1           280
            3           312
2013-02-28  1           259
            5           718
2013-03-31  1           201
            5          1102
Name: whole_cost, dtype: int64

在0.14之前,我觉得你只能做两个分组操作:

In [14]: g = df.groupby('user_id')['whole_cost']

In [15]: g.resample('M', how='sum').dropna()
Out[15]:
user_id
1        2012-10-31    2154
         2013-01-31     280
         2013-02-28     259
         2013-03-31     201
3        2012-10-31     623
         2012-12-31      90
         2013-01-31     312
5        2013-02-28     718
         2013-03-31    1102
dtype: float64

撰写回答