'Return the subgraph induced on nodes in nbunch.
The induced subgraph of the graph contains the nodes in nbunch
and the edges between those nodes.
Parameters
nbunch : list, iterable
A container of nodes which will be iterated through once.
Returns
G : Graph
A subgraph of the graph with the same edge attributes.
Notes
The graph, edge or node attributes just point to the original graph.
So changes to the node or edge structure will not be reflected in
the original graph while changes to the attributes will.
To create a subgraph with its own copy of the edge/node attributes use:
nx.Graph(G.subgraph(nbunch))
If edge attributes are containers, a deep copy can be obtained using:
G.subgraph(nbunch).copy()
For an inplace reduction of a graph to a subgraph you can remove nodes:
G.remove_nodes_from([ n in G if n not in set(nbunch)])
Examples
>>> G = nx.Graph()   # or DiGraph, MultiGraph, MultiDiGraph, etc
>>> nx.add_path(G, [0, 1, 2, 3])
>>> H = G.subgraph([0, 1, 2])
>>> list(H.edges())
[(0, 1), (1, 2)]'

def subgraph(self, nbunch):

    bunch = self.nbunch_iter(nbunch)
    H = self.__class__()
    for n in bunch:
        H._node[n] = self._node[n]
    H_adj = H._adj
    self_adj = self._adj
    for n in H:
        Hnbrs = H.adjlist_inner_dict_factory()
        H_adj[n] = Hnbrs
        for (nbr, edgedict) in self_adj[n].items():
            if (nbr in H_adj):
                ed = edgedict.copy()
                Hnbrs[nbr] = ed
                H_adj[nbr][n] = ed
    H.graph = self.graph
    return H
