Kristina Vakarov
Kristina Vakarov

Reputation: 191

Python iGraph - community_infomap graph

I made graph with networkx, kept 70% of most weighted branches and then converted to igraph, to use community_infomap. Labels on graph are very important. If you compare graph and result of community_infomap, you can see something strange. On graph it is obvious that there are 2 communities- signals 1,2 and second group 3.4.5.6.7.8 BUT! after infomap it mess up labels, it grouped signals 3.2 and 1.4.5.6.7.8. Why, what could happend? infomap graph

def nlargest_indices_orig(full, n):
full = full.copy()
x = np.zeros(n)
y = np.zeros(n)

for idx in range(n):
    x[idx] = np.unravel_index(full.argmax(), full.shape)[0]
    y[idx] = np.unravel_index(full.argmax(), full.shape)[1]
    full[full == full.max()] = 0.

return x, y

labels=[1,2,3,4,5,6,7,8]
o1 = scipy.io.loadmat('out.mat')
X=(o1['out'])
K=np.zeros((8,8))
m, n = np.shape(X)
G = nx.Graph()
for i in range(8):
    for j in range(8):
        if X[i,j]>0:
            s=labels[i]
            b=labels[j]
            w=X[i,j]
            G.add_edge(s,b,weight=w)
B=G.edges()
ND=len(B)
print('Grana ukupno')
procenat=round(0.7*ND)
x,y=nlargest_indices_orig(X, procenat)
s1=x
s2=y
for i in range(len(s2)):
    K[s1[i],s2[i]]=X[s1[i],s2[i]]
np.fill_diagonal(K, 0)
F = nx.Graph()

for i in range(8):
    for j in range(8):
        if K[i,j]>0:
            s=labels[i]
            b=labels[j]
            w=X[i,j]
            F.add_edge(s,b,weight=w)
edgewidth=[]
edgelabels={}
pos = nx.spring_layout(F) # position the nodes by force layout
plt.figure()
plt.axis('off')
print('Weighted graph')
for (u,v,d) in F.edges(data=True):
    print(u,v,d)
    edgewidth.append(d['weight'])
    edgelabels[(u,v)] = d['weight']
nx.draw_networkx_edges(F,pos,width=edgewidth,edge_color='r')
nx.draw_networkx_nodes(F,pos, alpha=0.8, node_size=400,node_color='w',scale=100)
nx.draw_networkx_labels(F,pos, font_size=12)
pylab.savefig('Graf--odabrani-sum imf.png')
plt.show()
edges = F.edges()
nodes=F.nodes()
cg = ig.Graph(edges)
cg.vs['label'] = labels
singletons = cg.vs.select(_degree = 0)
cg.delete_vertices(singletons)
degree = 0
community = cg.community_infomap()
print(len(community))
b=ig.plot(community,'infomap-odabrani-sum imf-.png')

Upvotes: 0

Views: 2953

Answers (1)

deeenes
deeenes

Reputation: 4586

To find out what happens here, we need to understand igraph's vertex indexing behaviour. Vertex indices are not stable, reindexing might happen at deletion or addition of vertices or edges. Indices always go from 0 to n-1. If you initialize a graph with integer tuples, igraph will consider the integers to be vertex indices. Your indices start from 1, so igraph will introduce a singleton vertex with index 0, which is completely wrong for you as it was not in your original network.

import igraph as ig
import networkx as nx
import pylab as plt

_edges = [
    (1, 2), 
    (3, 4), (3, 5), (3, 6), (3, 8),
    (4, 5), (4, 6), (4, 7), (4, 8),
    (5, 6), (5, 7), (5, 8),
    (6, 7), (6, 8),
    (7, 8)
]

G = nx.Graph()

for e in _edges:
    G.add_edge(e[0], e[1], weight = 1)

pos = nx.spring_layout(G)
plt.figure()
plt.axis('off')
nx.draw_networkx_edges(G, pos, edge_color='r')
nx.draw_networkx_nodes(G, pos, alpha=0.8, node_size=400, node_color='w', scale=100)
nx.draw_networkx_labels(G, pos, font_size=12)
plt.show()
plt.savefig('nx_graph1.png')

edges_from_nx = G.edges()

Try to initialize the igraph.Graph object as you did:

g = ig.Graph(edges_from_nx)

g.vcount() # returns 9. why? we supplied integers to igraph,
           # what it considered as vertex indices

'name' in g.vs.attributes() # returns False: vertices do not have names

ig.plot(g, vertex_label = range(g.vcount()))

graph without names

Notice the single vertex with index 0, what you have subsequently deleted, so all the other vertices happened to be reindexed in an unpredictable way.

To avoid this, initialize the Graph object with the TupleList constructor:

g = ig.Graph.TupleList(edges_from_nx)
g.vcount() # returns 8. this looks fine!
'name' in g.vs.attributes() # returns True: good, labels are assigned
                            # to the `name` vertex attribute
ig.plot(g, vertex_label = g.vs['name'])

graph with correct labels

Now everything looks the same as in NetworkX. Note: this has nothing to do with community_infomap. If you want stable identifiers for your vertices or edges in igraph, keep them in vertex or edge attributes.

Upvotes: 1

Related Questions