Repository: networkx/networkx

Issue:
_relabel_copy and OrderedGraph
The current behavior of `_relabel_copy()` is somewhat unintuitive for OrderedGraphs, where the nodes in the newly created graph are ordered according to the edge iterator of the original graph, not the node iterator. I think this would be fixed by placing `H.add_nodes_from(mapping.get(n, n) for n in G)` at the beginning of the function.


Discussion:
I agree. This would bring that function into line with other graph copy/subgraph code.
I suggest the order should be:

    1. update the graph attribute dict.
    2. add nodes and update node attributes.
    3. add edges and edge attributes.

+1

Resolving patch:
diff --git a/networkx/relabel.py b/networkx/relabel.py
--- a/networkx/relabel.py
+++ b/networkx/relabel.py
@@ -6,10 +6,11 @@
 #    BSD license.
 import networkx as nx
 __author__ = """\n""".join(['Aric Hagberg <aric.hagberg@gmail.com>',
-                           'Pieter Swart (swart@lanl.gov)',
-                           'Dan Schult (dschult@colgate.edu)'])
+                            'Pieter Swart (swart@lanl.gov)',
+                            'Dan Schult (dschult@colgate.edu)'])
 __all__ = ['convert_node_labels_to_integers', 'relabel_nodes']
 
+
 def relabel_nodes(G, mapping, copy=True):
     """Relabel the nodes of the graph G.
 
@@ -76,21 +77,21 @@ def relabel_nodes(G, mapping, copy=True):
     Only the nodes specified in the mapping will be relabeled.
 
     The keyword setting copy=False modifies the graph in place.
-    Relabel_nodes avoids naming collisions by building a 
+    Relabel_nodes avoids naming collisions by building a
     directed graph from ``mapping`` which specifies the order of
     relabelings. Naming collisions, such as a->b, b->c, are ordered
     such that "b" gets renamed to "c" before "a" gets renamed "b".
-    In cases of circular mappings (e.g. a->b, b->a), modifying the 
+    In cases of circular mappings (e.g. a->b, b->a), modifying the
     graph is not possible in-place and an exception is raised.
     In that case, use copy=True.
-    
+
     See Also
     --------
     convert_node_labels_to_integers
     """
     # you can pass a function f(old_label)->new_label
     # but we'll just make a dictionary here regardless
-    if not hasattr(mapping,"__getitem__"):
+    if not hasattr(mapping, "__getitem__"):
         m = dict((n, mapping(n)) for n in G)
     else:
         m = mapping
@@ -131,38 +132,39 @@ def _relabel_inplace(G, mapping):
         try:
             G.add_node(new, **G.node[old])
         except KeyError:
-            raise KeyError("Node %s is not in the graph"%old)
+            raise KeyError("Node %s is not in the graph" % old)
         if multigraph:
             new_edges = [(new, new if old == target else target, key, data)
-                         for (_,target,key,data)
+                         for (_, target, key, data)
                          in G.edges(old, data=True, keys=True)]
             if directed:
                 new_edges += [(new if old == source else source, new, key, data)
-                              for (source, _, key,data)
+                              for (source, _, key, data)
                               in G.in_edges(old, data=True, keys=True)]
         else:
             new_edges = [(new, new if old == target else target, data)
-                         for (_,target,data) in G.edges(old, data=True)]
+                         for (_, target, data) in G.edges(old, data=True)]
             if directed:
-                new_edges += [(new if old == source else source,new,data)
-                              for (source,_,data) in G.in_edges(old, data=True)]
+                new_edges += [(new if old == source else source, new, data)
+                              for (source, _, data) in G.in_edges(old, data=True)]
         G.remove_node(old)
         G.add_edges_from(new_edges)
     return G
 
+
 def _relabel_copy(G, mapping):
     H = G.__class__()
+    H.add_nodes_from(mapping.get(n, n) for n in G)
+    H._node.update(dict((mapping.get(n, n), d.copy()) for n, d in G.node.items()))
     if G.name:
         H.name = "(%s)" % G.name
     if G.is_multigraph():
-        H.add_edges_from( (mapping.get(n1, n1),mapping.get(n2, n2),k,d.copy())
-                          for (n1,n2,k,d) in G.edges(keys=True, data=True))
+        H.add_edges_from((mapping.get(n1, n1), mapping.get(n2, n2), k, d.copy())
+                         for (n1, n2, k, d) in G.edges(keys=True, data=True))
     else:
-        H.add_edges_from( (mapping.get(n1, n1),mapping.get(n2, n2),d.copy())
-                          for (n1, n2, d) in G.edges(data=True))
+        H.add_edges_from((mapping.get(n1, n1), mapping.get(n2, n2), d.copy())
+                         for (n1, n2, d) in G.edges(data=True))
 
-    H.add_nodes_from(mapping.get(n, n) for n in G)
-    H._node.update(dict((mapping.get(n, n), d.copy()) for n,d in G.node.items()))
     H.graph.update(G.graph.copy())
 
     return H
@@ -200,27 +202,27 @@ def convert_node_labels_to_integers(G, first_label=0, ordering="default",
     --------
     relabel_nodes
     """
-    N = G.number_of_nodes()+first_label
+    N = G.number_of_nodes() + first_label
     if ordering == "default":
         mapping = dict(zip(G.nodes(), range(first_label, N)))
     elif ordering == "sorted":
         nlist = sorted(G.nodes())
         mapping = dict(zip(nlist, range(first_label, N)))
     elif ordering == "increasing degree":
-        dv_pairs = [(d,n) for (n,d) in G.degree()]
-        dv_pairs.sort() # in-place sort from lowest to highest degree
-        mapping = dict(zip([n for d,n in dv_pairs], range(first_label, N)))
+        dv_pairs = [(d, n) for (n, d) in G.degree()]
+        dv_pairs.sort()  # in-place sort from lowest to highest degree
+        mapping = dict(zip([n for d, n in dv_pairs], range(first_label, N)))
     elif ordering == "decreasing degree":
-        dv_pairs = [(d,n) for (n,d) in G.degree()]
-        dv_pairs.sort() # in-place sort from lowest to highest degree
+        dv_pairs = [(d, n) for (n, d) in G.degree()]
+        dv_pairs.sort()  # in-place sort from lowest to highest degree
         dv_pairs.reverse()
-        mapping = dict(zip([n for d,n in dv_pairs], range(first_label, N)))
+        mapping = dict(zip([n for d, n in dv_pairs], range(first_label, N)))
     else:
-        raise nx.NetworkXError('Unknown node ordering: %s'%ordering)
+        raise nx.NetworkXError('Unknown node ordering: %s' % ordering)
     H = relabel_nodes(G, mapping)
-    H.name = "("+G.name+")_with_int_labels"
+    H.name = "(" + G.name + ")_with_int_labels"
     # create node attribute with the old label
     if label_attribute is not None:
         nx.set_node_attributes(H, label_attribute,
-                               dict((v,k) for k,v in mapping.items()))
+                               dict((v, k) for k, v in mapping.items()))
     return H


Test patch:
diff --git a/networkx/tests/test_relabel.py b/networkx/tests/test_relabel.py
--- a/networkx/tests/test_relabel.py
+++ b/networkx/tests/test_relabel.py
@@ -3,153 +3,161 @@
 from networkx import *
 from networkx.convert import *
 from networkx.algorithms.operators import *
-from networkx.generators.classic import barbell_graph,cycle_graph
+from networkx.generators.classic import barbell_graph, cycle_graph
 from networkx.testing import *
 
+
 class TestRelabel():
     def test_convert_node_labels_to_integers(self):
         # test that empty graph converts fine for all options
-        G=empty_graph()
-        H=convert_node_labels_to_integers(G,100)
+        G = empty_graph()
+        H = convert_node_labels_to_integers(G, 100)
         assert_equal(H.name, '(empty_graph(0))_with_int_labels')
         assert_equal(list(H.nodes()), [])
         assert_equal(list(H.edges()), [])
 
-        for opt in ["default", "sorted", "increasing degree",
-                    "decreasing degree"]:
-            G=empty_graph()
-            H=convert_node_labels_to_integers(G,100, ordering=opt)
+        for opt in ["default", "sorted", "increasing degree", "decreasing degree"]:
+            G = empty_graph()
+            H = convert_node_labels_to_integers(G, 100, ordering=opt)
             assert_equal(H.name, '(empty_graph(0))_with_int_labels')
             assert_equal(list(H.nodes()), [])
             assert_equal(list(H.edges()), [])
 
-        G=empty_graph()
-        G.add_edges_from([('A','B'),('A','C'),('B','C'),('C','D')])
-        G.name="paw"
-        H=convert_node_labels_to_integers(G)
+        G = empty_graph()
+        G.add_edges_from([('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'D')])
+        G.name = "paw"
+        H = convert_node_labels_to_integers(G)
         degH = (d for n, d in H.degree())
         degG = (d for n, d in G.degree())
         assert_equal(sorted(degH), sorted(degG))
 
-        H=convert_node_labels_to_integers(G,1000)
+        H = convert_node_labels_to_integers(G, 1000)
         degH = (d for n, d in H.degree())
         degG = (d for n, d in G.degree())
         assert_equal(sorted(degH), sorted(degG))
         assert_nodes_equal(H.nodes(), [1000, 1001, 1002, 1003])
 
-        H=convert_node_labels_to_integers(G,ordering="increasing degree")
+        H = convert_node_labels_to_integers(G, ordering="increasing degree")
         degH = (d for n, d in H.degree())
         degG = (d for n, d in G.degree())
         assert_equal(sorted(degH), sorted(degG))
-        assert_equal(degree(H,0), 1)
-        assert_equal(degree(H,1), 2)
-        assert_equal(degree(H,2), 2)
-        assert_equal(degree(H,3), 3)
+        assert_equal(degree(H, 0), 1)
+        assert_equal(degree(H, 1), 2)
+        assert_equal(degree(H, 2), 2)
+        assert_equal(degree(H, 3), 3)
 
-        H=convert_node_labels_to_integers(G,ordering="decreasing degree")
+        H = convert_node_labels_to_integers(G, ordering="decreasing degree")
         degH = (d for n, d in H.degree())
         degG = (d for n, d in G.degree())
         assert_equal(sorted(degH), sorted(degG))
-        assert_equal(degree(H,0), 3)
-        assert_equal(degree(H,1), 2)
-        assert_equal(degree(H,2), 2)
-        assert_equal(degree(H,3), 1)
+        assert_equal(degree(H, 0), 3)
+        assert_equal(degree(H, 1), 2)
+        assert_equal(degree(H, 2), 2)
+        assert_equal(degree(H, 3), 1)
 
-        H=convert_node_labels_to_integers(G,ordering="increasing degree",
-                                          label_attribute='label')
+        H = convert_node_labels_to_integers(G, ordering="increasing degree",
+                                            label_attribute='label')
         degH = (d for n, d in H.degree())
         degG = (d for n, d in G.degree())
         assert_equal(sorted(degH), sorted(degG))
-        assert_equal(degree(H,0), 1)
-        assert_equal(degree(H,1), 2)
-        assert_equal(degree(H,2), 2)
-        assert_equal(degree(H,3), 3)
+        assert_equal(degree(H, 0), 1)
+        assert_equal(degree(H, 1), 2)
+        assert_equal(degree(H, 2), 2)
+        assert_equal(degree(H, 3), 3)
 
         # check mapping
-        assert_equal(H.node[3]['label'],'C')
-        assert_equal(H.node[0]['label'],'D')
-        assert_true(H.node[1]['label']=='A' or H.node[2]['label']=='A')
-        assert_true(H.node[1]['label']=='B' or H.node[2]['label']=='B')
+        assert_equal(H.node[3]['label'], 'C')
+        assert_equal(H.node[0]['label'], 'D')
+        assert_true(H.node[1]['label'] == 'A' or H.node[2]['label'] == 'A')
+        assert_true(H.node[1]['label'] == 'B' or H.node[2]['label'] == 'B')
 
     def test_convert_to_integers2(self):
-        G=empty_graph()
-        G.add_edges_from([('C','D'),('A','B'),('A','C'),('B','C')])
-        G.name="paw"
-        H=convert_node_labels_to_integers(G,ordering="sorted")
+        G = empty_graph()
+        G.add_edges_from([('C', 'D'), ('A', 'B'), ('A', 'C'), ('B', 'C')])
+        G.name = "paw"
+        H = convert_node_labels_to_integers(G, ordering="sorted")
         degH = (d for n, d in H.degree())
         degG = (d for n, d in G.degree())
         assert_equal(sorted(degH), sorted(degG))
 
-        H=convert_node_labels_to_integers(G,ordering="sorted",
-                                          label_attribute='label')
-        assert_equal(H.node[0]['label'],'A')
-        assert_equal(H.node[1]['label'],'B')
-        assert_equal(H.node[2]['label'],'C')
-        assert_equal(H.node[3]['label'],'D')
+        H = convert_node_labels_to_integers(G, ordering="sorted",
+                                            label_attribute='label')
+        assert_equal(H.node[0]['label'], 'A')
+        assert_equal(H.node[1]['label'], 'B')
+        assert_equal(H.node[2]['label'], 'C')
+        assert_equal(H.node[3]['label'], 'D')
 
     @raises(nx.NetworkXError)
     def test_convert_to_integers_raise(self):
         G = nx.Graph()
-        H=convert_node_labels_to_integers(G,ordering="increasing age")
-
+        H = convert_node_labels_to_integers(G, ordering="increasing age")
 
     def test_relabel_nodes_copy(self):
-        G=empty_graph()
-        G.add_edges_from([('A','B'),('A','C'),('B','C'),('C','D')])
-        mapping={'A':'aardvark','B':'bear','C':'cat','D':'dog'}
-        H=relabel_nodes(G,mapping)
+        G = empty_graph()
+        G.add_edges_from([('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'D')])
+        mapping = {'A': 'aardvark', 'B': 'bear', 'C': 'cat', 'D': 'dog'}
+        H = relabel_nodes(G, mapping)
         assert_nodes_equal(H.nodes(), ['aardvark', 'bear', 'cat', 'dog'])
 
     def test_relabel_nodes_function(self):
-        G=empty_graph()
-        G.add_edges_from([('A','B'),('A','C'),('B','C'),('C','D')])
+        G = empty_graph()
+        G.add_edges_from([('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'D')])
         # function mapping no longer encouraged but works
+
         def mapping(n):
             return ord(n)
-        H=relabel_nodes(G,mapping)
+        H = relabel_nodes(G, mapping)
         assert_nodes_equal(H.nodes(), [65, 66, 67, 68])
 
     def test_relabel_nodes_graph(self):
-        G=Graph([('A','B'),('A','C'),('B','C'),('C','D')])
-        mapping={'A':'aardvark','B':'bear','C':'cat','D':'dog'}
-        H=relabel_nodes(G,mapping)
+        G = Graph([('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'D')])
+        mapping = {'A': 'aardvark', 'B': 'bear', 'C': 'cat', 'D': 'dog'}
+        H = relabel_nodes(G, mapping)
         assert_nodes_equal(H.nodes(), ['aardvark', 'bear', 'cat', 'dog'])
 
+    def test_relabel_nodes_orderedgraph(self):
+        G = OrderedGraph()
+        G.add_nodes_from([1, 2, 3])
+        G.add_edges_from([(1, 3), (2, 3)])
+        mapping = {1: 'a', 2: 'b', 3: 'c'}
+        H = relabel_nodes(G, mapping)
+        assert list(H.nodes) == ['a', 'b', 'c']
+
     def test_relabel_nodes_digraph(self):
-        G=DiGraph([('A','B'),('A','C'),('B','C'),('C','D')])
-        mapping={'A':'aardvark','B':'bear','C':'cat','D':'dog'}
-        H=relabel_nodes(G,mapping,copy=False)
+        G = DiGraph([('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'D')])
+        mapping = {'A': 'aardvark', 'B': 'bear', 'C': 'cat', 'D': 'dog'}
+        H = relabel_nodes(G, mapping, copy=False)
         assert_nodes_equal(H.nodes(), ['aardvark', 'bear', 'cat', 'dog'])
 
     def test_relabel_nodes_multigraph(self):
-        G=MultiGraph([('a','b'),('a','b')])
-        mapping={'a':'aardvark','b':'bear'}
-        G=relabel_nodes(G,mapping,copy=False)
-        assert_nodes_equal(G.nodes(),['aardvark', 'bear'])
-        assert_edges_equal(G.edges(),[('aardvark', 'bear'), ('aardvark', 'bear')])
+        G = MultiGraph([('a', 'b'), ('a', 'b')])
+        mapping = {'a': 'aardvark', 'b': 'bear'}
+        G = relabel_nodes(G, mapping, copy=False)
+        assert_nodes_equal(G.nodes(), ['aardvark', 'bear'])
+        assert_edges_equal(G.edges(), [('aardvark', 'bear'), ('aardvark', 'bear')])
 
     def test_relabel_nodes_multidigraph(self):
-        G=MultiDiGraph([('a','b'),('a','b')])
-        mapping={'a':'aardvark','b':'bear'}
-        G=relabel_nodes(G,mapping,copy=False)
-        assert_nodes_equal(G.nodes(),['aardvark', 'bear'])
-        assert_edges_equal(G.edges(),[('aardvark', 'bear'), ('aardvark', 'bear')])
+        G = MultiDiGraph([('a', 'b'), ('a', 'b')])
+        mapping = {'a': 'aardvark', 'b': 'bear'}
+        G = relabel_nodes(G, mapping, copy=False)
+        assert_nodes_equal(G.nodes(), ['aardvark', 'bear'])
+        assert_edges_equal(G.edges(), [('aardvark', 'bear'), ('aardvark', 'bear')])
 
     def test_relabel_isolated_nodes_to_same(self):
-        G=Graph()
+        G = Graph()
         G.add_nodes_from(range(4))
-        mapping={1:1}
-        H=relabel_nodes(G, mapping, copy=False)
+        mapping = {1: 1}
+        H = relabel_nodes(G, mapping, copy=False)
         assert_nodes_equal(H.nodes(), list(range(4)))
 
     @raises(KeyError)
     def test_relabel_nodes_missing(self):
-        G=Graph([('A','B'),('A','C'),('B','C'),('C','D')])
-        mapping={0:'aardvark'}
-        G=relabel_nodes(G,mapping,copy=False)
+        G = Graph([('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'D')])
+        mapping = {0: 'aardvark'}
+        G = relabel_nodes(G, mapping, copy=False)
 
     def test_relabel_copy_name(self):
-        G=Graph()
+        G = Graph()
         H = relabel_nodes(G, {}, copy=True)
         assert_equal(H.graph, G.graph)
         H = relabel_nodes(G, {}, copy=False)
@@ -161,22 +169,21 @@ def test_relabel_copy_name(self):
         assert_equal(H.graph, G.graph)
 
     def test_relabel_toposort(self):
-        K5=nx.complete_graph(4)
-        G=nx.complete_graph(4)
-        G=nx.relabel_nodes(G,dict( [(i,i+1) for i in range(4)]),copy=False)
-        nx.is_isomorphic(K5,G)
-        G=nx.complete_graph(4)
-        G=nx.relabel_nodes(G,dict( [(i,i-1) for i in range(4)]),copy=False)
-        nx.is_isomorphic(K5,G)
-
+        K5 = nx.complete_graph(4)
+        G = nx.complete_graph(4)
+        G = nx.relabel_nodes(G, dict([(i, i + 1) for i in range(4)]), copy=False)
+        nx.is_isomorphic(K5, G)
+        G = nx.complete_graph(4)
+        G = nx.relabel_nodes(G, dict([(i, i - 1) for i in range(4)]), copy=False)
+        nx.is_isomorphic(K5, G)
 
     def test_relabel_selfloop(self):
         G = nx.DiGraph([(1, 1), (1, 2), (2, 3)])
         G = nx.relabel_nodes(G, {1: 'One', 2: 'Two', 3: 'Three'}, copy=False)
-        assert_nodes_equal(G.nodes(),['One','Three','Two'])
+        assert_nodes_equal(G.nodes(), ['One', 'Three', 'Two'])
         G = nx.MultiDiGraph([(1, 1), (1, 2), (2, 3)])
         G = nx.relabel_nodes(G, {1: 'One', 2: 'Two', 3: 'Three'}, copy=False)
-        assert_nodes_equal(G.nodes(),['One','Three','Two'])
+        assert_nodes_equal(G.nodes(), ['One', 'Three', 'Two'])
         G = nx.MultiDiGraph([(1, 1)])
         G = nx.relabel_nodes(G, {1: 0}, copy=False)
         assert_nodes_equal(G.nodes(), [0])