statistical-ranking-wilcoxon-test
Summary
Apply the Wilcoxon rank-sum test to rank genes by differential expression across cell clusters in single-cell RNA-seq data. This non-parametric statistical test identifies marker genes for each cluster by computing log-fold-change and p-value scores, enabling robust cluster characterization without assuming expression normality.
When to use
When you have leiden or louvain cluster assignments in single-cell data (stored in adata.obs) and need to identify cluster-specific marker genes. Use this skill when comparing gene expression distributions between a focal cluster and all other cells, particularly when expression values may violate normality assumptions or when you need reproducible, documented statistical rankings that match published benchmarks.
When NOT to use
- Cluster assignments are missing or unreliable — ensure clustering is complete and validated before ranking.
- Input is bulk RNA-seq or non-clustered data — Wilcoxon ranking requires meaningful group structure.
- Expression values are not on a compatible scale (e.g., raw counts without normalization) — Scanpy typically expects log-normalized or scaled input.
Inputs
- AnnData object (adata) with raw or normalized gene expression matrix
- Cluster assignments in adata.obs (e.g., 'leiden' or 'louvain' column)
- Gene expression matrix (cells × genes), typically log-transformed counts or normalized values
Outputs
- Ranked gene list per cluster with log-fold-change scores
- Adjusted p-values (stored in adata.uns['rank_genes_groups'])
- Summary DataFrame of top marker genes per cluster (via sc.get.rank_genes_groups_df)
How to apply
Load your clustered AnnData object and call sc.tl.rank_genes_groups(adata, groupby='leiden', method='wilcoxon') to compute Wilcoxon test statistics across all clusters. The function tests each gene in each cluster against all other cells, computing log-fold-change and adjusted p-values. Extract results via sc.get.rank_genes_groups_df(adata) or from adata.uns['rank_genes_groups']. Validate by comparing the top 5–10 ranked genes per cluster against known marker genes documented in your experimental context, checking that log-fold-change and p-value scores fall within expected ranges (e.g., |log2FC| > 0.25, p_adj < 0.05). Wilcoxon's non-parametric nature makes it robust to outliers and non-normal distributions common in sparse single-cell data.
Related tools
- Scanpy (Primary tool for differential expression ranking via sc.tl.rank_genes_groups with Wilcoxon method and result extraction via sc.get.rank_genes_groups_df) — https://github.com/scverse/scanpy
- anndata (Data structure (AnnData) that stores clustered single-cell data, cluster assignments, and ranking results) — https://github.com/scverse/anndata
- Python (Programming language for executing Scanpy workflows and result validation)
Examples
import scanpy as sc
adata = sc.datasets.pbmc3k_processed()
sc.tl.rank_genes_groups(adata, groupby='leiden', method='wilcoxon')
results_df = sc.get.rank_genes_groups_df(adata)
print(results_df.head(10))
Evaluation signals
- Top-ranked genes per cluster match documented marker gene names for that cell type in published single-cell references or experimental validation studies.
- Log-fold-change values are in expected range (typically |log2FC| ≥ 0.25 for marker genes) and p-values are below significance threshold (p_adj < 0.05).
- Gene ranking order is stable across replicate runs and consistent with cluster identity (e.g., immune markers in immune clusters, neuronal markers in neuronal clusters).
- Summary table of top 5 marker genes per cluster shows no duplicate or ubiquitous genes, confirming cluster-specific differential expression.
- Result structure matches adata.uns['rank_genes_groups'] schema with 'names', 'logfoldchanges', and 'pvals_adj' keys for each group.
Limitations
- Wilcoxon test assumes independent observations; if cells are highly correlated (e.g., from the same tissue sample), p-values may be overly optimistic.
- The method ranks genes within pairwise comparisons of one cluster vs. rest; it does not account for multi-cluster structure or overlapping marker signatures.
- Performance scales with cluster size and gene count; extremely large datasets may require subsampling or sparse matrix optimizations for computation time.
- Log-fold-change calculation depends on library size normalization; poor normalization upstream will distort fold-change estimates.
- Multiple testing correction (typically FDR) is applied but may still yield false positives in highly granular clustering schemes with many rare clusters.
Evidence
- [other] Wilcoxon test method supported by Scanpy's rank_genes_groups function: "Run sc.tl.rank_genes_groups(adata, groupby='leiden', method='wilcoxon') to compute differential gene expression ranks across leiden clusters."
- [intro] Differential expression testing as core Scanpy capability: "It includes preprocessing, visualization, clustering, trajectory inference and differential expression testing"
- [other] Result extraction and validation approach: "Extract the result DataFrame using sc.get.rank_genes_groups_df(adata) or access adata.uns['rank_genes_groups']. Validate that the top-ranked genes per cluster match the documented marker gene names"
- [intro] Scanpy built on AnnData for single-cell analysis: "Scanpy is a scalable toolkit for analyzing single-cell gene expression data built jointly with anndata"
- [other] Example workflow using pbmc3k dataset: "Verify that leiden cluster assignments are present in adata.obs. Run sc.tl.rank_genes_groups(adata, groupby='leiden', method='wilcoxon') to compute differential gene expression ranks across leiden"
1---2name: statistical-ranking-wilcoxon-test3description: Use when when you have leiden or louvain cluster assignments in single-cell data (stored in adata.obs) and need to identify cluster-specific marker genes.4license: CC-BY-4.05---67# statistical-ranking-wilcoxon-test89## Summary1011Apply the Wilcoxon rank-sum test to rank genes by differential expression across cell clusters in single-cell RNA-seq data. This non-parametric statistical test identifies marker genes for each cluster by computing log-fold-change and p-value scores, enabling robust cluster characterization without assuming expression normality.1213## When to use1415When you have leiden or louvain cluster assignments in single-cell data (stored in adata.obs) and need to identify cluster-specific marker genes. Use this skill when comparing gene expression distributions between a focal cluster and all other cells, particularly when expression values may violate normality assumptions or when you need reproducible, documented statistical rankings that match published benchmarks.1617## When NOT to use1819- Cluster assignments are missing or unreliable — ensure clustering is complete and validated before ranking.20- Input is bulk RNA-seq or non-clustered data — Wilcoxon ranking requires meaningful group structure.21- Expression values are not on a compatible scale (e.g., raw counts without normalization) — Scanpy typically expects log-normalized or scaled input.2223## Inputs2425- AnnData object (adata) with raw or normalized gene expression matrix26- Cluster assignments in adata.obs (e.g., 'leiden' or 'louvain' column)27- Gene expression matrix (cells × genes), typically log-transformed counts or normalized values2829## Outputs3031- Ranked gene list per cluster with log-fold-change scores32- Adjusted p-values (stored in adata.uns['rank_genes_groups'])33- Summary DataFrame of top marker genes per cluster (via sc.get.rank_genes_groups_df)3435## How to apply3637Load your clustered AnnData object and call sc.tl.rank_genes_groups(adata, groupby='leiden', method='wilcoxon') to compute Wilcoxon test statistics across all clusters. The function tests each gene in each cluster against all other cells, computing log-fold-change and adjusted p-values. Extract results via sc.get.rank_genes_groups_df(adata) or from adata.uns['rank_genes_groups']. Validate by comparing the top 5–10 ranked genes per cluster against known marker genes documented in your experimental context, checking that log-fold-change and p-value scores fall within expected ranges (e.g., |log2FC| > 0.25, p_adj < 0.05). Wilcoxon's non-parametric nature makes it robust to outliers and non-normal distributions common in sparse single-cell data.3839## Related tools4041- **Scanpy** (Primary tool for differential expression ranking via sc.tl.rank_genes_groups with Wilcoxon method and result extraction via sc.get.rank_genes_groups_df) — https://github.com/scverse/scanpy42- **anndata** (Data structure (AnnData) that stores clustered single-cell data, cluster assignments, and ranking results) — https://github.com/scverse/anndata43- **Python** (Programming language for executing Scanpy workflows and result validation)4445## Examples4647```48import scanpy as sc49adata = sc.datasets.pbmc3k_processed()50sc.tl.rank_genes_groups(adata, groupby='leiden', method='wilcoxon')51results_df = sc.get.rank_genes_groups_df(adata)52print(results_df.head(10))53```5455## Evaluation signals5657- Top-ranked genes per cluster match documented marker gene names for that cell type in published single-cell references or experimental validation studies.58- Log-fold-change values are in expected range (typically |log2FC| ≥ 0.25 for marker genes) and p-values are below significance threshold (p_adj < 0.05).59- Gene ranking order is stable across replicate runs and consistent with cluster identity (e.g., immune markers in immune clusters, neuronal markers in neuronal clusters).60- Summary table of top 5 marker genes per cluster shows no duplicate or ubiquitous genes, confirming cluster-specific differential expression.61- Result structure matches adata.uns['rank_genes_groups'] schema with 'names', 'logfoldchanges', and 'pvals_adj' keys for each group.6263## Limitations6465- Wilcoxon test assumes independent observations; if cells are highly correlated (e.g., from the same tissue sample), p-values may be overly optimistic.66- The method ranks genes within pairwise comparisons of one cluster vs. rest; it does not account for multi-cluster structure or overlapping marker signatures.67- Performance scales with cluster size and gene count; extremely large datasets may require subsampling or sparse matrix optimizations for computation time.68- Log-fold-change calculation depends on library size normalization; poor normalization upstream will distort fold-change estimates.69- Multiple testing correction (typically FDR) is applied but may still yield false positives in highly granular clustering schemes with many rare clusters.7071## Evidence7273- [other] Wilcoxon test method supported by Scanpy's rank_genes_groups function: "Run sc.tl.rank_genes_groups(adata, groupby='leiden', method='wilcoxon') to compute differential gene expression ranks across leiden clusters."74- [intro] Differential expression testing as core Scanpy capability: "It includes preprocessing, visualization, clustering, trajectory inference and differential expression testing"75- [other] Result extraction and validation approach: "Extract the result DataFrame using sc.get.rank_genes_groups_df(adata) or access adata.uns['rank_genes_groups']. Validate that the top-ranked genes per cluster match the documented marker gene names"76- [intro] Scanpy built on AnnData for single-cell analysis: "Scanpy is a scalable toolkit for analyzing single-cell gene expression data built jointly with anndata"77- [other] Example workflow using pbmc3k dataset: "Verify that leiden cluster assignments are present in adata.obs. Run sc.tl.rank_genes_groups(adata, groupby='leiden', method='wilcoxon') to compute differential gene expression ranks across leiden"