SPAROscore is a gene signature scoring method designed to be robust across diverse gene expression datasets. SPAROscore adapts to varying levels of sparsity, allowing signature scores to be efficiently computed across bulk, single-cell, and spatial transcriptomic datasets.
The resulting scores quantify the relative expression of a gene signature compared with the background expression of each sample/cell/domain, making the scores straightforward to interpret biologically.
Internally, SPAROscore ranks genes within each column and computes the Spearman footrule distance between the observed ranks of the signature genes and a background gene expression rank estimated from the geometric mean expression of the sample, cell, or spatial domain.
To use SPAROscore, at minimum, a gene expression dataset and one or more gene signatures are required.
To demonstrate this, we will use the gene expression matrix from the
airway package, containing RNA-seq read counts from eight
human airway smooth muscle (ASM) cell line samples: four treated with
dexamethasone and four untreated controls.
As an example gene signature, we use the top differentially expressed genes reported in the original study.
The expression matrix contains genes in rows and samples in columns. The accompanying metadata indicates whether each sample received dexamethasone treatment (trt) or served as an untreated control (untrt).
# load the airway dataset
data(airway)
# extract the gene expression matrix
counts_data <- assay(airway)
# extract the metadata
metadata <- as.data.frame(colData(airway))
# view sample level dexamethasone treatment status
metadata[, c("Run", "dex")]
#> Run dex
#> SRR1039508 SRR1039508 untrt
#> SRR1039509 SRR1039509 trt
#> SRR1039512 SRR1039512 untrt
#> SRR1039513 SRR1039513 trt
#> SRR1039516 SRR1039516 untrt
#> SRR1039517 SRR1039517 trt
#> SRR1039520 SRR1039520 untrt
#> SRR1039521 SRR1039521 trt
# set the glucocorticoid response markers as the gene signature
signature_genes <- c("ENSG00000112936", "ENSG00000170606", "ENSG00000120129",
"ENSG00000152795", "ENSG00000211445", "ENSG00000163884",
"ENSG00000189221", "ENSG00000101347", "ENSG00000196136",
"ENSG00000152583", "ENSG00000120658", "ENSG00000157514",
"ENSG00000103196", "ENSG00000179094", "ENSG00000152763",
"ENSG00000103310", "ENSG00000127954")
# check if the gene ids in the signature match with that of the counts_data
head(signature_genes %in% rownames(counts_data))
#> [1] TRUE TRUE TRUE TRUE TRUE TRUEscores <- sparoscore(data = counts_data, signatures = signature_genes)
#> SPAROscore says: Calculating column-wise geometric averages
#> SPAROscore says: Ranking a matrix object
# view the scores
scores
#> SPAROscore
#> SRR1039508 0.5238153
#> SRR1039509 0.7654385
#> SRR1039512 0.5495932
#> SRR1039513 0.7473585
#> SRR1039516 0.5337068
#> SRR1039517 0.7162212
#> SRR1039520 0.5222398
#> SRR1039521 0.7593574Since dexamethasone activates glucocorticoid signalling, treated samples are expected to exhibit higher glucocorticoid response scores than untreated controls.
# add the signature scores to the metadata
metadata$SPAROscore <- scores[, 1]
# plot results
ggplot(metadata, aes(x = dex, y = SPAROscore, fill = dex)) +
geom_boxplot(width = 0.6, outlier.shape = NA) +
geom_jitter(width = 0.12, size = 3) +
xlab("Treatment") +
ylab("SPAROscore")+
ggtitle("Glucocorticoid response signature activity")+
theme_classic()SPAROscore is a rank-based gene signature scoring method designed to provide robust signature scores across a wide range of transcriptomics technologies, adapting automatically to the differences in platform-specific sequencing depth, expression sparsity, and technical variation.
As a result, the same scoring framework of SPAROscore can be applied consistently to bulk RNA sequencing, single-cell RNA sequencing, and spatial transcriptomics data without requiring platform-specific adjustments.
More information on how SPAROscore can be integrated into the analysis workflows of different transcriptomics technologies can be found here: Transcriptomics technologies
SPAROscore accepts a wide variety of commonly used data structures, including dense matrices, sparse matrices, DelayedArray, SummarizedExperiment, SingleCellExperiment, SpatialExperiment, and Seurat objects.
When dealing with transcriptomics-specific data structures like Seurat objects and SummarizedExperiment-derived objects, SPAROscore appends the scores to the existing metadata, to enhance further analyses.
SPAROscore can also handle multiple data structures for the gene signatures, including character vector, list of character vectors, GeneSet objects and GeneSetCollection objects, enabling single and multiple signature scoring.
More information on data structures and example codes can be found here: Data structures
By default, background gene expression is approximated using geometric mean expression values. This approximation can be overridden to accommodate biological contexts in which signature genes are expected to have lower expression. Users may provide custom background expression values to better reflect these conditions and tailor the scoring accordingly.
Because gene ranking is the most computationally intensive step, SPAROscore supports storing gene rankings for reuse in future scoring analyses. This avoids redundant computations and substantially improves performance.
For examples of additional options and more advanced usage, see: Advanced options
sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.32.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats4 stats graphics grDevices utils datasets methods
#> [8] base
#>
#> other attached packages:
#> [1] scater_1.41.2 ggplot2_4.0.3
#> [3] scuttle_1.23.1 SingleCellExperiment_1.35.2
#> [5] Seurat_5.5.1 SeuratObject_5.4.0
#> [7] sp_2.2-3 GSEABase_1.75.0
#> [9] graph_1.91.0 annotate_1.91.0
#> [11] XML_3.99-0.23 AnnotationDbi_1.75.2
#> [13] DelayedArray_0.39.3 SparseArray_1.13.2
#> [15] S4Arrays_1.13.0 abind_1.4-8
#> [17] Matrix_1.7-5 dplyr_1.2.1
#> [19] msigdbr_26.1.0 airway_1.33.2
#> [21] SummarizedExperiment_1.43.0 Biobase_2.73.1
#> [23] GenomicRanges_1.65.1 Seqinfo_1.3.0
#> [25] IRanges_2.47.2 S4Vectors_0.51.5
#> [27] BiocGenerics_0.59.10 generics_0.1.4
#> [29] MatrixGenerics_1.25.0 matrixStats_1.5.0
#> [31] SPAROscore_0.99.3 rmarkdown_2.31
#>
#> loaded via a namespace (and not attached):
#> [1] RcppAnnoy_0.0.23 splines_4.6.1
#> [3] later_1.4.8 tibble_3.3.1
#> [5] polyclip_1.10-7 fastDummies_1.7.6
#> [7] lifecycle_1.0.5 globals_0.19.1
#> [9] lattice_0.22-9 MASS_7.3-66
#> [11] magrittr_2.0.5 plotly_4.12.0
#> [13] sass_0.4.10 jquerylib_0.1.4
#> [15] yaml_2.3.12 httpuv_1.6.17
#> [17] otel_0.2.0 sctransform_0.4.3
#> [19] spam_2.11-4 spatstat.sparse_3.2-0
#> [21] reticulate_1.46.0 cowplot_1.2.0
#> [23] pbapply_1.7-4 DBI_1.3.0
#> [25] buildtools_1.0.0 RColorBrewer_1.1-3
#> [27] Rtsne_0.17 purrr_1.2.2
#> [29] ggrepel_0.9.8 irlba_2.3.7
#> [31] listenv_1.0.0 spatstat.utils_3.2-4
#> [33] maketools_1.3.2 goftest_1.2-3
#> [35] RSpectra_0.16-2 spatstat.random_3.5-0
#> [37] fitdistrplus_1.2-6 parallelly_1.48.0
#> [39] DelayedMatrixStats_1.35.0 codetools_0.2-20
#> [41] tidyselect_1.2.1 farver_2.1.2
#> [43] viridis_0.6.5 ScaledMatrix_1.21.0
#> [45] spatstat.explore_3.8-1 jsonlite_2.0.0
#> [47] BiocNeighbors_2.7.2 progressr_1.0.0
#> [49] ggridges_0.5.7 survival_3.8-9
#> [51] tools_4.6.1 ica_1.0-3
#> [53] Rcpp_1.1.2 glue_1.8.1
#> [55] gridExtra_2.3.1 BiocBaseUtils_1.15.1
#> [57] xfun_0.60 withr_3.0.3
#> [59] fastmap_1.2.0 rsvd_1.0.5
#> [61] digest_0.6.39 R6_2.6.1
#> [63] mime_0.13 scattermore_1.2
#> [65] tensor_1.5.1 spatstat.data_3.1-9
#> [67] RSQLite_3.53.3 tidyr_1.3.2
#> [69] data.table_1.18.4 httr_1.4.8
#> [71] htmlwidgets_1.6.4 uwot_0.2.4
#> [73] pkgconfig_2.0.3 gtable_0.3.6
#> [75] blob_1.3.0 lmtest_0.9-40
#> [77] S7_0.2.2 XVector_0.53.0
#> [79] sys_3.4.3 htmltools_0.5.9
#> [81] dotCall64_1.2 scales_1.4.0
#> [83] png_0.1-9 spatstat.univar_3.2-0
#> [85] knitr_1.51 reshape2_1.4.5
#> [87] nlme_3.1-170 curl_7.1.0
#> [89] cachem_1.1.0 zoo_1.8-15
#> [91] stringr_1.6.0 KernSmooth_2.23-26
#> [93] vipor_0.4.7 parallel_4.6.1
#> [95] miniUI_0.1.2 pillar_1.11.1
#> [97] grid_4.6.1 vctrs_0.7.3
#> [99] RANN_2.6.2 promises_1.5.0
#> [101] BiocSingular_1.29.0 beachmat_2.29.0
#> [103] xtable_1.8-8 cluster_2.1.8.2
#> [105] beeswarm_0.4.0 evaluate_1.0.5
#> [107] cli_3.6.6 compiler_4.6.1
#> [109] rlang_1.3.0 crayon_1.5.3
#> [111] future.apply_1.20.2 labeling_0.4.3
#> [113] ggbeeswarm_0.7.3 plyr_1.8.9
#> [115] stringi_1.8.7 viridisLite_0.4.3
#> [117] deldir_2.0-4 BiocParallel_1.47.0
#> [119] assertthat_0.2.1 babelgene_22.9
#> [121] Biostrings_2.81.5 lazyeval_0.2.3
#> [123] spatstat.geom_3.8-1 RcppHNSW_0.7.0
#> [125] patchwork_1.3.2 sparseMatrixStats_1.25.0
#> [127] bit64_4.8.2 future_1.75.0
#> [129] KEGGREST_1.53.5 shiny_1.14.0
#> [131] ROCR_1.0-12 igraph_2.3.3
#> [133] memoise_2.0.1 bslib_0.11.0
#> [135] bit_4.6.0