Search code examples
pythongraphnetworkxedgesweighted-graph

Generate weighted edges from duplicate list of set in networkx python


So, i want to create weighted graph with data in list of set like this :

temp_comb_test = [{'AN', 'TA'}, {'TA', 'DP'},{'AS','TA'},{'HS','AS'},{'HS','TA'},{'TA','AA'},{'LS','TA'}]

Those weighted, is generate from duplicate edges. Using set() type of data is simply because in set, (A, B) and (B, A) is equal/duplicate data (in my knowledge list and tuple can't do that). So i wrote a code like this to add weighted edges :

G_Author = nx.Graph()

temp = [] # to keep temporary relation (no dupe)

for iter1 in temp_comb_test:
    
    if len(temp) == 0: # to add first set
        temp.append(iter1)
        G_Author.add_edges_from([iter1], weight = 1)

        print("A - Data ", iter1, " In")
        print("temp :", temp)
        print(G_Author.edges.data(), '\n') 

    else:
        for iter2 in temp: # iterate temporary list
            if iter1 == iter2: # checking duplicate set

                nod1, nod2 = iter1
                nod3, nod4 = iter2                                          
                
                if ((nod1 == nod3) and (nod2 == nod4) and (nod1 != nod4)): # if set look like --> (A, B) == (A, B)

                    print("F -", "new :", iter1, "old :", iter2)
                    
                    wei = nx.get_edge_attributes(G_Author, "weight")
                    wei2 = wei[nod4, nod3] + 1      # ====> THE PROBLEM 2
                    nx.set_edge_attributes(G_Author, {(nod3, nod4): {"weight": wei2}})
                    print(G_Author.edges.data(), '\n')

                elif ((nod1 != nod3) and (nod2 != nod4) and (nod1 == nod4)): # if duplicate set looks like --> (A, B) == (B, A)
                    print("F -", iter1, iter2)
                    wei3 = nx.get_edge_attributes(G_Author, "weight")
                    wei4 = wei3[nod3, nod4] + 1
                    nx.set_edge_attributes(G_Author, {(nod2, nod1): {"weight": wei4}})
            else:
                nd1, nd2 = iter1
                print("E - Data {", nd1, ",", nd2, "} in || iter1 :", iter1)
                G_Author.add_edge(nd2, nd1, weight = 1)     # ====> THE PROBLEM 1
                temp.append({nd2, nd1})
  
                print("temp :", temp)
                print(G_Author.edges.data(), '\n') 

When i run this code, first element is successfully add to graph. Following by the first else condition. But, the problem occur on the next iteration like this :

A - Data  {'TA', 'AN'}  in
temp : [{'TA', 'AN'}]
[('TA', 'AN', {'weight': 1})] 

E - Data { DP , TA } in || iter1 : {'DP', 'TA'}
temp : [{'TA', 'AN'}, {'DP', 'TA'}]
[('TA', 'AN', {'weight': 1}), ('TA', 'DP', {'weight': 1})] 

F - new : {'DP', 'TA'} old : {'DP', 'TA'}

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-136-f103fe75d64d> in <module>
     33                     wei = nx.get_edge_attributes(G_Author, "weight")
     34                     # print(wei)
---> 35                     wei2 = wei[nod3, nod4] + 1
     36                     nx.set_edge_attributes(G_Author, {(nod3, nod4): {"weight": wei2}})
     37                     print(G_Author.edges.data(), '\n')

KeyError: ('DP', 'TA')

The main error come from this line wei2 = wei[nod4, nod3] + 1, it is cause by else condition. Where new data is { DP , TA }, proven by temp : [{'TA', 'AN'}, {'DP', 'TA'}]. But, when {'DP', 'TA'} add into the G_Author, the order is switched and become {'TA', 'DP'}.

I already try to change wei2 = wei[nod4, nod3] + 1 into wei2 = wei[nod3, nod4] + 1, but it only fix the first duplicate. When another duplicate comes up, the error come again from those 2 line of code.

Maybe someone can help me with this or have a better solution to generate weight from duplicate set()?


Solution

  • You might want to use collections.Counter, which will count the occurrences of specific keys in an iterable:

    from collections import Counter
    from networkx import Graph
    
    # create edge counts
    t = [{'A', 'B'}, {'C', 'D'}, {'B', 'A'}]
    # note that Counter does not use sets, so change data to tuples
    c = Counter(map(tuple,t))
    print(c)
    # Counter({('A', 'B'): 2, ('C', 'D'): 1})
    
    # add edges to the graph
    G = Graph()
    for (source, target), weight in c.items():
       G.add_edge(source, target, weight=weight)
    print(G.edges(data=True))
    # [('A', 'B', {'weight': 2}), ('C', 'D', {'weight': 1})]