We define our graph as an igraph.Graph
object. Python igraph
is a library for high-performance graph generation and analysis.
import igraph as ig
Read graph data from a json
file:
import json
data = []
with open('miserables.json') as f:
for line in f:
data.append(json.loads(line))
data=data[0]
data
{u'links': [{u'source': 1, u'target': 0, u'value': 1}, {u'source': 2, u'target': 0, u'value': 8}, {u'source': 3, u'target': 0, u'value': 10}, {u'source': 3, u'target': 2, u'value': 6}, {u'source': 4, u'target': 0, u'value': 1}, {u'source': 5, u'target': 0, u'value': 1}, {u'source': 6, u'target': 0, u'value': 1}, {u'source': 7, u'target': 0, u'value': 1}, {u'source': 8, u'target': 0, u'value': 2}, {u'source': 9, u'target': 0, u'value': 1}, {u'source': 11, u'target': 10, u'value': 1}, {u'source': 11, u'target': 3, u'value': 3}, {u'source': 11, u'target': 2, u'value': 3}, {u'source': 11, u'target': 0, u'value': 5}, {u'source': 12, u'target': 11, u'value': 1}, {u'source': 13, u'target': 11, u'value': 1}, {u'source': 14, u'target': 11, u'value': 1}, {u'source': 15, u'target': 11, u'value': 1}, {u'source': 17, u'target': 16, u'value': 4}, {u'source': 18, u'target': 16, u'value': 4}, {u'source': 18, u'target': 17, u'value': 4}, {u'source': 19, u'target': 16, u'value': 4}, {u'source': 19, u'target': 17, u'value': 4}, {u'source': 19, u'target': 18, u'value': 4}, {u'source': 20, u'target': 16, u'value': 3}, {u'source': 20, u'target': 17, u'value': 3}, {u'source': 20, u'target': 18, u'value': 3}, {u'source': 20, u'target': 19, u'value': 4}, {u'source': 21, u'target': 16, u'value': 3}, {u'source': 21, u'target': 17, u'value': 3}, {u'source': 21, u'target': 18, u'value': 3}, {u'source': 21, u'target': 19, u'value': 3}, {u'source': 21, u'target': 20, u'value': 5}, {u'source': 22, u'target': 16, u'value': 3}, {u'source': 22, u'target': 17, u'value': 3}, {u'source': 22, u'target': 18, u'value': 3}, {u'source': 22, u'target': 19, u'value': 3}, {u'source': 22, u'target': 20, u'value': 4}, {u'source': 22, u'target': 21, u'value': 4}, {u'source': 23, u'target': 16, u'value': 3}, {u'source': 23, u'target': 17, u'value': 3}, {u'source': 23, u'target': 18, u'value': 3}, {u'source': 23, u'target': 19, u'value': 3}, {u'source': 23, u'target': 20, u'value': 4}, {u'source': 23, u'target': 21, u'value': 4}, {u'source': 23, u'target': 22, u'value': 4}, {u'source': 23, u'target': 12, u'value': 2}, {u'source': 23, u'target': 11, u'value': 9}, {u'source': 24, u'target': 23, u'value': 2}, {u'source': 24, u'target': 11, u'value': 7}, {u'source': 25, u'target': 24, u'value': 13}, {u'source': 25, u'target': 23, u'value': 1}, {u'source': 25, u'target': 11, u'value': 12}, {u'source': 26, u'target': 24, u'value': 4}, {u'source': 26, u'target': 11, u'value': 31}, {u'source': 26, u'target': 16, u'value': 1}, {u'source': 26, u'target': 25, u'value': 1}, {u'source': 27, u'target': 11, u'value': 17}, {u'source': 27, u'target': 23, u'value': 5}, {u'source': 27, u'target': 25, u'value': 5}, {u'source': 27, u'target': 24, u'value': 1}, {u'source': 27, u'target': 26, u'value': 1}, {u'source': 28, u'target': 11, u'value': 8}, {u'source': 28, u'target': 27, u'value': 1}, {u'source': 29, u'target': 23, u'value': 1}, {u'source': 29, u'target': 27, u'value': 1}, {u'source': 29, u'target': 11, u'value': 2}, {u'source': 30, u'target': 23, u'value': 1}, {u'source': 31, u'target': 30, u'value': 2}, {u'source': 31, u'target': 11, u'value': 3}, {u'source': 31, u'target': 23, u'value': 2}, {u'source': 31, u'target': 27, u'value': 1}, {u'source': 32, u'target': 11, u'value': 1}, {u'source': 33, u'target': 11, u'value': 2}, {u'source': 33, u'target': 27, u'value': 1}, {u'source': 34, u'target': 11, u'value': 3}, {u'source': 34, u'target': 29, u'value': 2}, {u'source': 35, u'target': 11, u'value': 3}, {u'source': 35, u'target': 34, u'value': 3}, {u'source': 35, u'target': 29, u'value': 2}, {u'source': 36, u'target': 34, u'value': 2}, {u'source': 36, u'target': 35, u'value': 2}, {u'source': 36, u'target': 11, u'value': 2}, {u'source': 36, u'target': 29, u'value': 1}, {u'source': 37, u'target': 34, u'value': 2}, {u'source': 37, u'target': 35, u'value': 2}, {u'source': 37, u'target': 36, u'value': 2}, {u'source': 37, u'target': 11, u'value': 2}, {u'source': 37, u'target': 29, u'value': 1}, {u'source': 38, u'target': 34, u'value': 2}, {u'source': 38, u'target': 35, u'value': 2}, {u'source': 38, u'target': 36, u'value': 2}, {u'source': 38, u'target': 37, u'value': 2}, {u'source': 38, u'target': 11, u'value': 2}, {u'source': 38, u'target': 29, u'value': 1}, {u'source': 39, u'target': 25, u'value': 1}, {u'source': 40, u'target': 25, u'value': 1}, {u'source': 41, u'target': 24, u'value': 2}, {u'source': 41, u'target': 25, u'value': 3}, {u'source': 42, u'target': 41, u'value': 2}, {u'source': 42, u'target': 25, u'value': 2}, {u'source': 42, u'target': 24, u'value': 1}, {u'source': 43, u'target': 11, u'value': 3}, {u'source': 43, u'target': 26, u'value': 1}, {u'source': 43, u'target': 27, u'value': 1}, {u'source': 44, u'target': 28, u'value': 3}, {u'source': 44, u'target': 11, u'value': 1}, {u'source': 45, u'target': 28, u'value': 2}, {u'source': 47, u'target': 46, u'value': 1}, {u'source': 48, u'target': 47, u'value': 2}, {u'source': 48, u'target': 25, u'value': 1}, {u'source': 48, u'target': 27, u'value': 1}, {u'source': 48, u'target': 11, u'value': 1}, {u'source': 49, u'target': 26, u'value': 3}, {u'source': 49, u'target': 11, u'value': 2}, {u'source': 50, u'target': 49, u'value': 1}, {u'source': 50, u'target': 24, u'value': 1}, {u'source': 51, u'target': 49, u'value': 9}, {u'source': 51, u'target': 26, u'value': 2}, {u'source': 51, u'target': 11, u'value': 2}, {u'source': 52, u'target': 51, u'value': 1}, {u'source': 52, u'target': 39, u'value': 1}, {u'source': 53, u'target': 51, u'value': 1}, {u'source': 54, u'target': 51, u'value': 2}, {u'source': 54, u'target': 49, u'value': 1}, {u'source': 54, u'target': 26, u'value': 1}, {u'source': 55, u'target': 51, u'value': 6}, {u'source': 55, u'target': 49, u'value': 12}, {u'source': 55, u'target': 39, u'value': 1}, {u'source': 55, u'target': 54, u'value': 1}, {u'source': 55, u'target': 26, u'value': 21}, {u'source': 55, u'target': 11, u'value': 19}, {u'source': 55, u'target': 16, u'value': 1}, {u'source': 55, u'target': 25, u'value': 2}, {u'source': 55, u'target': 41, u'value': 5}, {u'source': 55, u'target': 48, u'value': 4}, {u'source': 56, u'target': 49, u'value': 1}, {u'source': 56, u'target': 55, u'value': 1}, {u'source': 57, u'target': 55, u'value': 1}, {u'source': 57, u'target': 41, u'value': 1}, {u'source': 57, u'target': 48, u'value': 1}, {u'source': 58, u'target': 55, u'value': 7}, {u'source': 58, u'target': 48, u'value': 7}, {u'source': 58, u'target': 27, u'value': 6}, {u'source': 58, u'target': 57, u'value': 1}, {u'source': 58, u'target': 11, u'value': 4}, {u'source': 59, u'target': 58, u'value': 15}, {u'source': 59, u'target': 55, u'value': 5}, {u'source': 59, u'target': 48, u'value': 6}, {u'source': 59, u'target': 57, u'value': 2}, {u'source': 60, u'target': 48, u'value': 1}, {u'source': 60, u'target': 58, u'value': 4}, {u'source': 60, u'target': 59, u'value': 2}, {u'source': 61, u'target': 48, u'value': 2}, {u'source': 61, u'target': 58, u'value': 6}, {u'source': 61, u'target': 60, u'value': 2}, {u'source': 61, u'target': 59, u'value': 5}, {u'source': 61, u'target': 57, u'value': 1}, {u'source': 61, u'target': 55, u'value': 1}, {u'source': 62, u'target': 55, u'value': 9}, {u'source': 62, u'target': 58, u'value': 17}, {u'source': 62, u'target': 59, u'value': 13}, {u'source': 62, u'target': 48, u'value': 7}, {u'source': 62, u'target': 57, u'value': 2}, {u'source': 62, u'target': 41, u'value': 1}, {u'source': 62, u'target': 61, u'value': 6}, {u'source': 62, u'target': 60, u'value': 3}, {u'source': 63, u'target': 59, u'value': 5}, {u'source': 63, u'target': 48, u'value': 5}, {u'source': 63, u'target': 62, u'value': 6}, {u'source': 63, u'target': 57, u'value': 2}, {u'source': 63, u'target': 58, u'value': 4}, {u'source': 63, u'target': 61, u'value': 3}, {u'source': 63, u'target': 60, u'value': 2}, {u'source': 63, u'target': 55, u'value': 1}, {u'source': 64, u'target': 55, u'value': 5}, {u'source': 64, u'target': 62, u'value': 12}, {u'source': 64, u'target': 48, u'value': 5}, {u'source': 64, u'target': 63, u'value': 4}, {u'source': 64, u'target': 58, u'value': 10}, {u'source': 64, u'target': 61, u'value': 6}, {u'source': 64, u'target': 60, u'value': 2}, {u'source': 64, u'target': 59, u'value': 9}, {u'source': 64, u'target': 57, u'value': 1}, {u'source': 64, u'target': 11, u'value': 1}, {u'source': 65, u'target': 63, u'value': 5}, {u'source': 65, u'target': 64, u'value': 7}, {u'source': 65, u'target': 48, u'value': 3}, {u'source': 65, u'target': 62, u'value': 5}, {u'source': 65, u'target': 58, u'value': 5}, {u'source': 65, u'target': 61, u'value': 5}, {u'source': 65, u'target': 60, u'value': 2}, {u'source': 65, u'target': 59, u'value': 5}, {u'source': 65, u'target': 57, u'value': 1}, {u'source': 65, u'target': 55, u'value': 2}, {u'source': 66, u'target': 64, u'value': 3}, {u'source': 66, u'target': 58, u'value': 3}, {u'source': 66, u'target': 59, u'value': 1}, {u'source': 66, u'target': 62, u'value': 2}, {u'source': 66, u'target': 65, u'value': 2}, {u'source': 66, u'target': 48, u'value': 1}, {u'source': 66, u'target': 63, u'value': 1}, {u'source': 66, u'target': 61, u'value': 1}, {u'source': 66, u'target': 60, u'value': 1}, {u'source': 67, u'target': 57, u'value': 3}, {u'source': 68, u'target': 25, u'value': 5}, {u'source': 68, u'target': 11, u'value': 1}, {u'source': 68, u'target': 24, u'value': 1}, {u'source': 68, u'target': 27, u'value': 1}, {u'source': 68, u'target': 48, u'value': 1}, {u'source': 68, u'target': 41, u'value': 1}, {u'source': 69, u'target': 25, u'value': 6}, {u'source': 69, u'target': 68, u'value': 6}, {u'source': 69, u'target': 11, u'value': 1}, {u'source': 69, u'target': 24, u'value': 1}, {u'source': 69, u'target': 27, u'value': 2}, {u'source': 69, u'target': 48, u'value': 1}, {u'source': 69, u'target': 41, u'value': 1}, {u'source': 70, u'target': 25, u'value': 4}, {u'source': 70, u'target': 69, u'value': 4}, {u'source': 70, u'target': 68, u'value': 4}, {u'source': 70, u'target': 11, u'value': 1}, {u'source': 70, u'target': 24, u'value': 1}, {u'source': 70, u'target': 27, u'value': 1}, {u'source': 70, u'target': 41, u'value': 1}, {u'source': 70, u'target': 58, u'value': 1}, {u'source': 71, u'target': 27, u'value': 1}, {u'source': 71, u'target': 69, u'value': 2}, {u'source': 71, u'target': 68, u'value': 2}, {u'source': 71, u'target': 70, u'value': 2}, {u'source': 71, u'target': 11, u'value': 1}, {u'source': 71, u'target': 48, u'value': 1}, {u'source': 71, u'target': 41, u'value': 1}, {u'source': 71, u'target': 25, u'value': 1}, {u'source': 72, u'target': 26, u'value': 2}, {u'source': 72, u'target': 27, u'value': 1}, {u'source': 72, u'target': 11, u'value': 1}, {u'source': 73, u'target': 48, u'value': 2}, {u'source': 74, u'target': 48, u'value': 2}, {u'source': 74, u'target': 73, u'value': 3}, {u'source': 75, u'target': 69, u'value': 3}, {u'source': 75, u'target': 68, u'value': 3}, {u'source': 75, u'target': 25, u'value': 3}, {u'source': 75, u'target': 48, u'value': 1}, {u'source': 75, u'target': 41, u'value': 1}, {u'source': 75, u'target': 70, u'value': 1}, {u'source': 75, u'target': 71, u'value': 1}, {u'source': 76, u'target': 64, u'value': 1}, {u'source': 76, u'target': 65, u'value': 1}, {u'source': 76, u'target': 66, u'value': 1}, {u'source': 76, u'target': 63, u'value': 1}, {u'source': 76, u'target': 62, u'value': 1}, {u'source': 76, u'target': 48, u'value': 1}, {u'source': 76, u'target': 58, u'value': 1}], u'nodes': [{u'group': 1, u'name': u'Myriel'}, {u'group': 1, u'name': u'Napoleon'}, {u'group': 1, u'name': u'Mlle.Baptistine'}, {u'group': 1, u'name': u'Mme.Magloire'}, {u'group': 1, u'name': u'CountessdeLo'}, {u'group': 1, u'name': u'Geborand'}, {u'group': 1, u'name': u'Champtercier'}, {u'group': 1, u'name': u'Cravatte'}, {u'group': 1, u'name': u'Count'}, {u'group': 1, u'name': u'OldMan'}, {u'group': 2, u'name': u'Labarre'}, {u'group': 2, u'name': u'Valjean'}, {u'group': 3, u'name': u'Marguerite'}, {u'group': 2, u'name': u'Mme.deR'}, {u'group': 2, u'name': u'Isabeau'}, {u'group': 2, u'name': u'Gervais'}, {u'group': 3, u'name': u'Tholomyes'}, {u'group': 3, u'name': u'Listolier'}, {u'group': 3, u'name': u'Fameuil'}, {u'group': 3, u'name': u'Blacheville'}, {u'group': 3, u'name': u'Favourite'}, {u'group': 3, u'name': u'Dahlia'}, {u'group': 3, u'name': u'Zephine'}, {u'group': 3, u'name': u'Fantine'}, {u'group': 4, u'name': u'Mme.Thenardier'}, {u'group': 4, u'name': u'Thenardier'}, {u'group': 5, u'name': u'Cosette'}, {u'group': 4, u'name': u'Javert'}, {u'group': 0, u'name': u'Fauchelevent'}, {u'group': 2, u'name': u'Bamatabois'}, {u'group': 3, u'name': u'Perpetue'}, {u'group': 2, u'name': u'Simplice'}, {u'group': 2, u'name': u'Scaufflaire'}, {u'group': 2, u'name': u'Woman1'}, {u'group': 2, u'name': u'Judge'}, {u'group': 2, u'name': u'Champmathieu'}, {u'group': 2, u'name': u'Brevet'}, {u'group': 2, u'name': u'Chenildieu'}, {u'group': 2, u'name': u'Cochepaille'}, {u'group': 4, u'name': u'Pontmercy'}, {u'group': 6, u'name': u'Boulatruelle'}, {u'group': 4, u'name': u'Eponine'}, {u'group': 4, u'name': u'Anzelma'}, {u'group': 5, u'name': u'Woman2'}, {u'group': 0, u'name': u'MotherInnocent'}, {u'group': 0, u'name': u'Gribier'}, {u'group': 7, u'name': u'Jondrette'}, {u'group': 7, u'name': u'Mme.Burgon'}, {u'group': 8, u'name': u'Gavroche'}, {u'group': 5, u'name': u'Gillenormand'}, {u'group': 5, u'name': u'Magnon'}, {u'group': 5, u'name': u'Mlle.Gillenormand'}, {u'group': 5, u'name': u'Mme.Pontmercy'}, {u'group': 5, u'name': u'Mlle.Vaubois'}, {u'group': 5, u'name': u'Lt.Gillenormand'}, {u'group': 8, u'name': u'Marius'}, {u'group': 5, u'name': u'BaronessT'}, {u'group': 8, u'name': u'Mabeuf'}, {u'group': 8, u'name': u'Enjolras'}, {u'group': 8, u'name': u'Combeferre'}, {u'group': 8, u'name': u'Prouvaire'}, {u'group': 8, u'name': u'Feuilly'}, {u'group': 8, u'name': u'Courfeyrac'}, {u'group': 8, u'name': u'Bahorel'}, {u'group': 8, u'name': u'Bossuet'}, {u'group': 8, u'name': u'Joly'}, {u'group': 8, u'name': u'Grantaire'}, {u'group': 9, u'name': u'MotherPlutarch'}, {u'group': 4, u'name': u'Gueulemer'}, {u'group': 4, u'name': u'Babet'}, {u'group': 4, u'name': u'Claquesous'}, {u'group': 4, u'name': u'Montparnasse'}, {u'group': 5, u'name': u'Toussaint'}, {u'group': 10, u'name': u'Child1'}, {u'group': 10, u'name': u'Child2'}, {u'group': 4, u'name': u'Brujon'}, {u'group': 8, u'name': u'Mme.Hucheloup'}]}
print data.keys()
[u'nodes', u'links']
Get the number of nodes:
N=len(data['nodes'])
N
77
Define the list of edges:
L=len(data['links'])
Edges=[(data['links'][k]['source'], data['links'][k]['target']) for k in range(L)]
Define the Graph object from Edges:
G=ig.Graph(Edges, directed=False)
Extract the node attributes, 'group', and 'name':
data['nodes'][0]
{u'group': 1, u'name': u'Myriel'}
labels=[]
group=[]
for node in data['nodes']:
labels.append(node['name'])
group.append(node['group'])
Get the node positions, set by the Kamada-Kawai layout for 3D graphs:
layt=G.layout('kk', dim=3)
layt
is a list of three elements lists (the coordinates of nodes):
layt[5]
[-2.165298835959627, -3.688710574002034, -1.6020681541017792]
Set data for the Plotly plot of the graph:
Xn=[layt[k][0] for k in range(N)]# x-coordinates of nodes
Yn=[layt[k][1] for k in range(N)]# y-coordinates
Zn=[layt[k][2] for k in range(N)]# z-coordinates
Xe=[]
Ye=[]
Ze=[]
for e in Edges:
Xe+=[layt[e[0]][0],layt[e[1]][0], None]# x-coordinates of edge ends
Ye+=[layt[e[0]][1],layt[e[1]][1], None]
Ze+=[layt[e[0]][2],layt[e[1]][2], None]
import plotly.plotly as py
from plotly.graph_objs import *
trace1=Scatter3d(x=Xe,
y=Ye,
z=Ze,
mode='lines',
line=Line(color='rgb(125,125,125)', width=1),
hoverinfo='none'
)
trace2=Scatter3d(x=Xn,
y=Yn,
z=Zn,
mode='markers',
name='actors',
marker=Marker(symbol='dot',
size=6,
color=group,
colorscale='Viridis',
line=Line(color='rgb(50,50,50)', width=0.5)
),
text=labels,
hoverinfo='text'
)
axis=dict(showbackground=False,
showline=False,
zeroline=False,
showgrid=False,
showticklabels=False,
title=''
)
layout = Layout(
title="Network of coappearances of characters in Victor Hugo's novel<br> Les Miserables (3D visualization)",
width=1000,
height=1000,
showlegend=False,
scene=Scene(
xaxis=XAxis(axis),
yaxis=YAxis(axis),
zaxis=ZAxis(axis),
),
margin=Margin(
t=100
),
hovermode='closest',
annotations=Annotations([
Annotation(
showarrow=False,
text="Data source: <a href='http://bost.ocks.org/mike/miserables/miserables.json'>[1]</a>",
xref='paper',
yref='paper',
x=0,
y=0.1,
xanchor='left',
yanchor='bottom',
font=Font(
size=14
)
)
]), )
data=Data([trace1, trace2])
py.sign_in('empet', 'jkxft90od0')
fig=Figure(data=data, layout=layout)
py.plot(fig, filename='Les-Miserables')
u'https://plot.ly/~empet/9059'
from IPython.core.display import HTML
def css_styling():
styles = open("./custom.css", "r").read()
return HTML(styles)
css_styling()