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:source
、target
和 value
。 value
是 id
具有这样一个步骤对的计数。
期望的 df:
source target value
0 A B 1
1 B C 2
我知道我可以用 groupby
或 cat
将 step
塞进一行。但是,我认为这只会创建一个不同的起点,而不会真正推进解决方案。造成困难的部分原因是这些步骤取决于 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']
我有一个 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:source
、target
和 value
。 value
是 id
具有这样一个步骤对的计数。
期望的 df:
source target value
0 A B 1
1 B C 2
我知道我可以用 groupby
或 cat
将 step
塞进一行。但是,我认为这只会创建一个不同的起点,而不会真正推进解决方案。造成困难的部分原因是这些步骤取决于 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']