1

I am using ipycytoscape for building networks, but it is not clear to me how to let node size being dependent on node's degree and add labels to each node. My network has two columns, one for Nodes and one for Target.

Data
Nodes      Target
A           B
B           C
B           D
C           B
E          nan


G = nx.from_pandas_edgelist(df, source='Nodes', target='Target') 

Currently I am building the graph as follows:

cytoscapeobj = ipycytoscape.CytoscapeWidget()
cytoscapeobj.graph.add_graph_from_networkx(G, labels) # labels however is not adding any label to the node, so probably the location is wrong
cytoscapeobj

I know about customization using set style:

cytoscapeobj.set_style(my_style)

but I do not know how to change it in order to visualize labels and node's size depending on node's degree. Has anyone ever had experience with ipycytoscape?

V_sqrt
  • 537
  • 8
  • 28

1 Answers1

1

To be able to visualize the labels, you will need to add the node attributes to your networkx graph and set the appropriate style. For the style, you can define one for all nodes to display the label. To control the size of the nodes based on degree, you will need to add a degree column to the node dataframe. You can do this by using networkx degree API. You will first need to create the graph, then recreate the node dataframe based on networkx degree API and add the node attributes that contain the degree attribute to be able render the graph taking the degree information into account.

Here is the complete solution:

import ipycytoscape as cy
import networkx as nx
import pandas as pd

edge_data = {
    'source': ['A', 'B', 'B', 'C'],
    'target': ['B', 'C', 'D', 'B'],
}
link_df = pd.DataFrame.from_dict(edge_data)
node_data = {
    'id': ['A', 'B', 'C', 'D', 'E']
}
node_df = pd.DataFrame.from_dict(node_data)

G = nx.from_pandas_edgelist(link_df)
node_df = pd.DataFrame(G.degree(), columns=['id', 'degree'])
nx.set_node_attributes(G, node_df.set_index('id').to_dict('index'))
cytoscapeobj = cy.CytoscapeWidget()
cytoscapeobj.graph.add_graph_from_networkx(G)

cytoscapeobj.set_style(
    [
        {
             'selector': 'node',
             'style': {
                 'font-family': 'helvetica',
                 'font-size': '20px',
                 'label': 'data(id)'
             }
        },
        {
             'selector': 'edge',
             'style': {
                 'font-family': 'helvetica',
                 'font-size': '20px'
             }
        },
        {
             'selector': 'node[degree>0]',
             'style': {
                 'width': '100px',
                 'height': '100px'
             }
        },
        {
             'selector': 'node[degree>1]',
             'style': {
                 'width': '150px',
                 'height': '150px'
             }
        },
        {
             'selector': 'node[degree>2]',
             'style': {
                 'width': '200px',
                 'height': '200px'
             }
        }
    ]
)
cytoscapeobj

You can use % instead of px in the width and height if you want relative instead of absolute values.

  • Thank you so much, Martin. For labelling, the code you provided works fine. However, it does not change the size of nodes, because the degree has not been calculated in the dataframe. I would have thought it was possible using some function in networkx. Do you know if it would be possible to do it automatically? I could have nodes even with degree=100 so it would be not so easy to define selectors individually – V_sqrt Aug 19 '21 at 23:30
  • Thanks, @Martin Dubuc. It is not clear what you mean when you say " based on value as in: – ". I will consider to add that column in my df. In case you might interested, I have opened another question on ipycytoscape. If you might want to have a look: https://stackoverflow.com/questions/68895606/how-to-create-multiple-graphs-networkx – V_sqrt Aug 23 '21 at 19:42
  • I edited my last answer to address the addition of a degree column using networkx degree API. Once a graph is created, networkx can return the degree of each node as a list using G.degree(), where G is the networkx graph object created beforehand. – Martin Dubuc Aug 24 '21 at 12:50
  • Hi Martin, may I ask you to merge in one answer your proposed solution so I can mark it? I am still having issues with spark, so I cannot test the solution (if it works correctly), but I will assign the bounty later. Thanks – V_sqrt Aug 26 '21 at 12:16
  • 1
    I have merged the two solutions into this answer and removed any reference to Spark. You should be able to test the code, given you installed the ipycytoscape, networkx and pandas packages. – Martin Dubuc Aug 26 '21 at 15:47
  • Thank you so much Martin for all the help – V_sqrt Aug 26 '21 at 16:04
  • quick question: in case of attribute and column (Weight) in my df, should I add `'width' : 'mapData(weight)'` in the `'selector': 'edge'`? Thanks a lot. Let me know if you prefer a new question to answer in a separate post and I will open it – V_sqrt Aug 26 '21 at 18:55
  • 1
    Yes, you can define the width in the edge style based on some edge attribute. You need an extra statement though to make that attribute available to the networkx graph. If your edge databframe is defined as: edge_data = { 'source': ['A', 'B', 'B', 'C'], 'target': ['B', 'C', 'D', 'B'], 'weight': ['1', '1', '5', '10'] } link_df = pd.DataFrame.from_dict(edge_data) You have to issue command: G = nx.from_pandas_edgelist(link_df, edge_attr=True) Then set the style for the edge adding the width attribute to the 'style' section ('selector': 'edge'): 'width': 'data(weight)' – Martin Dubuc Aug 27 '21 at 15:30
  • Thank you so much, Martin. Very greatly appreciated your help – V_sqrt Aug 28 '21 at 22:56