为网络图重组 pandas 数据框

Restructure pandas dataframe for Network Graph

我正在构建一个 pandas 数据框来制作网络图。我的数据框目前看起来像这样:

Group1 Group2 Group3 Asset
A      A      A      MI
A      A      A      JI
A      A      A      MI
A      A      A      JI
A      A      A      MI
A      A      B      MI
A      A      C      MI
A      A      C      PA
A      A      C      MI
A      A      C      PA
A      A      C      MI
A      A      C      PA
A      A      C      MI
A      A      C      PA
A      A      C      MI

我想将其操作成如下所示:

Source Target Weight
MI     JI     1
MI     MI     1
MI     PA     1
JI     MI     1
PA     MI     1

基本上,对于第 1、2 和 3 组的每个唯一配对,我想将资产列分成 2 列,每个可能的组合。配对的第一部分将构成源列和第二列配对的一部分将构成目标列。对于这个最小的示例,只有第 3 组有所不同。权重列表示单个资产的总配对总和。

有人可以帮我指明正确的方向吗?如有任何帮助,我们将不胜感激!

下面是一些生成 df 的示例代码:

df = pd.DataFrame({'Group1': ['A','A','A','A', 'A','A','A', 'A','A','A', 'A','A','A', 'A','A'],
                   'Group2': ['A','A','A','A', 'A','A','A', 'A','A','A', 'A','A','A', 'A','A'],
                   'Group3': ['A','A','A','A','A','B','C','C','C','C','C','C','C','C','C'],
                   'Asset': ['MI','JI','MI','JI','MI','MI','MI','PA','MI','PA','MI','PA','MI','PA','MI']
                   
                   })

您可以迭代数据的转置视图:

from collections import defaultdict
d, v = [*zip(*[df[i] for i in df])], []
for i in range(len(d)-1):
   if (k:=(d[i][-1], d[i+1][-1])) not in v:
      v.append(k)

r = [tuple([*k, 1]) for k in v]

输出:

[('MI', 'JI', 1), ('JI', 'MI', 1), ('MI', 'MI', 1), ('MI', 'PA', 1), ('PA', 'MI', 1)]
import itertools as it
import pandas as pd

df = pd.DataFrame({'Group1': ['A','A','A','A', 'A','A','A', 'A','A','A', 'A','A','A', 'A','A'],
                   'Group2': ['A','A','A','A', 'A','A','A', 'A','A','A', 'A','A','A', 'A','A'],
                   'Group3': ['A','A','A','A','A','B','C','C','C','C','C','C','C','C','C'],
                   'Asset': ['MI','JI','MI','JI','MI','MI','MI','PA','MI','PA','MI','PA','MI','PA','MI']
                   })

def assets_pairs(assets_group):
    unique_assets = set(assets_group)
    if len(unique_assets) == 1:
        x = assets_group.iat[0]  # get the only unique asset
        pairs = [[x, x]]
    else:
        pairs = it.permutations(unique_assets, r=2)  # get all the unique pairs without repeated elements
    return pd.DataFrame(pairs, columns=['Source', 'Target']) 
   
df_pairs = (
    df.groupby(['Group1', 'Group2', 'Group3'])['Asset']
      .apply(assets_pairs)   # create asset pairs per group 
      .groupby(['Source', 'Target'], as_index=False)  # compute the weights  by 
      .agg(Weights = ('Source', 'size'))              # counting the unique ('Source', 'Target') pairs
)

>>> df_pairs

  Source Target  Weights
0     JI     MI        1
1     MI     JI        1
2     MI     MI        1
3     MI     PA        1
4     PA     MI        1