为网络图重组 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
我正在构建一个 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