通过序列识别在pandas groupby中创建唯一ID

问题描述

我有顺序数据,其中列名反映了每行 A 到 B 点序列的值。

Segment 应该表示行程段顺序,并且只能以偶数增量出现。即,假设 Segment 0 应该代表 Segment 2 之前的一条腿,它应该在 Segment 4 之前,等等。组合起来,这些段将构成一个单向序列(出站/返回)。但是,对该字段的检查表明该字段并不总是可信的:

  • 初始行程段似乎始终为 0,但也有多个 0 段行程无法验证哪个是“真实”初始行程段的情况。
  • 有时 Segments 会跳过偶数 - 意思是,对于给定的 Personnel_IDSegments 可能是例如,如下面的玩具数据,[0,2,10,12]。立>
  • 似乎在大多数情况下,后续行程的 Segment 值都在增加,但下面的指数 14 显示一个例外。
df = pd.DataFrame({'Personnel_ID':pd.Series(['AB1234']).repeat(10),'Segment':[0,8,12,4,6],'Origin_Depart_Date': ['2020-05-16','2020-05-16','2020-05-17','2020-06-04','2020-06-04'],'Origin':['Indianapolis','Indianapolis','Zanesville','athens','Chicago','Fredericksburg','Jacksonville'],'Destination':['Zanesville','Jacksonville','Indianapolis']})
    
df2 = pd.DataFrame({'Personnel_ID':pd.Series(['BC5678']).repeat(7),'Origin_Depart_Date':['2020-05-08','2020-05-08','2020-05-19','2020-05-19'],'Seattle','athens'],'Destination':['athens','Indianapolis']})
    
df = pd.concat([df,df2])
    
df['Origin_Depart_Date'] = pd.to_datetime(df['Origin_Depart_Date'],format = '%Y-%m-%d')

目标:为数据中的每次往返创建一个唯一 ID,其中连接段之间可能存在 1 天的延迟。

理想情况下,我希望能够在每次往返中区分出境和回程。

出境旅行被定义为每 Origin 行的 DestinationPersonnel_ID 行序列,可以在 2 天内发生,其中 Origin 与 { {1}}。

回程被定义为每 Destination 行的 DestinationOrigin 行序列,可以在 2 天内发生,其中 Personnel_ID 与 { {1}}。

往返是出站和回程的配对,没有时间限制,此时DestinationOrigin是相等的。

我最初只是尝试识别出站和回程:

Origin

以上依赖于上述观察,Destination 可以被信任为旅行的第一段,然后根据按出发日期和段号排序的旅行段转发填充。

它显然没有包含任何时间窗口来关联连续几天发生的旅行(指数 14 比 1)。

def uid(x): return x['Personnel_ID'] + '_' + str(x['Segment']) + '_' + x['Origin_Depart_Date'].strftime('%Y-%m-%d') + '_' + x['Origin']

df.insert(0,'uid',(df[df['Segment']==0]).apply(lambda x: uid(x),axis=1))

df = df.sort_values(['uid','Segment'])

dupe_PIDs = df[df.duplicated(['Personnel_ID','Segment','Origin_Depart_Date'])]['Personnel_ID']
    
df = df[~df['Personnel_ID'].isin(dupe_PIDs)].reset_index()
df = df.sort_values(['Personnel_ID','Origin_Depart_Date','Segment'])
df['uid'] = df['uid'].ffill()

df.drop('level_0',axis=1).sort_values(['Personnel_ID','Segment']).to_clipboard(sep='\t')

所以我认为尝试结合日期检查0的布尔掩码可能更有效(尽管它确实带来了如何区分出站与返回的问题) :

        uid Personnel_ID    Segment Origin_Depart_Date  Origin  Destination
0   AB1234_0_2020-05-16_Indianapolis    AB1234  0   2020-05-16  Indianapolis    Zanesville
14  AB1234_0_2020-05-16_Indianapolis    AB1234  8   2020-05-16  Indianapolis    Zanesville
1   AB1234_0_2020-05-17_Zanesville  AB1234  0   2020-05-17  Zanesville  athens
6   AB1234_0_2020-05-17_Zanesville  AB1234  2   2020-05-17  athens  Chicago
15  AB1234_0_2020-05-17_Zanesville  AB1234  10  2020-05-17  Zanesville  athens
16  AB1234_0_2020-05-17_Zanesville  AB1234  12  2020-05-17  athens  Chicago
2   AB1234_0_2020-06-04_Chicago AB1234  0   2020-06-04  Chicago athens
7   AB1234_0_2020-06-04_Chicago AB1234  2   2020-06-04  athens  Fredericksburg
10  AB1234_0_2020-06-04_Chicago AB1234  4   2020-06-04  Fredericksburg  Jacksonville
12  AB1234_0_2020-06-04_Chicago AB1234  6   2020-06-04  Jacksonville    Indianapolis
3   BC5678_0_2020-05-08_Indianapolis    BC5678  0   2020-05-08  Indianapolis    athens
8   BC5678_0_2020-05-08_Indianapolis    BC5678  2   2020-05-08  athens  Seattle
4   BC5678_0_2020-05-16_Seattle BC5678  0   2020-05-16  Seattle athens
5   BC5678_0_2020-05-19_Seattle BC5678  0   2020-05-19  Seattle athens
9   BC5678_0_2020-05-19_Seattle BC5678  2   2020-05-19  athens  Indianapolis
11  BC5678_0_2020-05-19_Seattle BC5678  4   2020-05-19  Seattle athens
13  BC5678_0_2020-05-19_Seattle BC5678  6   2020-05-19  athens  Indianapolis

然而,这会丢弃 Origin==Destination,这是不受欢迎的行为。

生成往返 UID 的最佳方法是什么?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...