Plotly plot of the Coauthorship network of scientists working on network theory and experiment

In this Jupyter Notebook we plot the same network, first as an igraph.Graph object, with the Kamada-Kawai layout, and then as a networkx.Graph, with the Fruchterman-Reingold layout.

In [1]:
import igraph as ig
print ig.__version__
0.7.1

The graph data are read from a gml file, posted at UC Irvine Network Data Repository:

In [2]:
G=ig.Graph.Read_GML('netscience.gml')
In [3]:
labels=list(G.vs['label'])
In [4]:
N=len(labels)
N
Out[4]:
1589
In [5]:
labels[:10]
Out[5]:
['ABRAMSON, G',
 'KUPERMAN, M',
 'ACEBRON, J',
 'BONILLA, L',
 'PEREZVICENTE, C',
 'RITORT, F',
 'SPIGLER, R',
 'ADAMIC, L',
 'ADAR, E',
 'HUBERMAN, B']
In [6]:
E=[e.tuple for e in G.es]# list of edges
len(E)
Out[6]:
2742
In [7]:
layt=G.layout('kk') #kamada-kawai layout
In [55]:
type(layt)
Out[55]:
igraph.layout.Layout
In [27]:
layt[:4]
Out[27]:
[[-12.02504184293005, 23.453677963101],
 [-11.8821062828348, 24.395338667886193],
 [-2.239376063112759, 13.394766956945588],
 [-1.5358422588024399, 13.316073422546394]]
In [7]:
import plotly.plotly as py
from plotly.graph_objs import *

Define data for the Plotly plot:

In [9]:
Xn=[layt[k][0] for k in range(N)]
Yn=[layt[k][1] for k in range(N)]
Xe=[]
Ye=[]
for e in E:
    Xe+=[layt[e[0]][0],layt[e[1]][0], None]
    Ye+=[layt[e[0]][1],layt[e[1]][1], None] 
In [12]:
trace1=Scatter(x=Xe,
               y=Ye,
               mode='lines',
               line=Line(color='rgb(210,210,210)', width=1),
               hoverinfo='none'
               )
trace2=Scatter(x=Xn,
               y=Yn,
               mode='markers',
               name='ntw',
               marker=Marker(symbol='dot',
                             size=5, 
                             color='#6959CD',
                             line=Line(color='rgb(50,50,50)', width=0.5)
                             ),
               text=labels,
               hoverinfo='text'
               )

Set the plot layout (don't confuse with graph layout!!!):

In [13]:
axis=dict(showline=False, # hide axis line, grid, ticklabels and  title
          zeroline=False,
          showgrid=False,
          showticklabels=False,
          title='' 
          )
In [42]:
width=800
height=800
layout=Layout(title= "Coauthorship network of scientists working on network theory and experiment"+\
              "<br> Data source: <a href='https://networkdata.ics.uci.edu/data.php?id=11'> [1]</a>",  
    font= Font(size=12),
    showlegend=False,
    autosize=False,
    width=width,
    height=height,
    xaxis=XAxis(axis),
    yaxis=YAxis(axis),          
    margin=Margin(
        l=40,
        r=40,
        b=85,
        t=100,
    ),
    hovermode='closest',
    annotations=Annotations([
           Annotation(
           showarrow=False, 
            text='This igraph.Graph has the Kamada-Kawai layout',  
            xref='paper',     
            yref='paper',     
            x=0,  
            y=-0.1,  
            xanchor='left',   
            yanchor='bottom',  
            font=Font(
            size=14 
            )     
            )
        ]),           
    )
In [43]:
data=Data([trace1, trace2])
py.sign_in('empet', 'my_api_key')
fig=Figure(data=data, layout=layout)
py.plot(fig, filename='Coautorship-network-igraph') 
Out[43]:
u'https://plot.ly/~empet/9110'
Coauthorship network of scientists working on network theory and experiment<br> Data source: <a href='https://networkdata.ics.uci.edu/data.php?id=11'> [1]</a>

Now let us read the same gml file, define the network as a networkx.Graph, and plot it with Fruchterman Reingold layout (networkx does not provide the Kamada-Kawai layout):

In [16]:
import networkx as nx
In [18]:
nx.__version__
Out[18]:
'1.10'
In [17]:
G=nx.read_gml('netscience.gml')
---------------------------------------------------------------------------
NetworkXError                             Traceback (most recent call last)
<ipython-input-17-83ad480f0792> in <module>()
----> 1 G=nx.read_gml('netscience.gml')

/miniconda/lib/python2.7/site-packages/networkx/readwrite/gml.pyc in read_gml(path, label, destringizer)

/miniconda/lib/python2.7/site-packages/networkx/utils/decorators.pyc in _open_file(func, *args, **kwargs)
    218         # Finally, we call the original function, making sure to close the fobj.
    219         try:
--> 220             result = func(*new_args, **kwargs)
    221         finally:
    222             if close_fobj:

/miniconda/lib/python2.7/site-packages/networkx/readwrite/gml.pyc in read_gml(path, label, destringizer)
    208             yield line
    209 
--> 210     G = parse_gml_lines(filter_lines(path), label, destringizer)
    211     return G
    212 

/miniconda/lib/python2.7/site-packages/networkx/readwrite/gml.pyc in parse_gml_lines(lines, label, destringizer)
    381 
    382     tokens = tokenize()
--> 383     graph = parse_graph()
    384 
    385     directed = graph.pop('directed', False)

/miniconda/lib/python2.7/site-packages/networkx/readwrite/gml.pyc in parse_graph()
    370 
    371     def parse_graph():
--> 372         curr_token, dct = parse_kv(next(tokens))
    373         if curr_token[0] is not None:  # EOF
    374             unexpected(curr_token, 'EOF')

/miniconda/lib/python2.7/site-packages/networkx/readwrite/gml.pyc in parse_kv(curr_token)
    353                     except ValueError:
    354                         pass
--> 355                 curr_token = next(tokens)
    356             elif type == 4:  # dict start
    357                 curr_token, value = parse_dict(curr_token)

/miniconda/lib/python2.7/site-packages/networkx/readwrite/gml.pyc in tokenize()
    321                 else:
    322                     raise NetworkXError('cannot tokenize %r at (%d, %d)' %
--> 323                                         (line[pos:], lineno + 1, pos + 1))
    324             lineno += 1
    325         yield (None, None, lineno + 1, 1)  # EOF

NetworkXError: cannot tokenize u'graph' at (2, 1)

Because networkx cannot read the gml file (why?!!), we define the networkx.Graph from data provided by the igraph approach above.

In [19]:
V=range(N)# list of vertices
In [20]:
g=nx.Graph()
g.add_nodes_from(V)
g.add_edges_from(E)# E is the list of edges

Get node positions, set by Fruchterman-Reingold layout:

In [24]:
pos=nx.fruchterman_reingold_layout(g) 
In [25]:
type(pos)
Out[25]:
dict
In [28]:
pos[0]
Out[28]:
array([-0.67079008,  0.53285509])

Data for the Plotly plot of the same network but with a different layout:

In [29]:
Xv=[pos[k][0] for k in range(N)]
Yv=[pos[k][1] for k in range(N)]
Xed=[]
Yed=[]
for edge in E:
    Xed+=[pos[edge[0]][0],pos[edge[1]][0], None]
    Yed+=[pos[edge[0]][1],pos[edge[1]][1], None] 
In [30]:
trace3=Scatter(x=Xed,
               y=Yed,
               mode='lines',
               line=Line(color='rgb(210,210,210)', width=1),
               hoverinfo='none'
               )
trace4=Scatter(x=Xv,
               y=Yv,
               mode='markers',
               name='net',
               marker=Marker(symbol='dot',
                             size=5, 
                             color='#6959CD',
                             line=Line(color='rgb(50,50,50)', width=0.5)
                             ),
               text=labels,
               hoverinfo='text'
               )
In [59]:
annot="This networkx.Graph has the Fruchterman-Reingold layout<br>Code:"+\
"<a href='http://nbviewer.ipython.org/gist/empet/07ea33b2e4e0b84193bd'> [2]</a>"
In [60]:
data1=Data([trace3, trace4])
fig1=Figure(data=data1, layout=layout)
fig1['layout']['annotations'][0]['text']=annot
py.plot(fig1, filename='Coautorship-network-nx')
Out[60]:
u'https://plot.ly/~empet/9614'
Coauthorship network of scientists working on network theory and experiment<br> Data source: <a href='https://networkdata.ics.uci.edu/data.php?id=11'> [1]</a>

Zoom in a selected region of nodes to see that edges are also plotted, but due to the node positions assigned by FR layout, they are invisible at the first sight.

We get a similar plot setting pos=nx.spring_layout(g).

In [8]:
from IPython.core.display import HTML
def  css_styling():
    styles = open("./custom.css", "r").read()
    return HTML(styles)
css_styling()
Out[8]: