Announcement: NetworkX 2.0

We’re happy to announce the release of NetworkX 2.0! NetworkX is a Python package for the creation, manipulation, and study of the structure, dynamics, and functions of complex networks.

For more information, please visit our website and our gallery of examples. Please send comments and questions to the networkx-discuss mailing list.

Highlights

This release is the result of over two years of work with over 300 pull requests by 85 contributors. Highlights include:

API Changes

  • Base Graph Class Changes With the release of NetworkX 2.0 we are moving towards a view/iterator reporting API. We used to have two methods for the same property of the graph, one that returns a list and one that returns an iterator. With 2.0 we have replaced them with a view. A view is a read-only object that is quick to create, automatically updated, and provides basic access like iteration, membership and set operations where appropriate. For example, G.nodes() used to return a list and G.nodes_iter() an iterator. Now G.nodes() returns a view and G.nodes_iter() is removed. G.degree() returns a view with (node, degree) iteration, so that dict(G.degree()) returns a dict keyed by node with degree as value. The old behavior

    >>> G = nx.complete_graph(5)
    >>> G.nodes()  
    [0, 1, 2, 3, 4]
    >>> G.nodes_iter()  
    <dictionary-keyiterator at ...>
    

    has changed to

    >>> G = nx.complete_graph(5)
    >>> G.nodes()
    NodeView((0, 1, 2, 3, 4))
    >>> list(G.nodes())
    [0, 1, 2, 3, 4]
    

    New feature include lookup of node and edge data from the views, property access without parentheses, and set operations.

    >>> G.add_node(3, color='blue')
    >>> G.nodes[3]
    {'color': 'blue'}
    >>> G.nodes & {3, 4, 5}
    set([3, 4])
    

    The following methods have changed:

    • Graph/MultiGraph
      • G.nodes()
      • G.edges()
      • G.neighbors()
      • G.adjacency_list() and G.adjacency_iter() to G.adjacency()
      • G.degree()
      • G.nodes_with_selfloops()
      • G.selfloop_edges()
    • DiGraph/MultiDiGraph
      • G.nodes()
      • G.edges()
      • G.in_edges()
      • G.out_edges()
      • G.degree()
      • G.in_degree()
      • G.out_degree()
    Many subclasses have been changed accordingly such as:
    • AntiGraph
    • OrderedGraph and friends
    • Examples such as ThinGraph that inherit from Graph
  • [#2107] The Graph class methods add_edge and add_edges_from no longer allow the use of the attr_dict parameter. Instead use keyword arguments. Thus G.add_edge(1, 2, {'color': 'red'}) becomes G.add_edge(1, 2, color='red'). Note that this only works if the attribute name is a string. For non-string attributes you will need to add the edge and then update manually using e.g. G.edges[1, 2].update({0: "zero"})

  • [#1577] In addition to minimum spanning trees, a new function for calculating maximum spanning trees is now provided. The new API consists of four functions: minimum_spanning_edges, maximum_spanning_edges, minimum_spanning_tree, and maximum_spanning_tree. All of these functions accept an algorithm parameter which specifies the algorithm to use when finding the minimum or maximum spanning tree. Currently, Kruskal’s and Prim’s algorithms are implemented, defined as ‘kruskal’ and ‘prim’, respectively. If nothing is specified, Kruskal’s algorithm is used. For example, to calculate the maximum spanning tree of a graph using Kruskal’s algorithm, the function maximum_spanning_tree has to be called like:

    >>> nx.maximum_spanning_tree(G, algorithm='kruskal')
    

    The algorithm parameter is new and appears before the existing weight parameter. So existing code that did not explicitly name the optional weight parameter will need to be updated:

    >>> nx.minimum_spanning_tree(G, 'mass')  # old
    >>> nx.minimum_spanning_tree(G, weight='mass') # new
    

    In the above, we are still relying on the the functions being imported into the top-level namespace. We do not have immediate plans to deprecate this approach, but we recommend the following instead:

    >>> from networkx.algorithms import tree
    # recommended
    >>> tree.minimum_spanning_tree(G, algorithm='kruskal', weight='mass')
    >>> tree.minimum_spanning_edges(G, algorithm='prim', weight='mass')
    
  • [#1445] Most of the shortest_path algorithms now raise a NodeNotFound exception when a source or a target are not present in the graph.

  • [#2326] Centrality algorithms were harmonized with respect to the default behavior of the weight parameter. The default value of the weight keyword argument has been changed from weight to None. This affects the following centrality functions:

    • approximate_current_flow_betweenness_centrality()
    • current_flow_betweenness_centrality()
    • current_flow_betweenness_centrality_subset()
    • current_flow_closeness_centrality()
    • edge_current_flow_betweenness_centrality()
    • edge_current_flow_betweenness_centrality_subset()
    • eigenvector_centrality()
    • eigenvector_centrality_numpy()
    • katz_centrality()
    • katz_centrality_numpy()
  • [#2420] New community detection algorithm provided. Fluid Communities is an asynchronous algorithm based on the simple idea of fluids interacting in an environment, expanding and pushing each other. The algorithm is completely described in “Fluid Communities: A Competitive and Highly Scalable Community Detection Algorithm”.

  • [#2510 and #2508] single_source_dijkstra, multi_source_dijkstra and functions that use these now have new behavior when target is specified. Instead of returning dicts for distances and paths a 2-tuple of (distance, path) is returned. When target is not specified the return value is still 2 dicts.

  • [#2553] set_node_attributes() and set_edge_attributes() now accept dict-of-dict input of shape {node/edge: {name: value}} in addition to previous valid inputs: {node/edge: value} and value. The order of the parameters changed also: The second parameter “values” is the value argument and the third parameter “name” is the name of the attribute. “name” has default value None in which case “values” must be the newly allowed form containing names. Previously “name” came second without default, and “values” came third.

  • [#2604] Move selfloop methods out of base classes to networkx functions. G.number_of_selfloops(), G.selfloop_edges(), G.nodes_with_selfloops() are now nx.number_of_selfloops(G), nx.selfloop_edges(G), nx.nodes_with_selfloops(G).

    G.node and G.edge are removed. Their functionality are replaced by G.nodes and G.edges.

  • [#2558] Previously, the function from_pandas_dataframe assumed that the dataframe has edge-list like structures, but to_pandas_dataframe generates an adjacency matrix. We now provide four functions from_pandas_edgelist, to_pandas_edgelist, from_pandas_adjacency, and to_pandas_adjacency.

  • [#2620] Removed draw_nx, please use draw or draw_networkx.

  • [#2498] Starting in NetworkX 2.1 the parameter alpha is deprecated and replaced with the customizable p_dist function parameter, which defaults to r^-2 if p_dist is not supplied. To reproduce networks of earlier NetworkX versions, a custom function needs to be defined and passed as the p_dist parameter. For example, if the parameter alpha = 2 was used in NetworkX 2.0, the custom function def custom_dist(r): r**2 can be passed in versions >=2.1 as the parameter p_dist = custom_dist to produce an equivalent network.

Deprecations

The following deprecated functions will be removed in 21.

  • The function bellman_ford has been deprecated in favor of bellman_ford_predecessor_and_distance.
  • The functions to_pandas_dataframe and from_pandas_dataframe have been deprecated in favor of to_pandas_adjacency, from_pandas_adjacency, to_pandas_edgelist, and from_pandas_edgelist.

Contributors to this release

<output of contribs.py>

Pull requests merged in this release

<output of contribs.py>