Renaming a Graph in Networkx - python-3.x

I am new on Python and I am trying to learn Networkx ( https://networkx.github.io/ )
I am trying to run a basic a code:
import networkx as nx
import matplotlib.pyplot as plt
G=nx.Graph()
G.add_node(1)
G.add_node(2)
G.add_node(3)
G.add_node(4)
G.add_node(5)
G.add_node(6)
G.add_node(7)
G.add_edge(1,2)
G.add_edge(2,3)
G.add_edge(3,4)
G.add_edge(4,5)
G.add_edge(5,6)
G.add_edge(6,7)
G.add_edge(7,1)
G.add_edge(1,3)
G.add_edge(1,4)
G.add_edge(1,5)
G.add_edge(1,6)
G.add_edge(1,7)
G.add_edge(2,4)
G.add_edge(2,5)
G.add_edge(2,6)
G.add_edge(2,7)
G.add_edge(3,5)
G.add_edge(3,6)
G.add_edge(3,7)
G.add_edge(4,6)
G.add_edge(4,7)
G.add_edge(5,7)
nx.draw(G)
plt.savefig("graph1.png")
plt.show()
and this is the graph generated:
The problem comes when trying to add names to the nodes. I am running the next code:
import networkx as nx
import matplotlib.pyplot as plt
G=nx.Graph()
G.add_node(1)
G.add_node(2)
G.add_node(3)
G.add_node(4)
G.add_node(5)
G.add_node(6)
G.add_node(7)
G.add_edge(1,2)
G.add_edge(2,3)
G.add_edge(3,4)
G.add_edge(4,5)
G.add_edge(5,6)
G.add_edge(6,7)
G.add_edge(7,1)
G.add_edge(1,3)
G.add_edge(1,4)
G.add_edge(1,5)
G.add_edge(1,6)
G.add_edge(1,7)
G.add_edge(2,4)
G.add_edge(2,5)
G.add_edge(2,6)
G.add_edge(2,7)
G.add_edge(3,5)
G.add_edge(3,6)
G.add_edge(3,7)
G.add_edge(4,6)
G.add_edge(4,7)
G.add_edge(5,7)
names = {1:"Central",2:"South",3:"North",4:"East",5:"West",6:"Up",7:"Down"}
H=nx.relabel_nodes(G,names)
nx.draw(H)
plt.savefig("graph1.png")
plt.show()
and the resulted graph is this one:
How can I add names to the nodes? I am using python 3.8 and Networkx 2.4

You can either use nx.draw(H, with_labels=True),
Or nx.draw_networkx(H), which has with_labels=True as default.
documentation of nx.draw:
draw(G, pos=None, ax=None, **kwds)
[...]
kwds (optional keywords) – See networkx.draw_networkx() for a description of optional keywords.
documentation of nx.draw_networkx
draw_networkx(G, pos=None, arrows=True, with_labels=True, **kwds)
[...]
with_labels (bool, optional (default=True)) – Set to True to draw labels on the nodes.
edit:
draw edges with different colors:
check out the function nx.draw_networkx_edges
relevant attributes:
edge_color (color string, or array of floats) – Edge color. Can be a single color
format string (default=’r’), or a sequence of colors with the same length as edgelist. If numeric values are specified they will be mapped to colors using the edge_cmap and edge_vmin,edge_vmax parameters.
style (string) – Edge line style (default=’solid’) (solid|dashed|dotted,dashdot)
alpha (float) – The edge transparency (default=1.0)
cmap (edge) – Colormap for mapping intensities of edges (default=None)
edge_vmin,edge_vmax (floats) – Minimum and maximum for edge colormap scaling (default=None)
So, you can make a list of strings:
colors = ['red'] * len(G.edges()
pos = nx.spring(layout(G))
nx.draw_networkx_nodes(G, pos=pos)
nx.draw_networkx_edges(G, pos=pos, edge_color=colors)
or use numbers and a colormap:
colors = [np.random.rand() for e in G.edges()]
pos = nx.spring(layout(G))
nx.draw_networkx_nodes(G, pos=pos)
nx.draw_networkx_edges(G, pos=pos, edge_color=colors, cmap='viridis')

Related

Drawing Worldmap Whose Center Is Japan With Geopandas

Before reading my question, my english skill is poor, so please send me feedback or advise in easy words. Thank you.
What I wand to do:
I want to draw an worldmap whose center is Japan with geopandas library on python 3.x.
My Environment:
Windows10 (64bit)
Python v3.9.4
geopandas v0.9.0
My Code:
import geopandas
world = geopandas.read_file(geopandas.datasets.get_path("naturalearth_lowres"))
world.boundary.plot(figsize=(15,8))
The Obtained Image
world image
Question:
The center of an obtained worldmap drawing is arouond Africa. I want to draw the image whose center is Japan. I read an official document: Mapping and Plotting Tools, but I can not find how to realize it. Please tell me advices !!
I found working with geopandas (+ pyproj as its dependency) to get the shifted map is too difficult. In my code below, geopandas is used to provide the geodataframe of the world to manipulate and plot. Cartopy is used to provide the geoaxis for proper geospatial referencing. And shapely is used to do all sorts of manipulation to transform geometries for plotting re-centered world plot to meet the requirements in the question.
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from shapely.geometry import LineString, MultiPolygon, Polygon
from shapely.ops import split
from shapely.affinity import translate
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
import geopandas
def shift_map(world_gdf, shift, ax):
# world_gdf: world geodataframe to shift
# shift: longitude shift
# ax: geoaxis to plot the map
shift -= 180
moved_map = []
splitted_map = []
border = LineString([(shift,90),(shift,-90)])
for row in world_gdf["geometry"]:
splitted_map.append(split(row, border))
for element in splitted_map:
items = list(element)
for item in items:
minx, miny, maxx, maxy = item.bounds
if minx >= shift:
moved_map.append(translate(item, xoff=-180-shift))
else:
moved_map.append(translate(item, xoff=180-shift))
gdf = geopandas.GeoDataFrame({"geometry": moved_map})
gdf.boundary.plot(ax=ax, linewidth=1, color='gray')
# can also use: gdf.plot() to plot the geometries as polygons
# define CRS's
crs0 = ccrs.PlateCarree(central_longitude=0) # standard CRS
lon_0 = 138 # Japan at center
# crsJapan = ccrs.PlateCarree(central_longitude=lon_0) # japan's centered; not in-use
# a special CRS for use with ax1.gridlines() to get correct longitude's labels plot
crsGridLines = ccrs.PlateCarree(central_longitude=-lon_0)
# create figure, axis
# use cartopy ccrs to get some niceties
fig, ax1 = plt.subplots(figsize=(8, 4.5), subplot_kw={"projection": crs0})
# load world geodataframe
world = geopandas.read_file(geopandas.datasets.get_path("naturalearth_lowres"))
# Plot the shifted map
shift_map(world, lon_0, ax1)
# Plot graticule/grid; only work with geoaxis
gl = ax1.gridlines(crs=crsGridLines, draw_labels=True, linewidth=1, color='gray', linestyle='--')
gl.xformatter = LONGITUDE_FORMATTER
gl.yformatter = LATITUDE_FORMATTER
gl.xlabel_style = {'size': 10, 'color': 'black'}
gl.ylabel_style = {'size': 10, 'color': 'black'}
plt.show()

Networkx: how to add edge labels from csv file in a graph

How can I add Edge label from csv/excel file to networkx directed graph
I want to add labels to my networkx graph from column Edge_label present in csv file
import pandas as pd
import matplotlib.pyplot as plt
#%matplotlib inline
import networkx as nx
df = pd.read_csv('Trail_data.csv')
g = nx.from_pandas_edgelist(df,
'Source',
'Target',
create_using=nx.DiGraph() # For Directed Route arrows
)
plt.figure( figsize=(40, 40)
)
nx.draw(g,
with_labels=True,
node_size= 3000,#k=200,
node_color='#82CAFF',##00b4d9
font_size=16,
font_weight ='bold',
font_color='black',
edge_color = ('#E55451','#810541','#00FF00'),
node_shape='o',
width=4 ,
arrows=True, #Show arrow From and To
pos=nx.random_layout(g),iterations=20,
connectionstyle='arc3, rad =0.11' #To avoid overlapping edgs
)
plt.savefig('Visualization.jpeg',
dpi = (100)
)
** Also I wanted to convert this directed graph to interactive graph with python-dash **
According to the documentation of from_pandas_edgelist you can simply specify a list of columns with edge_attr.
In your case, you get the desired graph with:
g = nx.from_pandas_edgelist(df,
'Source',
'Target',
edge_attr=`Edge_label`,
create_using=nx.DiGraph(),)
For drawing you currently only draw node labels. You can add edge labels with draw_networkx_edge_labels
pos = nx.random_layout(g)
nx.draw(g,
pos=pos, ...) # add other parameters
edge_labels = nx.get_edge_attributes(g, "Edge_label")
nx.draw_networkx_edge_labels(g, pos, edge_labels)

How can i get Networkx to show both weights on an edge that is going in 2 directions?

I have a text file with the following data:
192.168.12.22 192.168.12.21 23
192.168.12.21 192.168.12.22 26
192.168.12.23 192.168.12.22 56
There are three nodes and two of them are sending packets to each other. I want to be able to show both weights on two different edges, but it only shows one with a single weight.
This is my code:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.read_weighted_edgelist('test.txt', create_using=nx.DiGraph())
pos = nx.spring_layout(G)
print(nx.info(G))
nx.draw(G, pos, with_labels=True)
nx.draw_networkx_edge_labels(G, pos)
plt.show()
You can use the label_pos parameter (see draw_networkx_edge_labels):
import networkx as nx
import matplotlib.pyplot as plt
edges = [["192.168.12.22", "192.168.12.21", 23],
["192.168.12.21", "192.168.12.22", 26],
["192.168.12.23", "192.168.12.22", 56]]
graph = nx.DiGraph()
graph.add_weighted_edges_from(edges)
pos = nx.spring_layout(graph)
nx.draw(graph, pos, with_labels=True)
nx.draw_networkx_edge_labels(graph,
pos,
edge_labels={(u, v): d for u, v, d in graph.edges(data="weight")},
label_pos=.66)
plt.show()
You may also want to take a look at this answer.

Assign edge weights to a networkx graph using pandas dataframe

I am contructing a networkx graph in python 3. I am using a pandas dataframe to supply the edges and nodes to the graph. Here is what I have done :
test = pd.read_csv("/home/Desktop/test_call1", delimiter = ';')
g_test = nx.from_pandas_edgelist(test, 'number', 'contactNumber', edge_attr='callDuration')
What I want is that the "callDuration" column of the pandas dataframe act as the weight of the edges for the networkx graph and the thickness of the edges also change accordingly.
I also want to get the 'n' maximum weighted edges.
Let's try:
import pandas as pd
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
df = pd.DataFrame({'number':['123','234','345'],'contactnumber':['234','345','123'],'callduration':[1,2,4]})
df
G = nx.from_pandas_edgelist(df,'number','contactnumber', edge_attr='callduration')
durations = [i['callduration'] for i in dict(G.edges).values()]
labels = [i for i in dict(G.nodes).keys()]
labels = {i:i for i in dict(G.nodes).keys()}
fig, ax = plt.subplots(figsize=(12,5))
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos, ax = ax, labels=True)
nx.draw_networkx_edges(G, pos, width=durations, ax=ax)
_ = nx.draw_networkx_labels(G, pos, labels, ax=ax)
Output:
Do not agree with what has been said. In the calcul of different metrics that takes into account the weight of each edges like the pagerank or the betweeness centrality your weight would not be taking into account if is store as an edge attributes.
Use graph.
Add_edges(source, target, weight, *attrs)

Draw Graphs proportional to weight of edges using networkx

I'm having a Graph to display, but it should be displayed where edges are proportional to the weight. I used networkx library to draw the graph but it draw nodes randomly.
Here is the part of my code to display graph:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
# Added nodes and Edges
pos = nx.spring_layout(G)
nx.draw(graph, pos=pos, nodelist=nodes, with_labels=True)
plt.show()
How can I create a graph where the edge length is weighted?
If it helps I'm also open to use a different library than matplotlib.
The graphviz force directed algorithm outputs what I want. (But I am not sure why it is different than the spring layout from networkx)
import networkx as nx
import pylab as plt
from networkx.drawing.nx_agraph import graphviz_layout
G = nx.Graph()
G.add_node(1)
G.add_node(2)
G.add_node(3)
G.add_node(4)
G.add_edge(1,2, len=4.5)
G.add_edge(2,3, len=2.5)
G.add_edge(3,4, len=7)
G.add_edge(4,1, len=10)
G.add_edge(3,1, len=4.5)
G.add_edge(4,2, len=9)
pos=graphviz_layout(G)
nx.draw(G, pos, node_size=1600, node_color=range(len(G)), with_labels=True, cmap=plt.cm.Dark2)
plt.show()

Resources