python:在时间序列内对数据进行分组

时间:2018-09-21 08:09:25

标签: python pandas pandas-groupby

给出以下数据库:

import pandas as pd
from time import strptime

data = {'num': ['B', 'A', 'B', 'A', 'B', 'A', 'B', 'C', 'B', 'A', 'C', 'B'],
        'dir': ['IN', 'IN', 'PASS', 'PASS', 'PASS', 'PASS', 'OUT', 'IN', 'IN', 'OUT', 'OUT', 'OUT'],
        'empty': [True, False, True, False, True, False, True, False, False, False, False, False],
        'station': [100, 1, 20, 20, 14, 14, 5, 65, 89, 8, 66, 11],
        'time': [strptime('20180115 00:25', '%Y%m%d %H:%M'),
                 strptime('20180115 00:30', '%Y%m%d %H:%M'),
                 strptime('20180115 01:10', '%Y%m%d %H:%M'),
                 strptime('20180115 01:10', '%Y%m%d %H:%M'),
                 strptime('20180115 02:10', '%Y%m%d %H:%M'),
                 strptime('20180115 02:10', '%Y%m%d %H:%M'),
                 strptime('20180115 03:33', '%Y%m%d %H:%M'),
                 strptime('20180115 03:33', '%Y%m%d %H:%M'),
                 strptime('20180115 03:34', '%Y%m%d %H:%M'),
                 strptime('20180115 04:10', '%Y%m%d %H:%M'),
                 strptime('20180115 04:11', '%Y%m%d %H:%M'),
                 strptime('20180115 10:10', '%Y%m%d %H:%M')]}

df = pd.DataFrame.from_dict(data)

我必须生成以下预期结果的列表:

   num  empty  station_from  station_to       time_from         time_to
0    B   True           100           5  20180115 00:25  20180115 03:33
1    A  False             1           8  20180115 00:30  20180115 04:10
2    C  False            65          66  20180115 03:33  20180115 04:11
3    B  False            89          11  20180115 03:34  20180115 10:10

说明: 那些是用数字标识每辆车(即A,B,C)的铁路车 那些可以收费或为空(列为空) dir列指示我们是否已选择或退出该特定汽车。可能还有很多其他状态(例如本例中的PASS),但我们仅对IN和OUT状态感兴趣 站列是事件发生的地方 时间栏是事件发生的时间。

我必须将每个IN和OUT对之间的数据分组(或显示每个对的轨迹),并显示活动发生的时间和地点。困难在于,这不是“正常”分组,而是一种基于时间序列的分层时间序列(同一天,一辆汽车可以装载和清空几次)。

我不知道熊猫是否是该练习的最佳结构,但数据库中有数亿条记录,性能至关重要。 (我们正在根据特定的时间范围预先选择数据)

如何达到预期效果?

1 个答案:

答案 0 :(得分:1)

1)用'IN'过滤所有行

2)为每个“ IN”找到匹配的 num empty

的第一个下一个“ OUT”
result = df[df.dir=='IN'][['num','empty','station','time']].rename({'station':'station_from','time':'time_from'},axis='columns')
result[['station_to','time_to']] = result.apply(lambda r: df[(df.index>r.name) & (df.num==r.num) & (df.empty==r.empty) & (df.dir=='OUT')][['station','time']].iloc[0,:], axis=1)

print(result)

  num  empty  station_from                           time_from  station_to  \
0   B   True           100  (2018, 1, 15, 0, 25, 0, 0, 15, -1)           5   
1   A  False             1  (2018, 1, 15, 0, 30, 0, 0, 15, -1)           8   
7   C  False            65  (2018, 1, 15, 3, 33, 0, 0, 15, -1)          66   
8   B  False            89  (2018, 1, 15, 3, 34, 0, 0, 15, -1)          11   

                               time_to  
0   (2018, 1, 15, 3, 33, 0, 0, 15, -1)  
1   (2018, 1, 15, 4, 10, 0, 0, 15, -1)  
7   (2018, 1, 15, 4, 11, 0, 0, 15, -1)  
8  (2018, 1, 15, 10, 10, 0, 0, 15, -1)