计算groupby对象经过的时间

时间:2015-08-21 10:59:48

标签: python python-2.7 pandas time-series

我有一些时间序列数据,我希望按类别分开,并在二进制值== 1时进一步分开。我想计算二进制值== 1时每天所经过的时间。

以下是原始数据样本:

                       category  binary
utctime                                               
2014-10-23 13:15:08           a   0
2014-10-24 16:09:13           b   0
2014-10-24 18:56:01           a   1
2014-10-24 21:42:42           a   1
2014-10-25 00:29:22           a   0
2014-10-25 03:16:02           c   1
2014-10-25 06:02:43           c   1
2014-10-25 08:49:23           c   0
2014-10-25 11:36:03           c   1
2014-10-25 14:22:43           c   1
2014-10-25 17:09:24           d   0
2014-10-25 19:56:05           b   0
2014-10-25 22:42:45           b   0
2014-10-26 01:29:26           e   0
2014-10-26 04:16:15           d   0
2014-10-26 07:02:56           e   1
2014-10-26 09:49:36           e   1
2014-10-26 12:36:16           e   0
2014-10-26 15:22:57           e   0
2014-10-26 18:09:46           d   0
2014-10-26 20:56:26           b   0
2014-10-26 23:43:07           e   0

我开始过滤二进制列,然后按类别分组,但我丢失了日期索引。如果我按index.date(或pd.date_grouper)分组,我不知道如何分组到单独的类别。

感觉数据可能处于特别无益的状态,但我不知道如何让它变得更好 - 我尝试了一个以类别为列的数据透视表,但由于utctimes是类别所特有的,没有工作。我应该把utctime从索引中删除吗?

所需的输出类似于以下内容:

category a   
date              total time binary == 1
2014-10-23          10 minutes
2014-10-24          5 minutes

category b   
date              total time binary == 1
2014-10-23          1 minutes
2014-10-24          15 minutes

2 个答案:

答案 0 :(得分:2)

要按类别和索引日期分组,您可以使用

date = df2.index.date
grouped = df2.groupby(['category', date])

请注意,groupby可以接受包含字符串和数组的列表。该 string指的是列名,而数组则充当虚拟的代理 柱。 date不是df2的列,但您可以按其分组。很酷,嗯?

要查找每个组中的总分钟数,您可以使用lambda函数(例如

)进行聚合
lambda x: (x.index[-1]-x.index[0])/pd.Timedelta(1, 'm')

(x.index[-1]-x.index[0])计算每个组中第一个和最后一个时间戳之间的差异。请注意,这假定索引按排序顺序排列。 差异(x.index[-1]-x.index[0])会返回pd.Timedelta。 除以pd.Timedelta(1, 'm')将返回总分钟数。

请注意,使用g.last()-g.first()的{​​{3}}对于大型DataFrame可能要快得多,因为它在一个向量化操作中计算所有Timedeltas,而不是为每个Timedelta计算一个lambda函数调用行。

import numpy as np
import pandas as pd

df = pd.DataFrame(
    [['2014-10-23 13:15:08', 'a', 999.9, 0],
     ['2014-10-24 16:09:13', 'b', 24.1, 0],
     ['2014-10-24 18:56:01', 'a', 23.3, 1],
     ['2014-10-24 21:42:42', 'a', 23.0, 1],
     ['2014-10-25 00:29:22', 'a', 22.7, 0],
     ['2014-10-25 03:16:02', 'c', 23.1, 1],
     ['2014-10-25 06:02:43', 'c', 22.8, 1],
     ['2014-10-25 08:49:23', 'c', 23.7, 1],
     ['2014-10-25 11:36:03', 'c', 24.8, 0],
     ['2014-10-25 14:22:43', 'c', 25.7, 0],
     ['2014-10-25 17:09:24', 'd', 24.9, 0],
     ['2014-10-25 19:56:05', 'b', 24.6, 0],
     ['2014-10-25 22:42:45', 'b', 24.2, 0],
     ['2014-10-26 01:29:26', 'e', 22.7, 0],
     ['2014-10-26 04:16:15', 'd', 23.6, 0],
     ['2014-10-26 07:02:56', 'e', 22.4, 1],
     ['2014-10-26 09:49:36', 'e', 22.7, 1],
     ['2014-10-26 12:36:16', 'e', 22.2, 0],
     ['2014-10-26 15:22:57', 'e', 23.1, 0],
     ['2014-10-26 18:09:46', 'd', 23.8, 0],
     ['2014-10-26 20:56:26', 'b', 23.8, 0],
     ['2014-10-26 23:43:07', 'e', 22.7, 0]], 
    columns=['utctime', 'category', 'temp', 'binary'])
df = df.set_index('utctime')
df.index = pd.DatetimeIndex(df.index)
df2 = df.loc[df['binary']==1]
date = df2.index.date
grouped = df2.groupby(['category', date])
result = grouped['binary'].agg(
    lambda x: (x.index[-1]-x.index[0])/pd.Timedelta(1, 'm'))
print(result)

产量

category            
a         2014-10-24    166.683333
c         2014-10-25    333.350000
e         2014-10-26    166.666667
Name: binary, dtype: float64

答案 1 :(得分:2)

使用@unutbu数据&设置

添加一个我们想要差异的额外列

app.controller('navigationCtrl', function ($scope, $stateParams, $location, $state) {

稍微更通用的分组方式

In [31]: df2['ts'] = df2.index

In [32]: df2
Out[32]: 
                    category  temp  binary                  ts
2014-10-24 18:56:01        a  23.3       1 2014-10-24 18:56:01
2014-10-24 21:42:42        a  23.0       1 2014-10-24 21:42:42
2014-10-25 03:16:02        c  23.1       1 2014-10-25 03:16:02
2014-10-25 06:02:43        c  22.8       1 2014-10-25 06:02:43
2014-10-25 08:49:23        c  23.7       1 2014-10-25 08:49:23
2014-10-26 07:02:56        e  22.4       1 2014-10-26 07:02:56
2014-10-26 09:49:36        e  22.7       1 2014-10-26 09:49:36

虽然是YMMV,但性能会更高。

In [33]: g = df2.groupby(['category',pd.Grouper(freq='D',level=0)])