I have a simple graph with the attributes height and area
import networkx as nx
nodes_list = [("A", {"height":10, "area":100}),
("B", {"height":12, "area":200}),
("C", {"height":8, "area":150}),
("D", {"height":9, "area":120})]
G = nx.Graph()
G.add_nodes_from(nodes_list)
edges_list = [("A","B"), ("B","C"), ("C","D")]
G.add_edges_from(edges_list)
nx.draw(G, with_labels=True, node_color="red")
I want to contract nodes and update the attributes with the average of height and the sum of area of the contracted nodes.
There must be some easier way than:
H = nx.contracted_nodes(G, "B","C")
#print(H.nodes["B"])
#{'height': 12, 'area': 200, 'contraction': {'C': {'height': 8, 'area': 150}}}
#Calc the average of node B and C's heights
new_height = (H.nodes["B"]["height"] + H.nodes["B"]["contraction"]["C"]["height"])/2 #10
#Calc the sum of of node B and C's areas
new_area = H.nodes["B"]["area"] + H.nodes["B"]["contraction"]["C"]["area"]
#Drop old attributes
del(H.nodes["B"]["height"], H.nodes["B"]["area"], H.nodes["B"]["contraction"])
nx.set_node_attributes(H, {"B":{"height":new_height, "area":new_area}})
print(H.nodes["B"])
#{'height': 10.0, 'area': 350}
Can I get networkx to average height and sum area, every time I contract multiple nodes?
I don't think there is a builtin way, especially since you have custom aggregation functions.
Here is an alternative way, using a custom function:
def contract_merge(G, n1, n2):
H = nx.contracted_nodes(G, n1, n2)
d_n1 = H.nodes[n1]
d_n2 = d_n1.pop('contraction')[n2]
d_n1['height'] = (d_n1['height']+d_n2['height'])/2
d_n1['area'] = d_n1['area']+d_n2['area']
nx.set_node_attributes(H, {n1: d_n1})
return H
H = contract_merge(G, 'B', 'C')
print(H.nodes(data=True))
Output:
NodeDataView({'A': {'height': 10, 'area': 100},
'B': {'height': 10.0, 'area': 350},
'D': {'height': 9, 'area': 120}})