Python Pandas-创建包含节点对和边缘强度的数据框架



我正在努力创建一个简单的网络图,并且我有一些问题使我的数据变为正确的形状。

我有一个带有两列的熊猫数据框架,其中包含有关不同实体之间协作的信息。列 project_id 列出了项目的ID,并且参与_entity 列出了一个参与项目的实体。一个拥有3个实体的项目将占用3行。这是一个简单的示例DF列表在3个项目上的3个实体之间的合作:

df =  pd.DataFrame([[1,'a'],[1,'b'],[2,'a'],[2,'c'],[3,'a'],[3,'b'],[3,'c']],  columns = ['Project_ID','Participating_entity']) 
#|---------------------|-------------------------|
#|       Project_ID    | Participating_entity    |
#|---------------------|-------------------------|
#|          1          |            A            |
#|          1          |            B            |
#|          2          |            A            |
#|          2          |            C            |
#|          3          |            A            |
#|          3          |            B            |
#|          3          |            C            |
#|---------------------|-------------------------|

我想创建一个新的DF,以显示参与者对之间的协作数量。对于上面的简单数据。

#|-------------|-----------|--------------------|
#|  Entity_1   | Entity_2  | Num_collaborations |
#|-------------|-----------|--------------------|
#|     A       |      B    |        2           |
#|     A       |      C    |        2           |
#|     B       |      C    |        1           |
#|-------------|-----------|--------------------|

A与B和C的每一个合作两次合作一次。合作仅应列出一次。例如,A和B之间的连接应仅在A-B下列出,而B-A。

不应存在行。

预先感谢!

您可以直接在NetworkX中进行:

In [210]: G = nx.from_pandas_edgelist(df, 'Project_ID', 'Participating_entity')
In [211]: from networkx.algorithms import bipartite
In [212]: W = bipartite.weighted_projected_graph(G, df['Participating_entity'].unique())
In [213]: W.edges(data=True)
Out[213]: EdgeDataView([('a', 'c', {'weight': 2}), ('a', 'b', {'weight': 2}), ('b', 'c', {'weight': 1})])

一种方法是将collections.defaultdictitertools.combinations结合使用。可能有一种特定于熊猫的方式,但从本质上讲,这将是特定于图书馆的。

from collections import defaultdict
from itertools import combinations
df_grouped = df.groupby('Project_ID')['Participating_entity'].apply(list).reset_index()
d = defaultdict(int)
for idx, row in df_grouped.iterrows():
    for comb in combinations(row['Participating_entity'], 2):
        d[frozenset(comb)] += 1
# defaultdict(int,
#             {frozenset({'a', 'b'}): 2,
#              frozenset({'a', 'c'}): 2,
#              frozenset({'b', 'c'}): 1})
d = {tuple(sorted(k)): v for k, v in d.items()}
df_out = pd.DataFrame(list(d.items()))
           .rename(columns={0: 'Entities', 1: 'Num_collaborations'})
df_out = df_out.join(df_out['Entities'].apply(pd.Series))
               .drop('Entities', 1).rename(columns={0: 'Entity 1', 1: 'Entity 2'})
#    Num_collaborations Entity 1 Entity 2
# 0                   2        a        b
# 1                   2        a        c
# 2                   1        b        c

最新更新