{"id":13689153,"url":"https://github.com/shobrook/communities","last_synced_at":"2025-05-16T07:03:54.117Z","repository":{"id":50267997,"uuid":"283101967","full_name":"shobrook/communities","owner":"shobrook","description":"Library of graph clustering algorithms","archived":false,"fork":false,"pushed_at":"2023-11-04T05:39:26.000Z","size":81038,"stargazers_count":750,"open_issues_count":14,"forks_count":106,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-05-11T10:50:01.903Z","etag":null,"topics":["bron-kerbosch-algorithm","community","community-detection","girvan-newman-algorithm","graph","graph-algorithms","louvain","spectral-clustering"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shobrook.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-07-28T04:46:25.000Z","updated_at":"2025-05-09T20:34:32.000Z","dependencies_parsed_at":"2023-12-19T03:28:31.857Z","dependency_job_id":null,"html_url":"https://github.com/shobrook/communities","commit_stats":{"total_commits":108,"total_committers":1,"mean_commits":108.0,"dds":0.0,"last_synced_commit":"c886a990bd7f6e3ab620171b90fdad7982093c7a"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shobrook%2Fcommunities","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shobrook%2Fcommunities/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shobrook%2Fcommunities/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shobrook%2Fcommunities/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shobrook","download_url":"https://codeload.github.com/shobrook/communities/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254485053,"owners_count":22078767,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bron-kerbosch-algorithm","community","community-detection","girvan-newman-algorithm","graph","graph-algorithms","louvain","spectral-clustering"],"created_at":"2024-08-02T15:01:35.710Z","updated_at":"2025-05-16T07:03:54.095Z","avatar_url":"https://github.com/shobrook.png","language":"Python","readme":"# communities\n\n`communities` is a Python library for detecting [community structure](https://en.wikipedia.org/wiki/Community_structure) in graphs. It implements the following algorithms:\n\n- Louvain method\n- Girvan-Newman algorithm\n- Hierarchical clustering\n- Spectral clustering\n- Bron-Kerbosch algorithm\n\u003c!-- - Minimum k-cut--\u003e\n\nYou can also use `communities` to visualize these algorithms. For example, here's a visualization of the Louvain method applied to the [karate club graph](https://en.wikipedia.org/wiki/Zachary%27s_karate_club):\n\n![Demo](./img/demo.gif)\n\n#### Cited in\n\n[An Interpretable Station Delay Prediction Model Based on Graph Community Neural Network and Time-Series Fuzzy Decision Tree](https://ieeexplore.ieee.org/document/9792625)\n\n[SITUATEDGEN: Incorporating Geographical and Temporal Contexts into Generative Commonsense Reasoning](https://arxiv.org/pdf/2306.12552.pdf)\n\n## Installation\n\n`communities` can be installed with `pip`:\n\n```bash\n$ pip install communities\n```\n\n## Getting Started\n\nEach algorithm expects an adjacency matrix representing an undirected graph, which can be weighted or unweighted. This matrix should be a 2D `numpy` array. Once you have this, simply import the algorithm you want to use from `communities.algorithms` and plug in the matrix, like so:\n\n```python\nimport numpy as np\nfrom communities.algorithms import louvain_method\n\nadj_matrix = np.array([[0, 1, 1, 0, 0, 0],\n                       [1, 0, 1, 0, 0, 0],\n                       [1, 1, 0, 1, 0, 0],\n                       [0, 0, 1, 0, 1, 1],\n                       [0, 0, 0, 1, 0, 1],\n                       [0, 0, 0, 1, 1, 0]])\ncommunities, _ = louvain_method(adj_matrix)\n# \u003e\u003e\u003e [{0, 1, 2}, {3, 4, 5}]\n```\n\nThe 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.\n\nSome algorithms, like `louvain_method` and `girvan_newman`, will return two values: the list of communities and data to plug into a visualization algorithm. More on this in the _Visualization_ section.\n\n## Algorithms\n\n### Louvain's Method\n\n**`louvain_method(adj_matrix : numpy.ndarray, n : int = None) -\u003e list`**\n\nImplementation of the Louvain method, from _[Fast unfolding of communities in large networks](https://arxiv.org/pdf/0803.0476.pdf)_. 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.\n\nLouvain's method runs in _O(nᆞlog\u003csup\u003e2\u003c/sup\u003en)_ time, where _n_ is the number of nodes in the graph.\n\n**Parameters:**\n\n- `adj_matrix` _(numpy.ndarray)_: Adjacency matrix representation of your graph\n- `n` _(int or None, optional (default=None))_: Terminates the search once this number of communities is detected; if `None`, then the algorithm will behave normally and terminate once modularity is maximized\n\n**Example Usage:**\n\n```python\nfrom communities.algorithms import louvain_method\n\nadj_matrix = [...]\ncommunities, _ = louvain_method(adj_matrix)\n```\n\n### Girvan-Newman algorithm\n\n**`girvan_newman(adj_matrix : numpy.ndarray, n : int = None) -\u003e list`**\n\nImplementation of the Girvan-Newman algorithm, from _[Community structure in social and biological networks](https://www.pnas.org/content/99/12/7821)_. This algorithm iteratively removes edges to create more [connected components](\u003chttps://en.wikipedia.org/wiki/Component_(graph_theory)\u003e). 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:\n\n\u003cp align=\"left\"\u003e\u003cimg src=\"img/edge_betweenness_centrality.png\" width=\"175px\" /\u003e\u003c/p\u003e\n\nwhere\n\n- _σ(i,j)_ is the number of shortest paths from node _i_ to _j_\n- _σ(i,j|e)_ is the number of shortest paths that pass through edge _e_\n\nThe Girvan-Newman algorithm runs in _O(m\u003csup\u003e2\u003c/sup\u003en)_ time, where _m_ is the number of edges in the graph and _n_ is the number of nodes.\n\n**Parameters:**\n\n- `adj_matrix` _(numpy.ndarray)_: Adjacency matrix representation of your graph\n  - If 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- `n` _(int or None, optional (default=None))_: Terminates the search once this number of communities is detected; if `None`, then the algorithm will behave normally and terminate once modularity is maximized\n\n**Example Usage:**\n\n```python\nfrom communities.algorithms import girvan_newman\n\nadj_matrix = [...]\ncommunities, _ = girvan_newman(adj_matrix)\n```\n\n### Hierarchical clustering\n\n**`hierarchical_clustering(adj_matrix : numpy.ndarray, metric : str = \"cosine\", linkage : str = \"single\", n : int = None) -\u003e list`**\n\nImplementation 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.\n\nThere are multiple schemes for measuring the similarity between two communities, _C\u003csub\u003e1\u003c/sub\u003e_ and _C\u003csub\u003e2\u003c/sub\u003e_:\n\n- **Single-linkage:** min({sim(i, j) | i ∊ C\u003csub\u003e1\u003c/sub\u003e, j ∊ C\u003csub\u003e2\u003c/sub\u003e})\n- **Complete-linkage:** max({sim(i, j) | i ∊ C\u003csub\u003e1\u003c/sub\u003e, j ∊ C\u003csub\u003e2\u003c/sub\u003e})\n- **Mean-linkage:** mean({sim(i, j) | i ∊ C\u003csub\u003e1\u003c/sub\u003e, j ∊ C\u003csub\u003e2\u003c/sub\u003e})\n\nwhere _sim(i, j)_ is the similarity between nodes _i_ and _j_, defined as either the cosine similarity or inverse Euclidean distance between their row vectors in the adjacency matrix, _A\u003csub\u003ei\u003c/sub\u003e_ and _A\u003csub\u003ej\u003c/sub\u003e_.\n\nThis algorithm runs in _O(n\u003csup\u003e3\u003c/sup\u003e)_ time, where _n_ is the number of nodes in the graph.\n\n**Parameters:**\n\n- `adj_matrix` _(numpy.ndarray)_: Adjacency matrix representation of your graph\n- `metric` _(str, optional (default=\"cosine\"))_: Scheme for measuring node similarity; options are \"cosine\", for cosine similarity, or \"euclidean\", for inverse Euclidean distance\n- `linkage` _(str, optional (default=\"single\"))_: Scheme for measuring community similarity; options are \"single\", \"complete\", and \"mean\"\n- `n` _(int or None, optional (default=None))_: Terminates the search once this number of communities is detected; if `None`, then the algorithm will behave normally and terminate once modularity is maximized\n\n**Example Usage:**\n\n```python\nfrom communities.algorithms import hierarchical_clustering\n\nadj_matrix = [...]\ncommunities = hierarchical_clustering(adj_matrix, metric=\"euclidean\", linkage=\"complete\")\n```\n\n### Spectral clustering\n\n**`spectral_clustering(adj_matrix : numpy.ndarray, k : int) -\u003e list`**\n\nImplementation 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:\n\n1. Compute the Laplacian matrix, _L = D - A_, where _A_ is the adjacency matrix and _D_ is the diagonal matrix\n2. Compute the _k_ smallest eigenvectors of _L_, skipping the first eigenvector\n3. Create a matrix _V_ containing eigenvectors _v\u003csub\u003e1\u003c/sub\u003e_, _v\u003csub\u003e2\u003c/sub\u003e_, ... _v\u003csub\u003en\u003c/sub\u003e_ as columns\n4. Cluster the rows in _V_ using k-means into _k_ communities\n\nThis algorithm is NP-hard.\n\n**Parameters:**\n\n- `adj_matrix` _(numpy.ndarray)_: Adjacency matrix representation of your graph\n- `k` _(int)_: Number of communities to cluster nodes into\n\n**Example Usage:**\n\n```python\nfrom communities.algorithms import spectral_clustering\n\nadj_matrix = [...]\ncommunities = spectral_clustering(adj_matrix, k=5)\n```\n\n### Bron-Kerbosch algorithm\n\n**`bron_kerbosch(adj_matrix : numpy.ndarray, pivot : bool = False) -\u003e list`**\n\nImplementation of the [Bron-Kerbosch algorithm](https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm) for 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.\n\n\u003c!--TODO: Given a brief overview of how the algorithm works--\u003e\n\u003c!--TODO: Explain the `pivot` argument--\u003e\n\nIf your input graph has less than _3\u003csup\u003en/3\u003c/sup\u003e_ maximal cliques, then this algorithm runs in _O(3\u003csup\u003en/3\u003c/sup\u003e)_ time (assuming `pivot=True`).\n\n**Parameters:**\n\n- `adj_matrix` _(numpy.ndarray)_: Adjacency matrix representation of your graph\n  - Note that this algorithm treats the graph as unweighted\n- `pivot` _(bool, optional (default=False))_: If `True`, the pivot variant of the algorithm (described [here](https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm#With_pivoting)) will be used\n  - This will make the algorithm more efficient if your graph has several non-maximal cliques\n\n**Example Usage:**\n\n```python\nfrom communities.algorithms import bron_kerbosch\n\nadj_matrix = [...]\ncommunities = bron_kerbosch(adj_matrix, pivot=True)\n```\n\n## Visualization\n\n### Plot communities\n\n**`draw_communities(adj_matrix : numpy.ndarray, communities : list, dark : bool = False, filename : str = None, seed : int = 1)`**\n\nVisualize your graph such that nodes are grouped into their communities and color-coded.\n\nReturns a `matplotlib.axes.Axes` representing the plot.\n\n**Parameters:**\n\n- `adj_matrix` _(numpy.ndarray)_: Adjacency matrix representation of your graph\n- `dark` _(bool, optional (default=False))_: If `True`, the plot will have a dark background and color scheme, else it will have a light color scheme\n- `filename` _(str or None, optional (default=None))_: If you want to save the plot as a PNG, `filename` is the path of the file to save it as; set to `None` to display the plot interactively\n- `dpi` _(int or None, optional (default=None))_: Dots per inch (controls the resolution of the image)\n- `seed` _(int, optional (default=2))_: Random seed\n\n**Example Usage:**\n\n```python\nfrom communities.algorithms import louvain_method\nfrom communities.visualization import draw_communities\n\nadj_matrix = [...]\ncommunities, frames = louvain_method(adj_matrix)\n\ndraw_communities(adj_matrix, communities)\n```\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"img/draw_communities.png\" width=\"75%\"/\u003e\u003c/p\u003e\n\n### Animate the Louvain method\n\n**`louvain_animation(adj_matrix : numpy.ndarray, frames : list, dark : bool = False, duration : int = 15, filename : str = None, dpi : int = None, seed : int = 2)`**\n\nUse 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.\n\nThis function returns a `matplotlib.animation.FuncAnimation` object representing the animation.\n\n**Parameters:**\n\n- `adj_matrix` _(numpy.ndarray)_: Adjacency matrix representation of your graph\n- `frames` _(list)_: List of dictionaries representing each iteration of the algorithm\n  - Each dictionary has two keys: `\"C\"`, which holds a node-to-community lookup table, and `\"Q\"`, the modularity value of the graph\n  - This list of dictionaries is the second return value of the `louvain_method`\n- `dark` _(bool, optional (default=False))_: If `True`, the animation will have a dark background and color scheme, else it will have a light color scheme\n- `duration` _(int, optional (default=15))_: The desired duration of the animation in seconds\n- `filename` _(str or None, optional (default=None))_: If you want to save the animation as a GIF, `filename` is the path of the file to save it as; set to `None` to display the animation as an interactive plot\n- `dpi` _(int or None, optional (default=None))_: Dots per inch (controls the resolution of the animation)\n- `seed` _(int, optional (default=2))_: Random seed\n\n**Example Usage:**\n\n```python\nfrom communities.algorithms import louvain_method\nfrom communities.visualization import louvain_animation\n\nadj_matrix = [...]\ncommunities, frames = louvain_method(adj_matrix)\n\nlouvain_animation(adj_matrix, frames)\n```\n\n![Demo](./img/demo.gif)\n\n## Utilities\n\n### Inter-community adjacency matrix\n\n**`intercommunity_matrix(adj_matrix : numpy.ndarray, communities : list, aggr : Callable = sum) -\u003e numpy.ndarray`**\n\nCreates an inter-community adjacency matrix. Each node in this matrix represents a community in `communities`, and each edge between nodes _i_ and _j_ is created by aggregating (e.g. summing) the weights of edges between nodes in `communities[i]` and nodes in `communities[j]`.\n\n**Parameters:**\n\n- `adj_matrix` _(numpy.ndarray)_: Adjacency matrix representation of the graph from which communities were extracted\n- `communities` _(list)_: List of communities\n- `aggr` _(Callable, optional (default=sum))_: Function that takes a list of inter-community edge weights and combines them into a single edge weight\n\n**Example Usage:**\n\n```python\nfrom statistics import mean\nfrom communities.algorithms import louvain_method\nfrom communities.utilities import intercommunity_matrix\n\nadj_matrix = [...]\ncommunities = louvain_method(adj_matrix)\nintercomm_adj_matrix = intercommunity_matrix(adj_matrix, communities, mean)\n```\n\n### Graph Laplacian\n\n**`laplacian_matrix(adj_matrix : numpy.ndarray) -\u003e numpy.ndarray`**\n\nComputes the [graph Laplacian](https://en.wikipedia.org/wiki/Laplacian_matrix). This matrix is used in the `spectral_clustering` algorithm, and is generally useful for revealing properties of a graph. It is defined as _L = D - A_, where _A_ is the adjacency matrix of the graph, and _D_ is the degree matrix, defined as:\n\n\u003cp align=\"left\"\u003e\u003cimg src=\"img/degree_matrix.png\" width=\"235px\" /\u003e\u003c/p\u003e\n\nwhere _w\u003csub\u003eik\u003c/sub\u003e_ is the edge weight between a node _i_ and its neighbor _k_.\n\n**Parameters:**\n\n- `adj_matrix` _(numpy.ndarray)_: Adjacency matrix representation of your graph\n\n**Example Usage:**\n\n```python\nfrom communities.utilities import laplacian_matrix\n\nadj_matrix = [...]\nL = laplacian_matrix(adj_matrix)\n```\n\n### Modularity matrix\n\n**`modularity_matrix(adj_matrix : numpy.ndarray) -\u003e numpy.ndarray`**\n\nComputes the modularity matrix for a graph. The modularity matrix is defined as:\n\n\u003cp align=\"left\"\u003e\u003cimg src=\"img/modularity_matrix.png\" width=\"200px\" /\u003e\u003c/p\u003e\n\nwhere\n\n- _A\u003csub\u003eij\u003c/sub\u003e_ is the weight of the edge between nodes _i_ and _j_\n- _k\u003csub\u003ei\u003c/sub\u003e_ and _k\u003csub\u003ej\u003c/sub\u003e_ are the sum of the weights of the edges attached to nodes _i_ and _j_, respectively\n- _m_ is the sum of all of the edge weights in the graph\n\n**Parameters:**\n\n- `adj_matrix` _(numpy.ndarray)_: Adjacency matrix representation of your graph\n\n### Modularity\n\n**`modularity(mod_matrix : numpy.ndarray, communities : list) -\u003e float`**\n\nComputes modularity of a partitioned graph. Modularity is defined as:\n\n\u003cp align=\"left\"\u003e\u003cimg src=\"img/modularity.png\" width=\"275px\" /\u003e\u003c/p\u003e\n\nwhere\n\n- _A\u003csub\u003eij\u003c/sub\u003e_ is the weight of the edge between nodes _i_ and _j_\n- _k\u003csub\u003ei\u003c/sub\u003e_ and _k\u003csub\u003ej\u003c/sub\u003e_ are the sum of the weights of the edges attached to nodes _i_ and _j_, respectively\n- _m_ is the sum of all of the edge weights in the graph\n- _c\u003csub\u003ei\u003c/sub\u003e_ and _c\u003csub\u003ej\u003c/sub\u003e_ are the communities of the nodes\n- _δ_ is the Kronecker delta function (_δ(x, y) = 1_ if _x = y_, _0_ otherwise)\n\n**Parameters:**\n\n- `mod_matrix` _(numpy.ndarray)_: Modularity matrix computed from the adjacency matrix representation of your graph\n- `communities` _(list)_: List of (non-overlapping) communities identified in the graph\n\n**Example Usage:**\n\n```python\nfrom communities.algorithms import louvain_method\nfrom communities.utilities import modularity_matrix, modularity\n\nadj_matrix = [...]\ncommunities = louvain_method(adj_matrix)\n\nmod_matrix = modularity_matrix(adj_matrix)\nQ = modularity(mod_matrix, communities)\n```\n\n# Authors\n\n`communities` was created by Jonathan Shobrook with the help of [Paul C. Bogdan](https://github.com/paulcbogdan/) as part of our research in the [Dolcos Lab](https://dolcoslab.beckman.illinois.edu/) at the Beckman Institute for Advanced Science and Technology.\n","funding_links":[],"categories":["Python","其他_生物医药"],"sub_categories":["网络服务_其他"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshobrook%2Fcommunities","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshobrook%2Fcommunities","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshobrook%2Fcommunities/lists"}