Networkx is a python library for creation, manipulation and understanding structure of complex networks. It supports the creation of graphs, digraphs & multigraphs. It also has various graph algorithms by default.

Networkx supports nodes like text, images, XML and edges like time-series, weight, etc.

It can be used to analyze the structure of social, biological, infrastructure and various other types of networks.

```
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import matplotlib.pyplot as plt
import os
import sys
import networkx as nx
import scipy
print('Python Version : '+sys.version)
print('NetworkX version : '+nx.__version__)
```

Users can test networkx library by running its tests using the below statements. I have commented on it as of now as It'll take time to run.

```
#nx.test()
```

**Undirected Graphs** can be created using simple Graph constructor. The graph consists of a list of nodes and node pairs (edges). Any hashable object except **None** can be node of graph-like text, image, etc. including another graph as well.

It allows self-loop for node but it does not allow parallel edges (more than 1 edges between 2 nodes).

Graph constructor can be **initialized** in various ways mentioned below:

- Empty without any node
- Using list of edges
- Using dict of dict
- dict of lists
- Using Numpy matrix / 2-d array
- Using scipy sparse array
- Other networkx graph

```
G = nx.Graph()
G1 = nx.Graph([(4,5),(6,7),(8,9), (5,7),(4,9), (9,7)]) ## Creating graphs from list of edges
G2 = nx.Graph(G1) ## Creating graph from existing graph
G3 = nx.Graph(dict([(4,[(6,7),(2,3)]),(6,(8,9)), (5,(5,7)),(7,(4,9)), (9,(9,7))])) ## Creating graph from dict of list
G4 = nx.Graph(dict([(4,{6:7}),(6,{10:11}), (5,{5: 7}),(7,{4: 9}), (9,{9:7})])) ## Creating graph from dict of dict
l = np.random.rand(5,5)
print(l)
G5 = nx.Graph(l) ## Creating graph from numpy 2-d array
row = [0,3,1,0]
col = [0,3,1,2]
data = [4,5,7,9]
sparse_mat = scipy.sparse.coo_matrix((data, (row, col)), shape=(4,4)) ## Creating graph from scipy sparse matrix
print(sparse_mat.toarray())
G6 = nx.Graph(sparse_mat)
plt.figure(figsize=(12,3))
plt.subplot(1,6,1)
nx.draw(G1, with_labels=True, font_weight='bold')
plt.title('G1')
plt.subplot(1,6,2)
nx.draw(G2, with_labels=True, font_weight='bold')
plt.title('G2')
plt.subplot(1,6,3)
nx.draw(G3, with_labels=True, font_weight='bold')
plt.title('G3')
plt.subplot(1,6,4)
nx.draw(G4, with_labels=True, font_weight='bold')
plt.title('G4')
plt.subplot(1,6,5)
nx.draw(G5, with_labels=True, font_weight='bold')
plt.title('G5')
plt.subplot(1,6,6)
nx.draw(G6, with_labels=True, font_weight='bold')
plt.title('G6')
None
```

Below we are analyzing properties of graphs created above using various methods.

```
for i, graph in enumerate([G1,G2,G3,G4,G5,G6], start=1):
print('Graph%d : '%i)
print('Nodes : %s'%graph.nodes,'Edges : %s'%graph.edges)
print('Attribute with first edge : %s'%graph.get_edge_data(*list(graph.edges)[0]))
print('Nodes with selfloops : %s'%list(graph.nodes_with_selfloops()))
print('Undirected : %s'%graph.is_directed())
print('Number of Edges : %s'%graph.number_of_edges())
print('Number of Nodes : %s'%graph.number_of_nodes())
print('Graph size : %s'%graph.size())
print('Graph adjacent nodes : %s'%graph.adj)
print('Degree of each node : %s'%graph.degree)
print(graph.name)
```

There are various methods available to add new nodes and edges to the graph. We have listed below a few of them. One can add any hashable python object as a node to the graph. One can add another graph as well as a node to an existing graph.

```
plt.figure(figsize=(8,4))
G = nx.Graph()
G.add_node(1), G.add_node(32), G.add_node('Node1'), G.add_node('Node2'), G.add_node('Node3')
G.add_nodes_from([2,3])
G.add_edge(1,3), G.add_edge('Node2','Node3'), G.add_edge(1,'Node1')
G.add_edges_from([(26,27, {'weight': 3.14}),(28,29, {'weight': 6.45})])
G.add_cycle([4,5,6,7,20,21,22,4])
G.add_star([8,9,10,11,12,13,25])
G.add_path([14,15,16,17])
print(G.get_edge_data(26,27), G.get_edge_data(28,29))
nx.draw(G, with_labels=True, font_weight='bold')
```

```
H = nx.path_graph(10)
G.add_nodes_from(H)
G.remove_node(32), G.remove_node('Node2'), G.remove_node(28) ## Removing node 'Node2' & 28 also removed edges associated with them
G.remove_edge(26,27) ## Though edge 26-27 is removed but node 26,27 will still be existing independent
nx.draw(G, with_labels=True, font_weight='bold')
```

```
nx.draw_shell(G, with_labels=True, font_weight='bold')
```

```
nx.draw_random(G, with_labels=True, font_weight='bold')
```

```
G = nx.dfs_tree(G)
nx.draw(G, with_labels=True, font_weight='bold')
```

```
G = nx.bfs_tree(G,source=8)
nx.draw(G, with_labels=True, font_weight='bold')
```

```
G = nx.dodecahedral_graph()
nx.draw(G, with_labels=True, font_weight='bold')
```

```
Di_G = nx.DiGraph(G)
nx.draw(Di_G, with_labels=True, font_weight='bold')
```

```
Di_G1 = nx.DiGraph(G1)
nx.draw(Di_G1, with_labels=True, font_weight='bold')
```

If you are more comfortable learning through video tutorials then we would recommend that you subscribe to our **YouTube** channel.

When going through coding examples, it's quite common to have doubts and errors.

If you have doubts about some code examples or are stuck somewhere when trying our code, send us an email at **coderzcolumn07@gmail.com**. We'll help you or point you in the direction where you can find a solution to your problem.

You can even send us a mail if you are trying something new and need guidance regarding coding. We'll try to respond as soon as possible.

If you want to

- provide some suggestions on topic
- share your views
- include some details in tutorial
- suggest some new topics on which we should create tutorials/blogs