Search code examples
pythonnetworkxpyvis

Networkx common neighbors not filtering properly, not returning right list of neighbors


I have a test graph that I would like to filter

import networkx as nx
import pickle
from pyvis.network import Network

central_node='a'

nono=['a', 'b', 'c', 'd', 'e', 'f', 'g','h','i','j','k']
eded=[('a', 'b'), ('a', 'c'), ('a', 'd'),('a','f'),('b', 'e'),('c', 'e'),('f', 'd'),('a', 'g'),('e','h'),('e','g'),('i','e'),('j','f'),('k','j')]

graph=nx.Graph()
graph.add_nodes_from(nono)
graph.add_edges_from(eded)

net=Network(height='100%', width='100%', bgcolor='white', font_color='black')
net.from_nx(graph)
net.show('test Graph.html')

Which gives this graph

Full Graph

I am then filtering out all nodes which are further than a radius 2 aroung my central node 'a'

subgraph=nx.ego_graph(G=graph,n=central_node, radius=2, center=True)
subnet.from_nx(subgraph)
subnet.show('test SubGraph.html')

which gives this graph (everything ok so far)

Sub graph

Now, the difficult part. I am trying to keep nodes from the subgraph that have at least 3 nodes in common with my central node 'a' (in my case the node 'e' is the only one I would like to keep).

for node in subgraph.nodes:
    neighbor = nx.common_neighbors(subgraph,central_node,node)
    n=len(list(neighbor))
    print(node,n)
    print(list(neighbor))
    for i in sorted(neighbor):
        filtered_nodes.extend(i)
    if n > 2:
        neighbors[node]=n
        filtered_nodes.append(node)
        filtered_nodes.extend(sorted(neighbor))

And would like to display the resulting graph (displaying nodes a,b,c,e,g and their connecting edges)

But here is the result

filtered_graph=subgraph.subgraph(filtered_nodes)
final_net=Network(height='100%', width='100%', bgcolor='white', font_color='black')
final_net.from_nx(filtered_graph)
final_net.show('Traffic Graph.html')

Final Graph

It seems that the common_neighbors function does return the list of node b,c,g. Whenever I am trying to print it, it displays an empty list. On the other hand, it could count properly the number of common neighbors between node and central node 'a'.

a 5
[]
b 0
[]
c 0
[]
d 1
[]
e 3
[]
f 1
[]
g 0
[]
j 1
[]

I cannnot figure out properly which part I am doing wrong.


Solution

  • The common_neighbors function doesn't actually return a list-- rather, it returns an iterator, which can be used to generate a list. As a result, when you do n=len(list(neighbor)), you actually consume the iterator, leaving it empty. To fix this, call list on its return value and save that to a variable:

    for node in subgraph.nodes:
        neighbor = list(nx.common_neighbors(subgraph, central_node, node))
        n = len(neighbor)
        print(node, n)
        print(neighbor)
        for i in sorted(neighbor):
            filtered_nodes.extend(i)
        if n > 2:
            neighbors[node] = n
            filtered_nodes.append(node)
            filtered_nodes.extend(sorted(neighbor))