Multiplying Weights in Networkx Python

2019-06-24 19:56发布

I am graphing a tree in networkx, and have added percentage shares as weights. Example: shops and owners of the shops, which can be another shop:

import pandas as pd
data = pd.DataFrame({'shop': ['S1', 'S1', 'S1', 'S2', 'S2', 'S3', 'S3', 'S3'],
                     'owner': ['O1', 'O2', 'S2', 'S3', 'O3', 'O4', 'O5', 'O6'],
                     'share': [0.2, 0.2, 0.6, 0.5, 0.5, 0.1, 0.1, 0.8]})
data

 shop   owner   share
 S1      O1     0.2
 S1      O2     0.2
 S1      S2     0.6
 S2      S3     0.5
 S2      O3     0.5
 S3      O4     0.1
 S3      O5     0.1
 S3      O6     0.8

I can create a directed graph in networkx like this:

import networkx as nx    
G = nx.from_pandas_edgelist(data,'shop','owner',edge_attr = ('share'), 
create_using=nx.DiGraph())

And graph the result:

pos=nx.spring_layout(G, k = 0.5, iterations = 20)
node_labels = {node:node for node in G.nodes()}
nx.draw_networkx(G, pos, labels = node_labels, arrowstyle = '-|>',
             arrowsize = 20,  font_size = 15, font_weight = 'bold')

enter image description here

How would I multiply the weights for each shop in the graph such that I have the owner and the percentage share? Something like the following:

output = pd.DataFrame({'shop': ['S1', 'S1', 'S1', 'S1', 'S1', 'S1', 'S2', 
                                'S2', 'S2','S2', 'S3', 'S3', 'S3'],
                      'owner': ['O1', 'O2', 'O3', 'O4', 'O5', 'O6', 'O3', 
                                'O4', 'O5','O6', 'O4', 'O5', 'O6'],
                      'share': [0.2, 0.2, 0.3, 0.03, 0.03, 0.24, 0.5, 0.05, 
                                0.05, 0.4, 0.1, 0.1, 0.8]})

output

shop    owner   share
 S1     O1      0.2
 S1     O2      0.2
 S1     O3      0.3
 S1     O4      0.03
 S1     O5      0.03
 S1     O6      0.24
 S2     O3      0.5
 S2     O4      0.05
 S2     O5      0.05
 S2     O6      0.4
 S3     O4      0.1
 S3     O5      0.1
 S3     O6      0.8

Update: thanks to this question here I can get the product (multiplied weights) between any 2 chosen nodes (see below) How do I then get the same for all nodes in a data frame as above?

start = 'S1' # start node
end = 'O5'   # end node

all_paths = [path for path in nx.all_simple_paths(G, start, end)]

for p in all_paths:                          # keep track of each path
    for _ in range(len(p)):                 # for each node in this path
        pairs = zip(p, p[1:])                    # get sequence of nodes
        product = 1                              
        for pair in pairs:             # for each pair of nodes in this path
            an_edge = G.get_edge_data(pair[0], pair[1])                
            product *= an_edge['share'] 

1条回答
▲ chillily
2楼-- · 2019-06-24 20:21

Edit: misunderstood the question. Here is a possible answer:

owners = set(data['owner'])
shops  = set(data['shop'])
summary = {}
for owner in owners:
    for shop in shops:
        paths = list(nx.all_simple_paths(G, shop, owner))
        if len(paths):
            for path in paths:
                for start, end in zip(path[:-1], path[1:]):
                    summary[(shop, owner)] = summary.get((shop,owner), 1) * G[start][end]['share']

summary = pd.DataFrame.from_dict(summary, orient = 'index', columns = 'share'.split())
print(summary)

Output:

           share
(S2, O4)   0.05
(S3, O4)   0.10
(S1, O4)   0.03
(S2, O6)   0.40
(S3, O6)   0.80
(S1, O6)   0.24
(S2, O5)   0.05
(S3, O5)   0.10
(S1, O5)   0.03
(S1, O2)   0.20
(S2, S3)   0.50
(S1, S3)   0.30
(S1, S2)   0.60
(S2, O3)   0.50
(S1, O3)   0.30
(S1, O1)   0.20
查看更多
登录 后发表回答