如何按时间段对DataFrame进行分组?

68

我有一些来自日志文件的数据,希望能按分钟分组:

 def gen(date, count=10):
     while count > 0:
         yield date, "event{}".format(randint(1,9)), "source{}".format(randint(1,3))
         count -= 1
         date += DateOffset(seconds=randint(40))

 df = DataFrame.from_records(list(gen(datetime(2012,1,1,12, 30))), index='Time', columns=['Time', 'Event', 'Source'])

df:

 Event  Source
 2012-01-01 12:30:00     event3  source1
 2012-01-01 12:30:12     event2  source2
 2012-01-01 12:30:12     event2  source2
 2012-01-01 12:30:29     event6  source1
 2012-01-01 12:30:38     event1  source1
 2012-01-01 12:31:05     event4  source2
 2012-01-01 12:31:38     event4  source1
 2012-01-01 12:31:44     event5  source1
 2012-01-01 12:31:48     event5  source2
 2012-01-01 12:32:23     event6  source1

我尝试了以下选项:

  1. df.resample('Min') 这个选项过于高级,需要进行聚合。
  2. df.groupby(date_range(datetime(2012,1,1,12, 30), freq='Min', periods=4)) 出现异常。
  3. df.groupby(TimeGrouper(freq='Min')) 可以正常工作,并返回一个 DataFrameGroupBy 对象以供进一步处理,例如:

    grouped = df.groupby(TimeGrouper(freq='Min'))
    grouped.Source.value_counts()
    2012-01-01 12:30:00  source1    1
    2012-01-01 12:31:00  source2    2
                         source1    2
    2012-01-01 12:32:00  source2    2
                         source1    2
    2012-01-01 12:33:00  source1    1
    

然而TimeGrouper类并没有被记录在文档中。

正确的按时间段分组方式是什么?我怎样才能将数据按分钟和来源列进行分组,例如groupby([TimeGrouper(freq='Min'), df.Source])

3个回答

67

您可以根据与DataFrame相同长度的任何数组/系列进行分组,甚至可以是未实际作为DataFrame列的计算因子。因此,要按分钟分组,可以执行以下操作:

df.groupby(df.index.map(lambda t: t.minute))

如果您想按分钟和其他内容分组,只需将上述内容与您想要使用的列混合即可:
df.groupby([df.index.map(lambda t: t.minute), 'Source'])

个人而言,如果我经常需要按照这些计算出来的东西(例如,“分钟”列)进行分组,我会发现将列添加到DataFrame中很有用,因为它可以使分组代码更简洁。

或者你可以尝试像这样:

df.groupby([df['Source'],pd.TimeGrouper(freq='Min')])

5
谢谢。我通过这个语句得到了我想要的结果:df.groupby([df.index.map(lambda t: datetime(t.year, t.month, t.day, t.hour, t.minute)), df.Source, df.Event]).size().unstack(level=2) - serguei
2
我该如何将其延长至30分钟? - igauravsehrawat
11
这个pd.TimeGrouper可以用来按时间单位的倍数进行分组,例如df.groupby(pd.TimeGrouper(freq='30Min')) - salomonvh
我想按天分组数据,但我的一天在凌晨2点结束,而不是晚上12点。应该如何实现这个? - Andi Anderle
4
TimeGrouper自Pandas 21版本开始被弃用(https://pandas.pydata.org/pandas-docs/stable/whatsnew/v0.21.0.html#deprecations) - 在这里,pdGrouper是否可以作为替代? - Mr_and_Mrs_D
显示剩余3条评论

28

由于原答案比较旧,而且pandas引入了periods,现在有了不同的解决方案:

df.groupby(df.index.to_period('T'))

此外,您可以进行重新采样。 (点击此处查看详细信息)
df.resample('T')

19

pd.TimeGrouper现在已经过时。这里是使用pd.Grouper的v1.05更新。

df['Date'] = df.index

df.groupby(['Source',pd.Grouper(key = 'Date', freq='30min')])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接