我有一个df,id
作为流ID,dttm
作为step
修改时间,step
作为流程中的步骤。它目前由dttm
订购。特定id
可以有任意数量的步骤。
当前df:
id dttm step
0 81 2015-05-26 07:56:03 A
1 81 2015-05-26 08:19:07 B
2 81 2015-05-26 08:32:05 C
3 91 2015-05-26 08:07:12 B
4 91 2015-05-26 08:07:12 C
我想创建链接数据以提供给Sankey。因此,我最终想要一个包含三列的df:source
,target
和value
。 value
是具有此类步骤对的id
的计数。
所需的df:
source target value
0 A B 1
1 B C 2
我知道我可以将step
填入groupby
或cat
的一行。但是,我认为这只会创建一个不同的起点而不会实际推进解决方案。令人困难的部分原因是步骤依赖于dttm
保持有序,以便步骤适当配对。此外,它必须是动态的,因为可能有任何数量的步骤增加了难度。
我应该如何动态“填充”step
列以获取链接数据?
有没有办法将df连接到自身以获取所有对,然后删除在连接期间创建但是无意义的行?
感谢您的任何见解!
答案 0 :(得分:2)
我找到了解决方案。这不像斯科特那样是一步到位的解决方案,但我认为理解起来有点简单。而且,它运行得更快,更快:
为每组id
添加一个序列。然后复制df以允许自我合并:
df['sequence'] = df.groupby('id').cumcount()
df2 = df
合并id
上的数据框,然后根据顺序保留有意义的行:
result = df.merge(df2, on='eoawthread_id', how='left')
result = result[result['sequence_x']+1==result['sequence_y']]
按步骤对生成的df进行分组,并使用size
获取value
。然后重置索引并重命名列:
result = pd.DataFrame(result.groupby(['step_x','step_y']).size().rename('value'))
result = result.reset_index()
result.columns = ['source','target','value']
答案 1 :(得分:1)
让我们试试:
(df.groupby('id')['step'].apply(lambda x: pd.DataFrame(list(zip(x, x[1:]))).set_index([0,1]).assign(count=1))
.rename_axis(['id','source','target'])
.sum(level=[1,2]).reset_index())
输出:
source target count
0 A B 1
1 B C 2