pandas dataframe groupby datetime month

ato*_*3ls 68 python datetime pandas pandas-groupby

考虑一个csv文件:

string,date,number
a string,2/5/11 9:16am,1.0
a string,3/5/11 10:44pm,2.0
a string,4/22/11 12:07pm,3.0
a string,4/22/11 12:10pm,4.0
a string,4/29/11 11:59am,1.0
a string,5/2/11 1:41pm,2.0
a string,5/2/11 2:02pm,3.0
a string,5/2/11 2:56pm,4.0
a string,5/2/11 3:00pm,5.0
a string,5/2/14 3:02pm,6.0
a string,5/2/14 3:18pm,7.0
Run Code Online (Sandbox Code Playgroud)

我可以阅读此内容,并将日期列重新格式化为datetime格式:

b=pd.read_csv('b.dat')
b['date']=pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')
Run Code Online (Sandbox Code Playgroud)

我一直试图按月对数据进行分组.似乎应该有一种明显的方式来访问月份和分组.但我似乎无法做到这一点.有谁知道怎么样?

我目前正在尝试的是按日期重新编制索引:

b.index=b['date']
Run Code Online (Sandbox Code Playgroud)

我可以这样访问这个月:

b.index.month
Run Code Online (Sandbox Code Playgroud)

但是,我似乎无法找到一个按月累计的功能.

ato*_*3ls 129

管理这样做:

b=pd.read_csv('b.dat')
b.groupby(by=[b.index.month, b.index.year])
Run Code Online (Sandbox Code Playgroud)

要么

b.groupby(pd.Grouper(freq='M'))  # update for v0.21+
Run Code Online (Sandbox Code Playgroud)

  • 我认为更多的pandonic方法是使用`resample`(当它提供你需要的功能时)或使用`TimeGrouper`:`df.groupby(pd.TimeGrouper(freq ='M'))` (46认同)
  • 得到结果DataFrame总和或平均值,`df.groupby(pd.TimeGrouper(freq ='M')).sum()`或`df.groupby(pd.TimeGrouper(freq ='M')).mean( )` (6认同)
  • 不建议使用pd.TimeGrouper,而建议使用pd.Grouper,它虽然灵活一些,但仍使用freq和level参数。 (3认同)

Pan*_*cks 52

(更新:2018年)

请注意,pd.Timegrouper折旧并将被删除.改为使用:

 df.groupby(pd.Grouper(freq='M'))
Run Code Online (Sandbox Code Playgroud)

  • 阅读2018年:) (9认同)
  • 我发现使用“key”避免重新索引 df 很有用,如下所示: df.groupby(pd.Grouper(key='your_date_column', freq='M')) (5认同)
  • 找到 Grouper 文档[此处](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Grouper.html?highlight=grouper) 和频率规范 (`freq=...` )[此处](https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases)。一些例子是“freq=D”代表**天**,“freq=B”代表**工作日**,“freq=W”代表**周**,甚至“freq=Q”代表**季度**。 (2认同)
  • 加快那些想要按特定列(或更多列)分组的人的进一步研究: df.groupby(['col1', pd.Grouper(key='date_col', freq='1M')]).agg({ 'col2': '总和', 'col3': '最大值' }) (2认同)

tsa*_*ndo 8

@jpp 的替代解决方案,但输出一个YearMonth字符串:

df['YearMonth'] = pd.to_datetime(df['Date']).apply(lambda x: '{year}-{month}'.format(year=x.year, month=x.month))

res = df.groupby('YearMonth')['Values'].sum()
Run Code Online (Sandbox Code Playgroud)


Myk*_*tko 6

要分组时间序列数据,您可以使用该方法resample。例如,按月分组:

df.resample(rule='M', on='date')['Values'].sum()
Run Code Online (Sandbox Code Playgroud)

您可以在此处找到带有偏移别名的列表。

  • 谢谢!这应该是公认的答案:按时间“groupby”称为“resample”。 (3认同)

jpp*_*jpp 5

一种避免MultiIndex的解决方案是创建一个新的datetime列设置日=1。然后按此列分组。下面的琐碎示例。

df = pd.DataFrame({'Date': pd.to_datetime(['2017-10-05', '2017-10-20']),
                   'Values': [5, 10]})

# normalize day to beginning of month
df['YearMonth'] = df['Date'] + pd.offsets.MonthBegin(1)

# two alternative methods
df['YearMonth'] = df['Date'] - pd.to_timedelta(df['Date'].dt.day-1, unit='D')
df['YearMonth'] = df['Date'].map(lambda dt: dt.replace(day=1))

g = df.groupby('YearMonth')

res = g['Values'].sum()

# YearMonth
# 2017-10-01    15
# Name: Values, dtype: int64
Run Code Online (Sandbox Code Playgroud)

与之不同pd.Grouper,此解决方案的微妙好处是,将grouper索引标准化为每个月的开始而不是每个月的结束,因此您可以通过get_group以下方式轻松提取组:

some_group = g.get_group('2017-10-01')
Run Code Online (Sandbox Code Playgroud)

计算十月的最后一天比较麻烦。pd.Grouper从v0.23开始,确实支持convention参数,但这仅适用于PeriodIndex石斑鱼。