Pandas groupby 一天中的时间到字典

Posted

技术标签:

【中文标题】Pandas groupby 一天中的时间到字典【英文标题】:Pandas groupby hour of the day to dictionary 【发布时间】:2017-06-19 06:40:22 【问题描述】:

我有一个pandas 数据框如下:

date                | Item   | count
------------------------------------
2016-12-06 10:45:08 |  Item1 |  60
2016-12-06 10:45:08 |  Item2 |  145
2016-12-06 09:45:00 |  Item1 |  60
2016-12-06 09:44:54 |  Item3 |  600
2016-12-06 09:44:48 |  Item4 |  15
2016-12-06 11:45:08 |  Item1 |  60
2016-12-06 10:45:08 |  Item2 |  14
2016-11-06 09:45:00 |  Item1 |  62
2016-11-06 09:44:54 |  Item3 |  6
2016-11-06 09:44:48 |  Item4 |  15

我正在尝试按一天中的某个小时(或一天的晚些时候)对项目进行分组,以了解以下统计信息: 每天售出的物品清单,例如:

2016-12-06,从09:00:0010:00:00,商品1、商品3 和商品4 已售出;等等。 在 2016-12-06,商品 1、商品 2、商品 3、商品 4(独特商品)已售出。

虽然我离获取这些统计数据还很遥远,但我仍然坚持按时间分组。 最初,print df.dtypes 显示

date    object
Item    object
count   int64
dtype: object

所以,我使用以下代码行将日期列转换为 pandas 日期对象。

df['date'] = pd.to_datetime(df['date'])

现在,print df.dtypes 产生:

date    datetime64[ns]
Item    object
count   int64
dtype: object

但是,当我尝试通过执行以下代码行使用TimeGrouperdate 列进行分组时

from pandas.tseries.resample import TimeGrouper 
print df.groupby([df['date'],pd.TimeGrouper(freq='Min')])

我收到以下TypeError。根据here 或here 给出的建议,使用 pd.to_datetime 进行转换应该可以解决此问题。

TypeError: Only valid with DatetimeIndex, TimedeltaIndex or PeriodIndex, but got an instance of 'RangeIndex'

我不知道如何解决此问题以继续查找我正在寻找的统计信息。任何有关解决此错误和使用 TimeGrouper 以字典格式(或任何更有意义的格式)查找统计信息的提示将不胜感激。

【问题讨论】:

【参考方案1】:

您可以通过numpy array 使用groupby - 删除minutesseconds 的日期时间:

print (df['date'].values.astype('<M8[h]'))
['2016-12-06T10' '2016-12-06T10' '2016-12-06T09' '2016-12-06T09'
 '2016-12-06T09' '2016-12-06T11' '2016-12-06T10' '2016-11-06T09'
 '2016-11-06T09' '2016-11-06T09']

print (df.groupby(df['date'].values.astype('<M8[h]')).Item.unique())
2016-11-06 09:00:00    [Item1, Item3, Item4]
2016-12-06 09:00:00    [Item1, Item3, Item4]
2016-12-06 10:00:00           [Item1, Item2]
2016-12-06 11:00:00                  [Item1]
Name: Item, dtype: object

print (df.groupby(df['date'].values.astype('<M8[h]')).Item
         .apply(lambda x: x.unique().tolist()).to_dict())
Timestamp('2016-11-06 09:00:00'): ['Item1', 'Item3', 'Item4'], 
 Timestamp('2016-12-06 09:00:00'): ['Item1', 'Item3', 'Item4'], 
 Timestamp('2016-12-06 10:00:00'): ['Item1', 'Item2'], 
 Timestamp('2016-12-06 11:00:00'): ['Item1']

print (df.groupby(df['date'].values.astype('<M8[D]')).Item
         .apply(lambda x: x.unique().tolist()).to_dict())
Timestamp('2016-11-06 00:00:00'): ['Item1', 'Item3', 'Item4'], 
 Timestamp('2016-12-06 00:00:00'): ['Item1', 'Item2', 'Item3', 'Item4']

感谢Jeff的建议使用round

print (df.groupby(df['date'].dt.round('h')).Item
         .apply(lambda x: x.unique().tolist()).to_dict())

Timestamp('2016-11-06 10:00:00'): ['Item1', 'Item3', 'Item4'], 
 Timestamp('2016-12-06 12:00:00'): ['Item1'], 
 Timestamp('2016-12-06 10:00:00'): ['Item1', 'Item3', 'Item4'], 
 Timestamp('2016-12-06 11:00:00'): ['Item1', 'Item2']

print (df.groupby(df['date'].dt.round('d')).Item
         .apply(lambda x: x.unique().tolist()).to_dict())
Timestamp('2016-11-06 00:00:00'): ['Item1', 'Item3', 'Item4'], 
 Timestamp('2016-12-06 00:00:00'): ['Item1', 'Item2', 'Item3', 'Item4']

【讨论】:

顺便说一句,我真的很喜欢。以后我会记住的。 更习惯使用 .round('min') .dt.round('min') 这是访问器上的一个方法【参考方案2】:
sold = df.set_index('date').Item.resample('H').agg('Sold': 'unique')
sold[sold.Sold.str.len() > 0]

                                      Sold
date                                      
2016-11-06 09:00:00  [Item4, Item3, Item1]
2016-12-06 09:00:00  [Item4, Item3, Item1]
2016-12-06 10:00:00         [Item1, Item2]
2016-12-06 11:00:00                [Item1]

【讨论】:

以上是关于Pandas groupby 一天中的时间到字典的主要内容,如果未能解决你的问题,请参考以下文章

python pandas 按一天中的小时求和

在 pandas 中以更快的方式分组一天中的时间

Pandas - Python 2.7:如何将时间序列索引转换为一天中的秒数?

使用 pandas 的滚动窗口计算一天中每个时间的平均值

如何更改 seaborn 直方图以在一天中的几个小时内工作?

查找一天中事件的开始时间和结束时间 - Pandas 时间序列 - 这样结束时间不会落入第二天