如何使用Python / Pandas从Date字段按月分组

时间:2017-07-04 14:19:52

标签: python pandas pandas-groupby

我有一个数据帧df,如下所示:

| date      | Revenue |
|-----------|---------|
| 6/2/2017  | 100     |
| 5/23/2017 | 200     |
| 5/20/2017 | 300     |
| 6/22/2017 | 400     |
| 6/21/2017 | 500     |

我需要按月对上述数据进行分组,以获得输出:

| date | SUM(Revenue) |
|------|--------------|
| May  | 500          |
| June | 1000         |

我尝试了这段代码但是没有用:

df.groupby(month('date')).agg({'Revenue': 'sum'})

我想只使用Pandas或Numpy而不使用其他库

6 个答案:

答案 0 :(得分:23)

试试这个:

In [6]: df['date'] = pd.to_datetime(df['date'])

In [7]: df
Out[7]: 
        date  Revenue
0 2017-06-02      100
1 2017-05-23      200
2 2017-05-20      300
3 2017-06-22      400
4 2017-06-21      500



In [59]: df.groupby(df['date'].dt.strftime('%B'))['Revenue'].sum().sort_values()
Out[59]: 
date
May      500
June    1000

答案 1 :(得分:12)

使用pandas Grouper尝试群组:

df = pd.DataFrame({'date':['6/2/2017','5/23/2017','5/20/2017','6/22/2017','6/21/2017'],'Revenue':[100,200,300,400,500]})
df.date = pd.to_datetime(df.date)
dg = df.groupby(pd.Grouper(key='date', freq='1M')).sum() # groupby each 1 month
dg.index = dg.index.strftime('%B')

     Revenue
 May    500
June    1000

答案 2 :(得分:2)

对于具有许多行的DataFrame,使用strftime会占用更多时间。如果日期列已经具有datetime64[ns]的dtype(可以使用pd.to_datetime()进行转换,或者在csv导入期间指定parse_dates等),则可以直接访问{{1}的datetime属性}标签(方法3)。加速非常快。

groupby

方法1:strftime

import numpy as np
import pandas as pd

T = pd.date_range(pd.Timestamp(0), pd.Timestamp.now()).to_frame(index=False)
T = pd.concat([T for i in range(1,10)])
T['revenue'] = pd.Series(np.random.randint(1000, size=T.shape[0]))
T.columns.values[0] = 'date'

print(T.shape) #(159336, 2)
print(T.dtypes) #date: datetime64[ns], revenue: int32

每个循环1.47 s±10.1毫秒(平均±标准偏差,共运行7次,每个循环10个循环)

方法2:石斑鱼

%timeit -n 10 -r 7 T.groupby(T['date'].dt.strftime('%B'))['revenue'].sum()

每个循环56.9 ms±2.88 ms(平均±标准偏差,共运行7次,每个循环10个)

方法3:日期时间属性

%timeit -n 10 -r 7 T.groupby(pd.Grouper(key='date', freq='1M')).sum()
#NOTE Manually map months as integer {01..12} to strings

每个循环34毫秒±3.34毫秒(平均±标准偏差,共运行7次,每个循环10个循环)

答案 3 :(得分:0)

这会更好。

尝试一下:

#explicitly convert to date
df['Date'] = pd.to_datetime(df['Date'])
# set your date column as index 
df.set_index('Date',inplace=True) 

# For monthly use 'M', If needed for other freq you can change.
df[revenue].resample('M').sum()

此代码给出的结果与第一篇文章中的@shivsn答案相同。

但是,在上述代码中我们可以做更多的操作。 建议使用此:

>>> df['Date'] = pd.to_datetime(df['Date'])
>>> df.set_index('Date',inplace=True)
>>> df['withdrawal'].resample('M').sum().sort_values()
Date
2019-10-31     28710.00
2019-04-30     31437.00
2019-07-31     39728.00
2019-11-30     40121.00
2019-05-31     46495.00
2020-02-29     57751.10
2019-12-31     72469.13
2020-01-31     76115.78
2019-06-30     76947.00
2019-09-30     79847.04
2020-03-31     97920.18
2019-08-31    205279.45
Name: withdrawal, dtype: float64

@shivsn代码的作用相同。

>>> df.groupby(df['Date'].dt.strftime('%B'))['withdrawal'].sum().sort_values()
Date
October       28710.00
April         31437.00
July          39728.00
November      40121.00
May           46495.00
February      57751.10
December      72469.13
January       76115.78
June          76947.00
September     79847.04
March         97920.18
August       205279.45
Name: withdrawal, dtype: float64

答案 4 :(得分:0)

尝试一下:

  1. 将日期列绑定到datetime formate中。

    ---> df['Date'] = pd.to_datetime(df['Date'])

  2. 在数据框中插入具有类似于-> [May,'June']

    的月份的新行

    ---> df['months'] = df['date'].apply(lambda x:x.strftime('%B'))

    --->这里的x是从数据框中的date列获取的日期。

  3. 现在在“月”列上汇总汇总数据并汇总收入。

    ---> response_data_frame = df.groupby('months')['Revenue'].sum()

    ----> print(response_data_frame)

输出-:

| month | Revenue |

|-------|---------|

| May   | 500     |

| June  | 1000    |

答案 5 :(得分:0)

df['Month'] = pd.DatetimeIndex(df['date']).month_name()

使用这个你应该得到

<头>
日期 收入
6/2/2017 100 六月
5/23/2017 200 五月
5/20/2017 300 五月
6/22/2017 400 六月
6/21/2017 500 六月