# How CRG Supports Community Detection: Network-Based Code Review Analysis Explained

> Discover how CRG enables community detection by analyzing pull request patterns. Our network-based approach reveals developer groups and team structures using the Louvain algorithm.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: deep-dive
- Published: 2026-08-10

---

**Community detection in CRG uses NetworkX's Louvain algorithm to partition code review graphs into collaborative developer groups, revealing natural team structures from pull request interaction patterns.**

The Code Review Graph (CRG) library transforms code review data into network structures where developers are nodes and their collaborative activities are edges. Understanding how CRG supports **community detection** requires examining its graph construction pipeline and the specific algorithms applied to identify developer clusters.

## Core Architecture: From Reviews to Communities

CRG builds developer collaboration networks by analyzing **pull request review patterns**. The [`build_graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/build_graph.py) module constructs weighted graphs where edge weights represent review frequency and sentiment between developers.

### Graph Construction Pipeline

In [[`src/build_graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/src/build_graph.py)](https://github.com/tirth8205/code-review-graph/blob/main/src/build_graph.py), the `ReviewGraphBuilder` class handles the initial network formation:

```python

# From src/build_graph.py

class ReviewGraphBuilder:
    def __init__(self, min_reviews=1):
        self.graph = nx.Graph()
        self.min_reviews = min_reviews  # Threshold for edge creation

    
    def add_review_interaction(self, reviewer, author, pr_id, sentiment_score):
        """Adds weighted edge based on review sentiment."""
        if self.graph.has_edge(reviewer, author):
            self.graph[reviewer][author]['weight'] += sentiment_score
            self.graph[reviewer][author]['reviews'] += 1
        else:
            self.graph.add_edge(
                reviewer, 
                author, 
                weight=sentiment_score,
                reviews=1,
                prs=[pr_id]
            )

```

The resulting **undirected weighted graph** serves as input for community detection algorithms.

## Where Community Detection Is Implemented

The actual **community detection functionality** resides in [[`src/analyze_communities.py`](https://github.com/tirth8205/code-review-graph/blob/main/src/analyze_communities.py)](https://github.com/tirth8205/code-review-graph/blob/main/src/analyze_communities.py). This module implements three detection strategies using NetworkX and community libraries.

### Method 1: Louvain Algorithm (Default)

The `detect_communities_louvain()` function applies the `python-louvain` library for **modularity-based partitioning**:

```python

# From src/analyze_communities.py

import community as community_louvain
import networkx as nx

def detect_communities_louvain(graph, resolution=1.0):
    """
    Detects communities using Louvain algorithm.
    Higher resolution yields more, smaller communities.
    """
    partition = community_louvain.best_partition(
        graph,
        weight='weight',
        resolution=resolution,
        random_state=42
    )
    return partition  # Dict: {node: community_id}

```

**Parameters configured in CRG:**
- `weight='weight'` — Uses sentiment-weighted edges
- `resolution=1.0` — Standard modularity optimization
- `random_state=42` — Reproducible results

### Method 2: Greedy Modularity Maximization

For comparison, CRG includes NetworkX's native alternative in the same file:

```python

# From src/analyze_communities.py

from networkx.algorithms.community import greedy_modularity_communities

def detect_communities_greedy(graph):
    """Faster but potentially lower-quality communities."""
    communities = greedy_modularity_communities(
        graph, 
        weight='weight',
        resolution=1.0
    )
    # Convert to node->community mapping

    partition = {}
    for idx, comm in enumerate(communities):
        for node in comm:
            partition[node] = idx
    return partition

```

### Method 3: Label Propagation

For large-scale graphs where performance matters:

```python

# From src/analyze_communities.py

from networkx.algorithms.community import label_propagation_communities

def detect_communities_label_propagation(graph):
    """O(n) complexity, good for very large teams."""
    communities = label_propagation_communities(graph)
    partition = {node: idx for idx, comm in enumerate(communities) 
                 for node in comm}
    return partition

```

## Practical Usage: Running Community Detection

CRG exposes community detection through the CLI and Python API.

### Command-Line Interface

```bash

# Detect communities with default Louvain algorithm

python -m crg analyze \
    --graph data/review_graph.gpickle \
    --communities \
    --output communities.json

# Adjust resolution for finer-grained detection

python -m crg analyze \
    --graph data/review_graph.gpickle \
    --algorithm louvain \
    --resolution 1.5 \
    --output teams_high_res.json

```

### Python API

```python
from crg import ReviewGraphBuilder, CommunityAnalyzer
import networkx as nx

# Build graph from PR data

builder = ReviewGraphBuilder(min_reviews=3)
builder.load_from_csv("pull_requests.csv")
graph = builder.get_graph()

# Run community detection

analyzer = CommunityAnalyzer(graph)
communities = analyzer.detect(
    method='louvain',      # or 'greedy', 'label_propagation'

    resolution=1.2         # Tune community granularity

)

# Analyze results

print(f"Detected {len(set(communities.values()))} communities")
metrics = analyzer.modularity_score(communities)  # Quality metric

```

## Community Evaluation Metrics

The `CommunityAnalyzer` class in [[`src/analyze_communities.py`](https://github.com/tirth8205/code-review-graph/blob/main/src/analyze_communities.py)](https://github.com/tirth8205/code-review-graph/blob/main/src/analyze_communities.py) provides validation:

```python

# From src/analyze_communities.py

class CommunityAnalyzer:
    def modularity_score(self, partition):
        """Returns modularity Q, range [-0.5, 1]. 
        Q > 0.3 indicates significant community structure."""
        return community_louvain.modularity(
            partition, 
            self.graph,
            weight='weight'
        )
    
    def community_stats(self, partition):
        """Returns size distribution and density per community."""
        from collections import Counter
        sizes = Counter(partition.values())
        return {
            'num_communities': len(sizes),
            'avg_size': sum(sizes.values()) / len(sizes),
            'largest': max(sizes.values()),
            'smallest': min(sizes.values())
        }

```

## Integration with Visualization

Detected communities feed into CRG's visualization pipeline. In [[`src/visualize.py`](https://github.com/tirth8205/code-review-graph/blob/main/src/visualize.py)](https://github.com/tirth8205/code-review-graph/blob/main/src/visualize.py), the `plot_communities()` function applies color mapping:

```python

# From src/visualize.py

import matplotlib.pyplot as plt
import networkx as nx

def plot_communities(graph, partition, output_path):
    """Generates community-colored network visualization."""
    pos = nx.spring_layout(graph, weight='weight', seed=42)
    
    # Color by community

    cmap = plt.cm.get_cmap('tab20')
    colors = [partition[node] for node in graph.nodes()]
    
    plt.figure(figsize=(12, 12))
    nx.draw_networkx(
        graph,
        pos,
        node_color=colors,
        cmap=cmap,
        node_size=300,
        with_labels=True,
        font_size=8
    )
    plt.savefig(output_path, dpi=300, bbox_inches='tight')

```

## Configuration and Tuning

CRG supports community detection tuning via [[`config.yaml`](https://github.com/tirth8205/code-review-graph/blob/main/config.yaml)](https://github.com/tirth8205/code-review-graph/blob/main/config.yaml):

```yaml
community_detection:
  algorithm: louvain           # louvain | greedy | label_propagation

  resolution: 1.0              # 0.5=fewer communities, 2.0=more communities

  min_community_size: 3        # Filter out isolated reviewers

  weight_threshold: 0.0        # Minimum edge weight to include

```

## Key Files for Community Detection

| File | Purpose |
|------|---------|
| [[`src/analyze_communities.py`](https://github.com/tirth8205/code-review-graph/blob/main/src/analyze_communities.py)](https://github.com/tirth8205/code-review-graph/blob/main/src/analyze_communities.py) | Core detection algorithms and evaluation |
| [[`src/build_graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/src/build_graph.py)](https://github.com/tirth8205/code-review-graph/blob/main/src/build_graph.py) | Graph construction from review data |
| [[`src/visualize.py`](https://github.com/tirth8205/code-review-graph/blob/main/src/visualize.py)](https://github.com/tirth8205/code-review-graph/blob/main/src/visualize.py) | Community-colored network plots |
| [[`config.yaml`](https://github.com/tirth8205/code-review-graph/blob/main/config.yaml)](https://github.com/tirth8205/code-review-config.yaml) | Algorithm parameters and thresholds |

## Summary

- **CRG supports community detection** through the `CommunityAnalyzer` class in [`src/analyze_communities.py`](https://github.com/tirth8205/code-review-graph/blob/main/src/analyze_communities.py)
- **Default algorithm**: Louvain modularity optimization with configurable resolution
- **Alternative methods**: Greedy modularity and label propagation for performance-critical scenarios
- **Key feature**: Sentiment-weighted edges capture collaboration quality, not just frequency
- **Output**: Developer-to-community mappings with modularity scores for quality validation

## Frequently Asked Questions

### What algorithm does CRG use for community detection?

CRG uses the **Louvain algorithm** by default, implemented via the `python-louvain` library in [`src/analyze_communities.py`](https://github.com/tirth8205/code-review-graph/blob/main/src/analyze_communities.py). This algorithm optimizes modularity greedily and scales efficiently to thousands of developers. Two alternatives are built-in: NetworkX's `greedy_modularity_communities` and `label_propagation_communities`.

### How does CRG handle weighted edges in community detection?

Edge weights derive from **review sentiment scores** accumulated during graph construction. In `detect_communities_louvain()`, the `weight='weight'` parameter ensures higher-sentiment collaborations (positive, thorough reviews) exert stronger influence on community boundaries than negative or neutral interactions.

### Can I control the number of communities detected?

Yes, via the `resolution` parameter. Values above 1.0 produce more, smaller communities; values below 1.0 yield fewer, larger groups. Modify in Python (`resolution=1.5`) or [`config.yaml`](https://github.com/tirth8205/code-review-graph/blob/main/config.yaml). The resolution parameter directly scales modularity's linear term, as implemented in `community_louvain.best_partition()`.

### What modularity score indicates good community structure?

According to the `modularity_score()` implementation in CRG, **Q > 0.3** typically indicates significant community structure worth interpreting. Scores approaching 0.7 suggest very strong clustering. Negative scores indicate the detected partition is worse than random assignment.