Python / Pandas:仅在匹配列时合并连续行

时间:2017-06-05 16:43:35

标签: python pandas

我有一个大型数据集,包含在网络中传播的对象的记录。数据集存储在pandas数据集中,大致如下所示:

Obj ID | Timestamp | x | y | link ID
-------|-----------|---|---|---------
 123   |  506      |123|456|  ab12
 123   |  517      |129|436|  ab12
 123   |  519      |125|454|  cd34
 126   |  501      |123|426|  gk77
 126   |  505      |153|453|  gk77
 126   |  507      |129|856|  bj88
 126   |  508      |143|496|  bj88
 126   |  512      |125|427|  gk77
 126   |  515      |153|453|  gk77
 126   |  518      |127|256|  ab12

数据框已按Obj ID排序,属于某个对象的每个记录块已按时间排序(Timestamp字段,以秒为单位)。具有相同Obj IDlink ID的两个连续行表示该链接的对象的开始和结束。该对象最终以链接结束,该链接由出现在对象记录末尾的单个链接ID表示。

这是所需的输出。将一个对象访问的开始记录和结束记录压缩到一个记录中。对于每个对象的结束链接,只需为StartTime填写EndTime

Obj ID | StartTime | EndTime | link ID
-------|-----------|---------|---------
 123   |  506      |   517   |  ab12
 123   |  519      |   519   |  cd34
 126   |  501      |   505   |  gk77
 126   |  507      |   508   |  bj88
 126   |  512      |   515   |  gk77
 126   |  518      |   518   |  ab12

注意:

  • 无法保证对象不会两次进入同一链接。但每次访问链接都需要单独记录。

  • 由于数据集非常大,我实施的天真循环解决方案内存不足。

编辑:我编辑了数据集,以包含我在"笔记"的第一点中提到的情况。

2 个答案:

答案 0 :(得分:2)

我们试试这个:

g =(df['link ID'] != df.shift().fillna(method='bfill')['link ID']).cumsum().rename('group')

df.groupby(['Obj ID','link ID',g])['Timestamp'].agg(['min','max']).reset_index().rename(columns={'min':'StartTime','max':'EndTime'}).drop('group',axis=1)

输出:

    Obj ID link ID    StartTime      EndTime
0   123       ab12    506          517      
1   123       cd34    519          519      
2   126       ab12    518          518      
3   126       bj88    507          508      
4   126       gk77    501          505      
5   126       gk77    512          515      

答案 1 :(得分:0)

df.drop_duplicates(subset = ['Obj ID','link ID'], 
    keep='first').merge(x.drop_duplicates(subset = ['Obj ID','link ID'], 
    keep='last'), on= ['Obj ID','link ID'])