使用pandas将带时间戳的事件整理到日期范围中

时间:2013-12-09 08:52:32

标签: python datetime pandas

我有一个主数据框,其中包含批号和日期时间范围,这些批次的发生方式如下:

BatchNo             StartTime                  Event A        Event B    
BATCH23797          2013-09-06 02:22:00           0              0   
BATCH23798          2013-09-06 06:06:00           0              0   
BATCH23799          2013-09-06 14:33:00           0              0   
BATCH23800          2013-09-06 18:12:00           0              0   
BATCH23801          2013-09-06 21:38:00           0              0   

然后我对我感兴趣的事件有另外一个时间戳。我有多个这些时间戳的数据格式不同但是一天结束时我会得到一个与事件对应的dateTimes列表。我使用df.index来获取下面的时间戳列表:

DateTime                      Event A Flag                                  
2013-09-06 03:20:18                 1
2013-09-06 12:09:50                 1
2013-09-06 13:19:45                 1
2013-09-06 19:09:35                 1

我想要做的是从这个事件时间列表中。填充顶部数据框,以便计算该日期范围内发生的事件数量。每个批次的时间长度不同,我也需要考虑到这一点。所以最后顶部的数据框将如下所示:

BatchNo             StartTime                  Event A        Event B    
BATCH23797          2013-09-06 02:22:00           1              0   
BATCH23798          2013-09-06 06:06:00           2              0   
BATCH23799          2013-09-06 14:33:00           0              0   
BATCH23800          2013-09-06 18:12:00           1              0   
BATCH23801          2013-09-06 21:38:00           0              0   

对于批次,批次的完成时间是下一批次的开始时间(因此始终有批次)。

非常感谢任何帮助。

Caz没有回答我自己的问题,但这是我提出的:

在花了好几个小时试图自己这样做之后,我设法在提出问题后自己回答。

我是这样做的。对于我所做的任何改进,我们将不胜感激。

我使用下一批的开始时间创建了另一个名为Endtime的列,然后切断了

的最后一个值
df["EndTime"] = df["StartTime"].shift(-1)
df = df[:-1]

然后我使用这个函数来查找时间戳在开始和结束之间的位置,然后执行1 * bool来添加事件。我使用events.index作为事件列表,它运行良好。

def collateEvents(masterdf, eventList, columnName):
    # For each event
    for i in range(len(eventList)):
        #Get a dataframe which says where this event is true
        eventSeries = (df["StartTime"] < eventList[i]) & (df["EndTime"] > eventList[i])
        #Add one onto the columnName if the event is true
        masterdf[columnName] = masterdf[columnName] + (1 * eventSeries)

    return masterdf

1 个答案:

答案 0 :(得分:0)

我们可以假设批处理表中的StartTime已排序吗?如果是这样的话,我想你可以做到如下,如果没有,那么,先把它排序。这是一个想法,两个表是这样的:

## batch table ##
      BatchNo             StartTime
0  BATCH23797   2013-09-06 02:22:00
1  BATCH23798   2013-09-06 06:06:00
2  BATCH23799   2013-09-06 14:33:00
3  BATCH23800   2013-09-06 18:12:00
4  BATCH23801  2013-09-06 21:38:00 

## event table ##
              DateTime  Event A Flag  Event B Flag
0  2013-09-06 03:20:18             1             1
1  2013-09-06 12:09:50             1             0
2  2013-09-06 13:19:45             1             0
3  2013-09-06 19:09:35             1             1

我调用了第一个batch表和第二个event,我还为Event B flag添加了一些非零值以进行演示。第一件事是对event.DateTime上的每个batch.StartTime执行二进制搜索,以找出事件发生的批处理作业。 (从技术上讲,你可以在这里做二分搜索,但没关系。)

使用bisect模块很容易。我们首先需要在batch表中找到相应的表索引,然后找到批号:

import bisect
# a helper function to perform binary search
hit_idx = lambda x: bisect.bisect_left( batch.StartTime, x ) - 1

idx = event.DateTime.map( hit_idx )
event[ 'BatchNo' ] = map( batch.BatchNo.get, idx )

这将是输出:

              DateTime  Event A Flag  Event B Flag     BatchNo
0  2013-09-06 03:20:18             1             1  BATCH23797
1  2013-09-06 12:09:50             1             0  BATCH23798
2  2013-09-06 13:19:45             1             0  BATCH23798
3  2013-09-06 19:09:35             1             1  BATCH23800

现在,您只需按BatchNo分组并添加事件:

pv = event.groupby( 'BatchNo' )['Event A Flag', 'Event B Flag'].aggregate( sum )

输出:

            Event A Flag  Event B Flag
BatchNo                               
BATCH23797             1             1
BATCH23798             2             0
BATCH23800             1             1

现在,如果你想现在批处理BATCH23798期间发生了每种类型的事件数量 你只需在数据透视表中查找:

pv.ix[ 'BATCH23798' ]

输出:

Event A Flag    2
Event B Flag    0

为了让生活更轻松,我们可以重新索引数据透视表:

pv.reindex( batch.BatchNo ).fillna( 0 )

输出:

            Event A Flag  Event B Flag
BatchNo                               
BATCH23797             1             1
BATCH23798             2             0
BATCH23799             0             0
BATCH23800             1             1
BATCH23801             0             0