Pandas从多行创建链接对

时间:2017-07-28 15:18:10

标签: python python-3.x pandas dataframe sankey-diagram

我有一个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:sourcetargetvaluevalue是具有此类步骤对的id的计数。

所需的df:

    source   target   value
0   A        B        1
1   B        C        2

我知道我可以将step填入groupbycat的一行。但是,我认为这只会创建一个不同的起点而不会实际推进解决方案。令人困难的部分原因是步骤依赖于dttm保持有序,以便步骤适当配对。此外,它必须是动态的,因为可能有任何数量的步骤增加了难度。

我应该如何动态“填充”step列以获取链接数据?

有没有办法将df连接到自身以获取所有对,然后删除在连接期间创建但是无意义的行?

感谢您的任何见解!

2 个答案:

答案 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