Modularity (Q) based on the Louvain split, unexpected values

Hi igraph community,

I have a graph and I want to estimate the modularity (Q) based on the Louvain split of the graph.

In python I used igraph and to compare, I also estimated Q in Matlab.
Based on igraph, the Q is negative (weird) whereas the Q based on the Matlab estimation is positive.

I would expect differences in the values but not by so far (+ shows modularity, - shows anti-modularity).
Any idea why this happens?

Makis

———————————

My code and data (https://gofile.io/?c=h24mcU):

PYTHON

import numpy as np
import scipy.io
from igraph import *

A = scipy.io.loadmat('A.mat')['A']

graph = Graph.Weighted_Adjacency(A.tolist(), mode=ADJ_UNDIRECTED, attr="weight", loops=False)
Louvain = graph.community_multilevel(weights=graph.es['weight'], return_levels=False)
Q = graph.modularity(Louvain)
print(Q)

-0.001847596203445795

MATLAB (Brain Connectivity Toolbox)
using community_louvain.m: Louvain community detection algorithm

clear all
load('A.mat')
[M,Q]=community_louvain(A);

Q =

   0.1466

PYTHON version of community_louvain.m: https://github.com/aestrivex/bctpy/blob/f9526a693a9af57051762442d8490dcdf2ebf4e3/bct/algorithms/modularity.py#L71,

import bct

split, Q = bct.community_louvain(A)
Q
0.14659657544165258

again I get approx. 0.1466 that matches the Matlab and Python BCT-based results but is far from the igraph output.

I am not immediately sure about the difference. One thought: you have to pass the weights to calculate the modularity in igraph. Perhaps this is not needed for the Brain Connectivity Toolbox? Perhaps if you pass the weights to the modularity calculations you do get the same modularity value?

1 Like

I did a really quick try with the Mathematica interface and got 0.141 for the weighted version (0 for the unweighted one).

1 Like

Indeed that is the case. I expected igraph to understand this since I defined a weighted adjacency matrix but I need to explicitly pass the weights argument in modularity().

import numpy as np
import scipy.io
from igraph import *
import bct

A = scipy.io.loadmat("A.mat")['A']
np.fill_diagonal(A,0.0)

# igraph
graph = Graph.Weighted_Adjacency(A.tolist(), mode=ADJ_UNDIRECTED, attr="weight", loops=False)
Louvain = graph.community_multilevel(weights=graph.es['weight'], return_levels=False)
Q = graph.modularity(Louvain, weights=graph.es['weight'])
print(Q)

#bctpy
com, q = bct.community_louvain(A)
print(q)

0.14133150351832535

0.14133150351832674

1 Like

I am happy to see the same Q value in your example. I found the culprit. See my post above. Thanks for the input !