Pandas 从多行创建 Link 对

Pandas Create Link Pairs from Multiple Rows

我有一个 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

我想创建 link 数据以输入 Sankey。因此,我最终想要一个包含三列的 df:sourcetargetvaluevalueid 具有这样一个步骤对的计数。

期望的 df:

    source   target   value
0   A        B        1
1   B        C        2

我知道我可以用 groupbycatstep 塞进一行。但是,我认为这只会创建一个不同的起点,而不会真正推进解决方案。造成困难的部分原因是这些步骤取决于 dttm 以保持顺序,以便这些步骤适当配对。此外,它必须是动态的,因为可能有任意数量的步骤,这增加了难度。

我应该如何动态地 "stuff" step 列来获得 link 数据?

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

感谢您的所有见解!

让我们试试:

(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

我找到了解决办法。它不是像 Scott 那样的一步解决方案,但我认为它更容易理解。而且,它运行得非常非常快:

为每组 id 添加一个序列。然后复制 df 以允许自合并:

df['sequence'] = df.groupby('id').cumcount()
df2 = df

合并 id 上的数据帧,然后仅保留基于序列有意义的行:

result = df.merge(df2, on='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']