A comprehensive clustering toolkit with advanced tree cutting and visualization
Project description
skclust
A comprehensive clustering toolkit with hierarchical clustering, k-nearest neighbors, and consensus network analysis.
Features
- Scikit-learn compatible API for seamless integration
- Hierarchical clustering with multiple linkage methods and tree cutting strategies
- K-nearest neighbors with cosine similarity using FAISS or sklearn backends
- Consensus Leiden clustering with parallel execution and edge co-occurrence analysis
- Cluster validation metrics for continuous and binary features
- FAISS-based kNN classifiers and transformers via DESlib integration
- Rich visualizations with dendrograms and metadata tracks
- Distance matrix utilities for kNN graph construction and conversion
Installation
pip install skclust
Optional Dependencies
# For enhanced hierarchical clustering
pip install dynamicTreeCut fastcluster skbio
# For visualization
pip install matplotlib seaborn
# For Leiden clustering
pip install leidenalg igraph
# For fast k-NN with large datasets
pip install faiss-cpu # or faiss-gpu (Python < 3.13)
# For FAISS-based kNN classifier/transformer (via DESlib)
pip install deslib
# For ensemble network analysis
pip install ensemble-networkx
Quick Start
Hierarchical Clustering
import pandas as pd
import numpy as np
from sklearn.datasets import make_blobs
from skclust.hierarchical import HierarchicalClustering
# Generate sample data
X, y = make_blobs(n_samples=100, centers=4, random_state=42)
X_df = pd.DataFrame(X, columns=['feature_1', 'feature_2'])
# Perform hierarchical clustering with dynamic tree cutting
hc = HierarchicalClustering(
method='ward',
cut_method='dynamic',
min_cluster_size=5,
cluster_prefix='C'
)
# Fit and get cluster labels
labels = hc.fit_transform(X_df)
print(f"Found {hc.n_clusters_} clusters")
# Plot dendrogram with clusters
fig, axes = hc.plot(figsize=(12, 6), show_clusters=True)
Output: Cluster labels as numpy array (e.g., ['C1', 'C1', 'C2', ...]) with hc.n_clusters_ indicating the number of clusters found.
Consensus Leiden Clustering
import igraph as ig
from skclust.graph import ConsensusLeidenClustering
# Create graph
graph = ig.Graph.Famous('Zachary')
graph.vs['name'] = [f'node_{i}' for i in range(graph.vcount())]
# Run consensus clustering with 100 iterations in parallel
leiden = ConsensusLeidenClustering(
n_iter=100,
resolution_parameter=1.0,
consensus_threshold=1.0,
minimum_cluster_size=3,
n_jobs=-1,
random_state=42
)
labels = leiden.fit_transform(graph)
print(f"Found {leiden.n_clusters_} clusters")
print(f"Consensus edges: {leiden.consensus_graph_.ecount()}")
print(f"Modularity (filtered): {leiden.modularity_['filtered']:.3f}")
Output: Returns pandas Series with cluster labels indexed by node names. The consensus_graph_ contains only edges where nodes consistently clustered together across all iterations. Nodes in clusters smaller than minimum_cluster_size are available via discarded_nodes_.
K-Nearest Neighbors with Cosine Similarity
import numpy as np
from skclust.neighbors import KNeighborsCosineSimilarity
# L2-normalized embeddings (required for cosine similarity)
embeddings = np.random.randn(1000, 128).astype(np.float32)
embeddings = embeddings / np.linalg.norm(embeddings, axis=1, keepdims=True)
# Exact search
knn = KNeighborsCosineSimilarity(n_neighbors=10, mode='exact')
similarities, indices = knn.fit_transform(embeddings)
# Convert to igraph for network analysis
graph = knn.to_igraph(include_self=False)
Output: similarities is shape (n_samples, k) with cosine similarity values (higher = more similar). indices contains the neighbor indices for each sample.
Module Overview
skclust.hierarchical
HierarchicalClustering
Hierarchical clustering with multiple linkage methods and tree cutting strategies.
Key Parameters:
method: Linkage method ('ward', 'complete', 'average', 'single')cut_method: Tree cutting strategy ('dynamic', 'height', 'maxclust')min_cluster_size: Minimum cluster size for dynamic cuttingcluster_prefix: String prefix for cluster labels (e.g., "C" produces "C1", "C2")
Key Methods:
fit(X): Fit clustering to data (accepts arrays or DataFrames)transform(): Return cluster labelsadd_track(name, data, track_type): Add metadata for visualizationplot(): Generate dendrogram with optional tracks and cluster colorssummary(): Print clustering statistics
Attributes:
labels_: Cluster assignments for each samplen_clusters_: Number of clusters foundlinkage_matrix_: Scipy linkage matrixdendrogram_: Dendrogram data structure
skclust.graph
ConsensusLeidenClustering
Runs Leiden clustering multiple times with different random seeds, computes edge consensus ratios, and builds a consensus graph from edges meeting the threshold. Final labels come from connected components, optionally filtered by minimum cluster size.
Key Parameters:
n_iter: Number of Leiden iterations (default: 100)resolution_parameter: Controls cluster size (1.0 = modularity, >1.0 = smaller clusters)consensus_threshold: Minimum consensus ratio for edges (default: 1.0, i.e. 100% agreement)minimum_cluster_size: Clusters smaller than this are removed fromlabels_(default: 1)weight: Edge weight attribute name (default: None for unweighted)n_jobs: Number of parallel processes (-1 = use all CPUs)cluster_prefix: String prefix for cluster labels (default: "leiden_")verbose: Verbosity level 0-3 (0=silent, 1=progress bars, 2=stage info, 3=detailed timing)
Key Methods:
fit(graph): Fit on igraph.Graph with named verticestransform(graph): Return cluster labels as pandas Seriesget_membership_matrix(): Return membership matrix as a pandas DataFrame with SparseDtype
Attributes:
labels_: Cluster labels for nodes in qualifying clusters (pd.Series)n_clusters_: Number of clusters meetingminimum_cluster_sizepartitions_: Node assignments for each iteration (DataFrame)membership_matrix_: Sparse boolean edge co-membership matrix (scipy.sparse.csr_matrix)consensus_ratio_: Proportion of iterations each edge had consistent membership (pd.Series)consensus_edges_: Edge pairs meetingconsensus_threshold(pd.Index)consensus_graph_: Subgraph with only consensus edges, pruned to qualifying clustersconsensus_graph_discarded_: Consensus edges for small clusters that were filtered outfiltered_graph_: Original edge structure induced on nodes in qualifying clustersmodularity_: Modularity scores for initial, consensus, and filtered graphs (pd.Series)summary_: Comprehensive summary with graph sizes, consensus metrics, and modularityunstable_nodes_: Nodes with no consensus edges across iterationsdiscarded_nodes_: Nodes in stable but too-small clusters
leiden_stability(consensus_ratio)
Computes comprehensive stability metrics from consensus ratio values.
cluster_membership_cooccurrence(df)
Compute edge-wise cluster co-occurrence across iterations.
Parameters:
df: DataFrame where rows are nodes and columns are iterations
Returns: Sparse boolean matrix showing whether each node pair shared cluster membership in each iteration.
skclust.neighbors
KNeighborsCosineSimilarity
K-nearest neighbors using cosine similarity with FAISS or sklearn backend.
Key Parameters:
n_neighbors: Number of neighbors to findmode: Search strategy ('exact', 'ivf', 'pq')backend: Library to use ('auto', 'faiss', 'sklearn')
Key Methods:
fit(X): Fit on L2-normalized embeddingstransform(X): Return (similarities, indices) for query vectorsto_igraph(): Convert to directed igraph
Attributes:
similarities_: Cosine similarities to k nearest neighborsindices_: Indices of k nearest neighbors
FaissKNNClassifier
Sklearn-compatible kNN classifier using FAISS via DESlib. Supports exact (brute), Voronoi (IVF), and hierarchical (HNSW) search algorithms.
Key Parameters:
n_neighbors: Number of neighbors (default: 5)algorithm: Search strategy ('brute', 'voronoi', 'hierarchical')n_jobs: Number of parallel jobs
Key Methods:
fit(X, y): Fit classifierpredict(X): Predict class labels via majority votekneighbors(X): Return (distances, indices) of k nearest neighbors
FaissKNNTransformer
Sklearn-compatible kNN transformer using FAISS via DESlib. Outputs a sparse distance matrix matching sklearn's KNeighborsTransformer interface.
Key Parameters:
n_neighbors: Number of neighbors (default: 5)algorithm: Search strategy ('brute', 'voronoi', 'hierarchical')
Key Methods:
fit(X): Fit transformertransform(X): Return sparse csr_matrix of L2 distances to k nearest neighbors
Utility Functions:
kneighbors_graph_from_transformer(): Build kNN graph from any KNeighborsTransformerbrute_force_kneighbors_graph_from_rectangular_distance(): Build kNN graph from distance matrixpairwise_distances_kneighbors(): Compute full or sparse pairwise distancesconvert_distance_matrix_to_kneighbors_matrix(): Convert dense distance matrix to sparse kNN matrixkneighbors_to_igraph(): Convert kNN results to igraphkneighbors_classification_assignment_score(): Compute assignment quality metrics (ambiguity detection) for kNN classification
skclust.metrics
Cluster validation metrics for evaluating cluster quality.
Continuous Features:
cv_score(X, labels): Coefficient of variation within each cluster (lower = more compact)eta_squared_score(X, labels): Eta-squared (η²), ratio of between-cluster variance to total variance (higher = more separated)
Binary Features:
entropy_score(X, labels): Shannon entropy within each cluster (lower = more consistent)cramers_v_score(X, labels): Cramér's V association between cluster membership and feature values (higher = more separated)
Advanced Usage
Adding Metadata Tracks to Dendrograms
# Add continuous metadata
sample_scores = pd.Series(np.random.randn(100), index=X_df.index)
hc.add_track('Quality Score', sample_scores, track_type='continuous')
# Add categorical metadata
sample_groups = pd.Series(['A', 'B', 'C'] * 34, index=X_df.index[:100])
hc.add_track('Group', sample_groups, track_type='categorical')
# Plot with all tracks
fig, axes = hc.plot(show_tracks=True, figsize=(12, 10))
Output: Multi-panel plot with dendrogram on top, followed by cluster assignments and metadata tracks below, all aligned to the same sample order.
Custom Tree Cutting
# Cut by height threshold
hc_height = HierarchicalClustering(
method='ward',
cut_method='height',
cut_threshold=50.0
)
labels = hc_height.fit_transform(X_df)
# Force specific number of clusters
hc_maxclust = HierarchicalClustering(
method='complete',
cut_method='maxclust',
cut_threshold=5
)
labels = hc_maxclust.fit_transform(X_df)
Output: cut_method='height' cuts tree at specified distance threshold. cut_method='maxclust' produces exactly the specified number of clusters.
Using Distance Matrices
from scipy.spatial.distance import pdist, squareform
# Compute custom distance matrix
distances = pdist(X_df, metric='cosine')
distance_matrix = pd.DataFrame(
squareform(distances),
index=X_df.index,
columns=X_df.index
)
# Cluster using precomputed distances
hc = HierarchicalClustering(method='average')
labels = hc.fit_transform(distance_matrix)
Output: Works identically to feature-based clustering but uses pre-computed distances. Useful for custom metrics.
Approximate k-NN with FAISS
# For large datasets, use approximate search
knn_ivf = KNeighborsCosineSimilarity(
n_neighbors=50,
mode='ivf',
n_voronoi_cells='auto',
n_probes=4
)
similarities, indices = knn_ivf.fit_transform(embeddings)
# Product quantization for memory efficiency
knn_pq = KNeighborsCosineSimilarity(
n_neighbors=50,
mode='pq',
n_subvectors=16,
n_bits=8
)
similarities, indices = knn_pq.fit_transform(embeddings)
Output: Faster but approximate nearest neighbor search. IVF uses inverted file index, PQ uses compressed representations. Trade accuracy for speed on large datasets.
Author
Josh L. Espinoza
License
Apache License 2.0 - see the LICENSE file for details.
Original Implementation
The hierarchical clustering implementation is based on the Soothsayer framework:
Espinoza JL, Dupont CL, O'Rourke A, Beyhan S, Morales P, et al. (2021) Predicting antimicrobial mechanism-of-action from transcriptomes: A generalizable explainable artificial intelligence approach. PLOS Computational Biology 17(3): e1008857. https://doi.org/10.1371/journal.pcbi.1008857
Citation
If you use this package in your research, please cite:
@article{espinoza2021predicting,
title={Predicting antimicrobial mechanism-of-action from transcriptomes: A generalizable explainable artificial intelligence approach},
author={Espinoza, Josh L and Dupont, Chris L and O'Rourke, Aubrie and Beyhan, Seherzada and Morales, Paula and others},
journal={PLOS Computational Biology},
volume={17},
number={3},
pages={e1008857},
year={2021},
publisher={Public Library of Science San Francisco, CA USA},
doi={10.1371/journal.pcbi.1008857},
url={https://doi.org/10.1371/journal.pcbi.1008857}
}
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file skclust-2026.6.17.tar.gz.
File metadata
- Download URL: skclust-2026.6.17.tar.gz
- Upload date:
- Size: 49.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
525567ee1c62db57aa9d8051544f060090002c2129e0b27580386608892f5dd7
|
|
| MD5 |
48242bb8cb78eeb9f3f0ef53a3fb7e3d
|
|
| BLAKE2b-256 |
0b224e1680b1a90d0467dc8234ab96fedaede3fbb96b6f814c4d66646fde2c73
|