Python - 按月分组日期

Eri*_*Red 4 python datetime python-itertools

这是一个快速的问题,我起初认为这很容易.一个小时,我不太确定!
所以,我有一个Python datetime对象列表,我想绘制它们.x值是年和月,y值是此列表中本月发生的日期对象的数量.
也许一个例子会更好地证明这一点(dd/mm/yyyy):

[28/02/2018, 01/03/2018, 16/03/2018, 17/05/2018] 
-> ([02/2018, 03/2018, 04/2018, 05/2018], [1, 2, 0, 1])
Run Code Online (Sandbox Code Playgroud)

我的第一次尝试尝试按日期和年份分组,方法如下:

import itertools
group = itertools.groupby(dates, lambda date: date.strftime("%b/%Y"))
graph = zip(*[(k, len(list(v)) for k, v in group]) # format the data for graphing
Run Code Online (Sandbox Code Playgroud)

正如您可能已经注意到的那样,这只会按列表中已存在的日期进行分组.在我上面的例子中,4月份没有发生日期的事实会被忽视.

接下来,我尝试查找开始日期和结束日期,并在它们之间循环:

import datetime
data = [[], [],]
for year in range(min_date.year, max_date.year):
    for month in range(min_date.month, max_date.month):
        k = datetime.datetime(year=year, month=month, day=1).strftime("%b/%Y")
        v = sum([1 for date in dates if date.strftime("%b/%Y") == k])
        data[0].append(k)
        data[1].append(v)
Run Code Online (Sandbox Code Playgroud)

当然,这只有在min_date.month小于max_date.month的情况下才有效,如果它们跨越多年则不一定如此.而且,它非常难看.

这样做有一种优雅的方式吗?
提前致谢

编辑:要清楚,日期是datetime对象,而不是字符串.为了便于阅读,它们在这里看起来像字符串.

jez*_*ael 5

我建议使用pandas:

import pandas as pd

dates = ['28/02/2018', '01/03/2018', '16/03/2018', '17/05/2018'] 

s = pd.to_datetime(pd.Series(dates), format='%d/%m/%Y')
s.index = s.dt.to_period('m')
s = s.groupby(level=0).size()

s = s.reindex(pd.period_range(s.index.min(), s.index.max(), freq='m'), fill_value=0)
print (s)
2018-02    1
2018-03    2
2018-04    0
2018-05    1
Freq: M, dtype: int64

s.plot.bar()
Run Code Online (Sandbox Code Playgroud)

图形

说明:

  1. 首先Seriesdates 列表和转换to_datetimes 创建.
  2. 创建PeriodIndexSeries.dt.to_period
  3. groupby通过index(level=0)得到计数GroupBy.size
  4. 通过添加缺少的周期Series.reindexPeriodIndex马克斯和指数的最小值创建
  5. 最后的情节,例如酒吧 - Series.plot.bar