Reduced dimension plotting is one of the essential tools for the
analysis of single cell data. However, as the number of cells/nuclei in
these plots increases, the usefulness of these plots decreases. Many
cells are plotted on top of each other obscuring information, even when
taking advantage of transparency settings. This package provides binning
strategies of cells/nuclei into hexagon cells. Plotting summarized
information of all cells/nuclei in their respective hexagon cells
presents information without obstructions. The package seemlessly works
with the two most common object classes for the storage of single cell
data; SingleCellExperiment from the SingleCellExperiment
package and Seurat from the Seurat package. In this
vignette I will be presenting the use of schex for
SingleCellExperiment objects that are converted from
Seurat objects.
In order to demonstrate the capabilities of the schex package, I will use the a subsetted dataset of Peripheral Blood Mononuclear Cells (PBMC) freely available from 10x Genomics. There are 80 single cells with 230 features in this dataset.
pbmc_small
#> An object of class Seurat
#> 230 features across 80 samples within 1 assay
#> Active assay: RNA (230 features, 20 variable features)
#> 3 layers present: counts, data, scale.data
#> 2 dimensional reductions calculated: pca, tsneThe dataset already contains two dimension reductions (PCA and TSNE). We will now add UMAP. Since there is a random component in the UMAP, we will set a seed. You can also add dimension reductions after conversion using package that include functionalities for SingleCellExperiment objects.
At this stage in the workflow we usually would like to plot aspects of our data in one of the reduced dimension representations. Instead of plotting this in an ordinary fashion, I will demonstrate how schex can provide a better way of plotting this.
First, I will calculate the hexagon cell representation for each cell
for a specified dimension reduction representation. I decide to use
nbins=40 which specifies that I divide my x range into 10
bins. Note that this might be a parameter that you want to play around
with depending on the number of cells/ nuclei in your dataset.
Generally, for more cells/nuclei, nbins should be
increased.
First I plot how many cells are in each hexagon cell. This should be
relatively even, otherwise change the nbins parameter in
the previous calculation.
Next I colour the hexagon cells by some meta information, such as the median total count in each hexagon cell.
Finally, I will visualize the gene expression of the CD1C gene in the hexagon cell representation.
gene_id <- "CD1C"
schex::plot_hexbin_feature(pbmc.sce,
type = "counts", feature = gene_id,
action = "mean", xlab = "UMAP1", ylab = "UMAP2",
title = paste0("Mean of ", gene_id)
)schex output as ggplot
objectsThe schex packages renders ordinary ggplot
objects and thus these can be treated and manipulated using the ggplot grammar.
For example the non-data components of the plots can be changed using
the function theme.
gene_id <- "CD1C"
gg <- schex::plot_hexbin_feature(pbmc.sce,
type = "counts", feature = gene_id,
action = "mean", xlab = "UMAP1", ylab = "UMAP2",
title = paste0("Mean of ", gene_id)
)
gg + theme_void()The fact that schex renders ggplot objects
can also be used to save these plots. Simply use ggsave in
order to save any created plot.
To find the details of the session for reproducibility, use this:
sessionInfo()
#> R version 4.5.0 Patched (2025-04-21 r88169)
#> Platform: aarch64-apple-darwin20
#> Running under: macOS Ventura 13.7.1
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
#>
#> locale:
#> [1] C/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> time zone: America/New_York
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats4 stats graphics grDevices utils datasets methods
#> [8] base
#>
#> other attached packages:
#> [1] Seurat_5.3.0 SeuratObject_5.1.0
#> [3] sp_2.2-0 dplyr_1.1.4
#> [5] schex_1.23.0 SingleCellExperiment_1.31.0
#> [7] SummarizedExperiment_1.39.0 Biobase_2.69.0
#> [9] GenomicRanges_1.61.0 GenomeInfoDb_1.45.0
#> [11] IRanges_2.43.0 S4Vectors_0.47.0
#> [13] BiocGenerics_0.55.0 generics_0.1.3
#> [15] MatrixGenerics_1.21.0 matrixStats_1.5.0
#> [17] ggplot2_3.5.2
#>
#> loaded via a namespace (and not attached):
#> [1] RColorBrewer_1.1-3 jsonlite_2.0.0 magrittr_2.0.3
#> [4] spatstat.utils_3.1-3 farver_2.1.2 rmarkdown_2.29
#> [7] vctrs_0.6.5 ROCR_1.0-11 spatstat.explore_3.4-2
#> [10] htmltools_0.5.8.1 S4Arrays_1.9.0 SparseArray_1.9.0
#> [13] sass_0.4.10 sctransform_0.4.1 parallelly_1.43.0
#> [16] KernSmooth_2.23-26 bslib_0.9.0 htmlwidgets_1.6.4
#> [19] ica_1.0-3 plyr_1.8.9 plotly_4.10.4
#> [22] zoo_1.8-14 cachem_1.1.0 igraph_2.1.4
#> [25] mime_0.13 lifecycle_1.0.4 pkgconfig_2.0.3
#> [28] Matrix_1.7-3 R6_2.6.1 fastmap_1.2.0
#> [31] GenomeInfoDbData_1.2.14 fitdistrplus_1.2-2 future_1.40.0
#> [34] shiny_1.10.0 digest_0.6.37 colorspace_2.1-1
#> [37] patchwork_1.3.0 tensor_1.5 RSpectra_0.16-2
#> [40] irlba_2.3.5.1 labeling_0.4.3 progressr_0.15.1
#> [43] spatstat.sparse_3.1-0 httr_1.4.7 polyclip_1.10-7
#> [46] abind_1.4-8 compiler_4.5.0 withr_3.0.2
#> [49] fastDummies_1.7.5 hexbin_1.28.5 ggforce_0.4.2
#> [52] MASS_7.3-65 concaveman_1.1.0 DelayedArray_0.35.1
#> [55] tools_4.5.0 lmtest_0.9-40 httpuv_1.6.16
#> [58] future.apply_1.11.3 goftest_1.2-3 glue_1.8.0
#> [61] nlme_3.1-168 promises_1.3.2 grid_4.5.0
#> [64] Rtsne_0.17 cluster_2.1.8.1 reshape2_1.4.4
#> [67] gtable_0.3.6 spatstat.data_3.1-6 tidyr_1.3.1
#> [70] data.table_1.17.0 XVector_0.49.0 spatstat.geom_3.3-6
#> [73] RcppAnnoy_0.0.22 ggrepel_0.9.6 RANN_2.6.2
#> [76] pillar_1.10.2 stringr_1.5.1 spam_2.11-1
#> [79] RcppHNSW_0.6.0 later_1.4.2 splines_4.5.0
#> [82] tweenr_2.0.3 lattice_0.22-7 deldir_2.0-4
#> [85] survival_3.8-3 tidyselect_1.2.1 miniUI_0.1.2
#> [88] pbapply_1.7-2 knitr_1.50 gridExtra_2.3
#> [91] scattermore_1.2 xfun_0.52 stringi_1.8.7
#> [94] UCSC.utils_1.5.0 lazyeval_0.2.2 yaml_2.3.10
#> [97] evaluate_1.0.3 codetools_0.2-20 entropy_1.3.2
#> [100] tibble_3.2.1 cli_3.6.5 uwot_0.2.3
#> [103] xtable_1.8-4 reticulate_1.42.0 jquerylib_0.1.4
#> [106] dichromat_2.0-0.1 Rcpp_1.0.14 spatstat.random_3.3-3
#> [109] globals_0.17.0 png_0.1-8 spatstat.univar_3.1-2
#> [112] parallel_4.5.0 dotCall64_1.2 listenv_0.9.1
#> [115] viridisLite_0.4.2 scales_1.4.0 ggridges_0.5.6
#> [118] purrr_1.0.4 crayon_1.5.3 rlang_1.1.6
#> [121] cowplot_1.1.3