13
votes

according to networkx documentation, connected_component_subgraphs(G) returns a sorted list of all components. Thus the very first one should be the largest component.

However, when I try to get the largest component of a graph G using the example code on the documentation page

G=nx.path_graph(4)
G.add_edge(5,6)
H=nx.connected_component_subgraphs(G)[0]

I get

TypeError: 'generator' object has no attribute '__getitem__'

It used to work on my other computer with earlier versions of networkx (1.7 I think, not 100% sure)

Now I am using a different computer with python 2.7.7 and networkx 1.9. Is it a version problem?

I have written a small function with a couple lines myself to find the largest component, just wondering why this error came out.

BTW, I can get the components by converting the generator object to a list.

components = [comp for comp in nx.connected_components(G)]

But the list is not sorted by component size as stated in the documentation.

example:

G = nx.Graph()
G.add_edges_from([(1,2),(1,3),(4,5)])
G.add_nodes_from(range(6,20))
components = [comp for comp in nx.connected_components(G)]
component_size = [len(comp) for comp in components]
print G.number_of_nodes(), G.number_of_edges(), component_size

G = nx.Graph()
G.add_edges_from([(1000,2000),(1000,3000),(4000,5000)])
G.add_nodes_from(range(6,20))
components = [comp for comp in nx.connected_components(G)]
component_size = [len(comp) for comp in components]
print G.number_of_nodes(), G.number_of_edges(), component_size

output:

19 3 [3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
19 3 [2, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

looks like when the node names are large numbers and when there are a bunch of single nodes, the returned subgraphs are not sorted properly

2
The components in your example are returned in order of size (largest to smallest) on my machine, using NetworkX 1.9. This matches the documentation which says the components will be returned in descending order by size. - mdml
Aside: if you want to materialize a generator into a list, simply call list, e.g. list(nx.connected_components(G)). If you only want the first element yielded by the generator, you can use next, e.g. next(nx.connected_components(G)). - DSM
Thanks @DSM! I found how to get elements from generator here. stackoverflow.com/questions/12556090/… - sophiadw
@mdml I edited my post to put in an example - sophiadw
@sophiadw: the example in your post also works perfectly for me. - mdml

2 Answers

18
votes

The networkx-1.9 documentation is here http://networkx.github.io/documentation/networkx-1.9/reference/generated/networkx.algorithms.components.connected.connected_components.html#networkx.algorithms.components.connected.connected_components

The interface was changed to return a generator (as you figured out). The example in the documentation shows how to do what you ask.

Generate a sorted list of connected components, largest first.

>> G = nx.path_graph(4)
>>> G.add_path([10, 11, 12])
>>> sorted(nx.connected_components(G), key = len, reverse=True)
[[0, 1, 2, 3], [10, 11, 12]]

or

>>> sorted(nx.connected_component_subgraphs(G), key = len, reverse=True)
2
votes

As for version 2.4: nx.connected_component_subgraphs(G) is removed.

Instead to get the same result use:

connected_subgraphs = [G.subgraph(cc) for cc in nx.connected_components(G)]

And to get the giant component:

Gcc = max(nx.connected_components(G), key=len)
giantC = G.subgraph(Gcc)