Package: communities
communitiescommunitiesis a Python library for detectingcommunity structurein graphs. It implements the following algorithms:Louvain methodGirvan-Newman algorithmHierarchical clusteringSpectral clusteringBron-Kerbosch algorithmYou can also usecommunitiesto visualize these algorithms. For example, here's a visualization of the Louvain method applied to thekarate club graph:Installationcommunitiescan be installed withpip:$pipinstallcommunitiesGetting StartedEach algorithm expects an adjacency matrix representing an undirected graph, which can be weighted or unweighted. This matrix should be a 2Dnumpyarray. Once you have this, simply import the algorithm you want to use fromcommunities.algorithmsand plug in the matrix, like so:importnumpyasnpfromcommunities.algorithmsimportlouvain_methodadj_matrix=np.array([[0,1,1,0,0,0],[1,0,1,0,0,0],[1,1,0,1,0,0],[0,0,1,0,1,1],[0,0,0,1,0,1],[0,0,0,1,1,0]])communities,_=louvain_method(adj_matrix)# >>> [{0, 1, 2}, {3, 4, 5}]The output of each algorithm is a list of communities, where each community is a set of nodes. Each node is referred to by the index of its row in the adjacency matrix.Some algorithms, likelouvain_methodandgirvan_newman, will return two values: the list of communities and data to plug into a visualization algorithm. More on this in theVisualizationsection.AlgorithmsLouvain's Methodlouvain_method(adj_matrix : numpy.ndarray, n : int = None) -> listImplementation of the Louvain method, fromFast unfolding of communities in large networks. This algorithm does a greedy search for the communities that maximize the modularity of the graph. A graph is said to be modular if it has a high density of intra-community edges and a low density of inter-community edges.Louvain's method runs inO(nᆞlog2n)time, wherenis the number of nodes in the graph.Parameters:adj_matrix(numpy.ndarray): Adjacency matrix representation of your graphn(int or None, optional (default=None)): Terminates the search once this number of communities is detected; ifNone, then the algorithm will behave normally and terminate once modularity is maximizedExample Usage:fromcommunities.algorithmsimportlouvain_methodadj_matrix=[...]communities,_=louvain_method(adj_matrix)Girvan-Newman algorithmgirvan_newman(adj_matrix : numpy.ndarray, n : int = None) -> listImplementation of the Girvan-Newman algorithm, fromCommunity structure in social and biological networks. This algorithm iteratively removes edges to create moreconnected components. Each component is considered a community, and the algorithm stops removing edges when no more gains in modularity can be made. Edges with the highest betweenness centralities (i.e. those that lie between many pairs of nodes) are removed. Formally, edge betweenness centrality is defined as:whereσ(i,j)is the number of shortest paths from nodeitojσ(i,j|e)is the number of shortest paths that pass through edgeeThe Girvan-Newman algorithm runs inO(m2n)time, wheremis the number of edges in the graph andnis the number of nodes.Parameters:adj_matrix(numpy.ndarray): Adjacency matrix representation of your graphIf your graph is weighted, then the weights need to be transformed into distances, since that's how they'll be interpreted when searching for shortest paths. One way to do this is to simply take the inverse of each weight.n(int or None, optional (default=None)): Terminates the search once this number of communities is detected; ifNone, then the algorithm will behave normally and terminate once modularity is maximizedExample Usage:fromcommunities.algorithmsimportgirvan_newmanadj_matrix=[...]communities,_=girvan_newman(adj_matrix)Hierarchical clusteringhierarchical_clustering(adj_matrix : numpy.ndarray, metric : str = "cosine", linkage : str = "single", n : int = None) -> listImplementation of a bottom-up, hierarchical clustering algorithm. Each node starts in its own community. Then, the most similar pairs of communities are merged as the hierarchy is built up. Communities are merged until no further gains in modularity can be made.There are multiple schemes for measuring the similarity between two communities,C1andC2:Single-linkage:min({sim(i, j) | i ∊ C1, j ∊ C2})Complete-linkage:max({sim(i, j) | i ∊ C1, j ∊ C2})Mean-linkage:mean({sim(i, j) | i ∊ C1, j ∊ C2})wheresim(i, j)is the similarity between nodesiandj, defined as either the cosine similarity or inverse Euclidean distance between their row vectors in the adjacency matrix,AiandAj.This algorithm runs inO(n3)time, wherenis the number of nodes in the graph.Parameters:adj_matrix(numpy.ndarray): Adjacency matrix representation of your graphmetric(str, optional (default="cosine")): Scheme for measuring node similarity; options are "cosine", for cosine similarity, or "euclidean", for inverse Euclidean distancelinkage(str, optional (default="single")): Scheme for measuring community similarity; options are "single", "complete", and "mean"n(int or None, optional (default=None)): Terminates the search once this number of communities is detected; ifNone, then the algorithm will behave normally and terminate once modularity is maximizedExample Usage:fromcommunities.algorithmsimporthierarchical_clusteringadj_matrix=[...]communities=hierarchical_clustering(adj_matrix,metric="euclidean",linkage="complete")Spectral clusteringspectral_clustering(adj_matrix : numpy.ndarray, k : int) -> listImplementation of a spectral clustering algorithm. This type of algorithm assumes the eigenvalues of the adjacency matrix hold information about community structure. Here's how it works:Compute the Laplacian matrix,L = D - A, whereAis the adjacency matrix andDis the diagonal matrixCompute theksmallest eigenvectors ofL, skipping the first eigenvectorCreate a matrixVcontaining eigenvectorsv1,v2, ...vnas columnsCluster the rows inVusing k-means intokcommunitiesThis algorithm is NP-hard.Parameters:adj_matrix(numpy.ndarray): Adjacency matrix representation of your graphk(int): Number of communities to cluster nodes intoExample Usage:fromcommunities.algorithmsimportspectral_clusteringadj_matrix=[...]communities=spectral_clustering(adj_matrix,k=5)Bron-Kerbosch algorithmbron_kerbosch(adj_matrix : numpy.ndarray, pivot : bool = False) -> listImplementation of theBron-Kerbosch algorithmfor maximal clique detection. A maximal clique in a graph is a subset of nodes that forms a complete graph and would no longer be complete if any other node was added to the subset. Treating maximal cliques as communities is reasonable, as cliques are the most densely connected groups of nodes in a graph. Because a node can be a member of more than one clique, this algorithm will sometimes identify overlapping communities.If your input graph has less than3n/3maximal cliques, then this algorithm runs inO(3n/3)time (assumingpivot=True).Parameters:adj_matrix(numpy.ndarray): Adjacency matrix representation of your graphNote that this algorithm treats the graph as unweightedpivot(bool, optional (default=False)): IfTrue, the pivot variant of the algorithm (describedhere) will be usedThis will make the algorithm more efficient if your graph has several non-maximal cliquesExample Usage:fromcommunities.algorithmsimportbron_kerboschadj_matrix=[...]communities=bron_kerbosch(adj_matrix,pivot=True)VisualizationPlot communitiesdraw_communities(adj_matrix : numpy.ndarray, communities : list, dark : bool = False, filename : str = None, seed : int = 1)Visualize your graph such that nodes are grouped into their communities and color-coded.Returns amatplotlib.axes.Axesrepresenting the plot.Parameters:adj_matrix(numpy.ndarray): Adjacency matrix representation of your graphdark(bool, optional (default=False)): IfTrue, the plot will have a dark background and color scheme, else it will have a light color schemefilename(str or None, optional (default=None)): If you want to save the plot as a PNG,filenameis the path of the file to save it as; set toNoneto display the plot interactivelydpi(int or None, optional (default=None)): Dots per inch (controls the resolution of the image)seed(int, optional (default=2)): Random seedExample Usage:fromcommunities.algorithmsimportlouvain_methodfromcommunities.visualizationimportdraw_communitiesadj_matrix=[...]communities,frames=louvain_method(adj_matrix)draw_communities(adj_matrix,communities)Animate the Louvain methodlouvain_animation(adj_matrix : numpy.ndarray, frames : list, dark : bool = False, duration : int = 15, filename : str = None, dpi : int = None, seed : int = 2)Use this to animate the application of the Louvain method to your graph. In this animation, the color of each node represents the community it's assigned to, and nodes in the same community are clustered together. Each step of the animation will show a node changing color (i.e. being assigned to a different community) and being moved to a new cluster, and the corresponding update to the graph's modularity.This function returns amatplotlib.animation.FuncAnimationobject representing the animation.Parameters:adj_matrix(numpy.ndarray): Adjacency matrix representation of your graphframes(list): List of dictionaries representing each iteration of the algorithmEach dictionary has two keys:"C", which holds a node-to-community lookup table, and"Q", the modularity value of the graphThis list of dictionaries is the second return value of thelouvain_methoddark(bool, optional (default=False)): IfTrue, the animation will have a dark background and color scheme, else it will have a light color schemeduration(int, optional (default=15)): The desired duration of the animation in secondsfilename(str or None, optional (default=None)): If you want to save the animation as a GIF,filenameis the path of the file to save it as; set toNoneto display the animation as an interactive plotdpi(int or None, optional (default=None)): Dots per inch (controls the resolution of the animation)seed(int, optional (default=2)): Random seedExample Usage:fromcommunities.algorithmsimportlouvain_methodfromcommunities.visualizationimportlouvain_animationadj_matrix=[...]communities,frames=louvain_method(adj_matrix)louvain_animation(adj_matrix,frames)UtilitiesInter-community adjacency matrixintercommunity_matrix(adj_matrix : numpy.ndarray, communities : list, aggr : Callable = sum) -> numpy.ndarrayCreates an inter-community adjacency matrix. Each node in this matrix represents a community incommunities, and each edge between nodesiandjis created by aggregating (e.g. summing) the weights of edges between nodes incommunities[i]and nodes incommunities[j].Parameters:adj_matrix(numpy.ndarray): Adjacency matrix representation of the graph from which communities were extractedcommunities(list): List of communitiesaggr(Callable, optional (default=sum)): Function that takes a list of inter-community edge weights and combines them into a single edge weightExample Usage:fromstatisticsimportmeanfromcommunities.algorithmsimportlouvain_methodfromcommunities.utilitiesimportintercommunity_matrixadj_matrix=[...]communities=louvain_method(adj_matrix)intercomm_adj_matrix=intercommunity_matrix(adj_matrix,communities,mean)Graph Laplacianlaplacian_matrix(adj_matrix : numpy.ndarray) -> numpy.ndarrayComputes thegraph Laplacian. This matrix is used in thespectral_clusteringalgorithm, and is generally useful for revealing properties of a graph. It is defined asL = D - A, whereAis the adjacency matrix of the graph, andDis the degree matrix, defined as:wherewikis the edge weight between a nodeiand its neighbork.Parameters:adj_matrix(numpy.ndarray): Adjacency matrix representation of your graphExample Usage:fromcommunities.utilitiesimportlaplacian_matrixadj_matrix=[...]L=laplacian_matrix(adj_matrix)Modularity matrixmodularity_matrix(adj_matrix : numpy.ndarray) -> numpy.ndarrayComputes the modularity matrix for a graph. The modularity matrix is defined as:whereAijis the weight of the edge between nodesiandjkiandkjare the sum of the weights of the edges attached to nodesiandj, respectivelymis the sum of all of the edge weights in the graphParameters:adj_matrix(numpy.ndarray): Adjacency matrix representation of your graphModularitymodularity(mod_matrix : numpy.ndarray, communities : list) -> floatComputes modularity of a partitioned graph. Modularity is defined as:whereAijis the weight of the edge between nodesiandjkiandkjare the sum of the weights of the edges attached to nodesiandj, respectivelymis the sum of all of the edge weights in the graphciandcjare the communities of the nodesδis the Kronecker delta function (δ(x, y) = 1ifx = y,0otherwise)Parameters:mod_matrix(numpy.ndarray): Modularity matrix computed from the adjacency matrix representation of your graphcommunities(list): List of (non-overlapping) communities identified in the graphExample Usage:fromcommunities.algorithmsimportlouvain_methodfromcommunities.utilitiesimportmodularity_matrix,modularityadj_matrix=[...]communities=louvain_method(adj_matrix)mod_matrix=modularity_matrix(adj_matrix)Q=modularity(mod_matrix,communities)