Skip to contents

Performs a network assortativity test for each label, describing whether the spots of that label displays a clustered or dispersed spatial pattern.

Usage

RunLabelAssortativityTest(
  object,
  column_name,
  n_permutations = 100,
  nCores = parallel::detectCores() - 1,
  seed = 123,
  verbose = TRUE
)

Arguments

object

A Seurat object

column_name

Column name in metadata corresponding to label ID of the spots.

n_permutations

Integer specifying number of iterations the labels should be randomized [default: 100]. Recommended to increase the number of permutations to >=100 for more robust results. A lower number of permutations will result in high standard deviations and thus more unreliable output

nCores

Number of cores [default: parallel::detectCores() - 1]

seed

A seed to use for reproducibility [default: 123]

verbose

Print messages [default: TRUE]

Value

A tibble with scores for each label.

Details

This analysis is inspired by the Newman's Assortativity measure by looking at the average degree of spots belonging to the same class or label (specified with column_name). The hypothesis that we want to address is that spots of the same label will lie next to each other in an aggregated fashion, as compared to being randomly dispersed throughout the tissue. As the average degree within a label may change based on the total number of observations, we scale it towards the maximum average degree (k) possible in the network (for Visium, the theoretical max avg k is 6) and the minimum avg k you would expect to see if spots are randomly dispersed. With the n_permutations argument, you can specify the number of iterations for generating a mean of the minimum avg k for each label. The output of this function is a tibble table with entries for each label corresponding to the observed avg k (avg_k), the mean of the randomized avg k (min_avg_k_mean), the standard deviation of the randomized avg k (min_avg_k_sd), and the scaled avg k (avg_k_scaled), which has been scaled towards the network max avg k (k_max) and thus goes from 0 (completely randomly dispersed) to 1 (fully connected).

Author

Lovisa Franzén

Examples

# \donttest{
library(semla)

# Read data
se <- readRDS(system.file("extdata/mousebrain",
                          "se_mbrain",
                          package = "semla"))

# Generate clusters
se <- se |>
  NormalizeData() |>
  ScaleData() |>
  FindVariableFeatures() |>
  RunPCA() |>
  FindNeighbors(reduction = "pca", dims = 1:30) |>
  FindClusters()
#> Centering and scaling data matrix
#> PC_ 1 
#> Positive:  Nrgn, Olfm1, Cck, Nptxr, Rtn1, Snca, Nov, Tmsb4x, Lamp5, Egr1 
#> 	   Crym, Cpne6, Coro1a, Arc, Hpca, Sst, Nr4a1, Npy, Chgb, Neurod6 
#> 	   Snap25, Myh7, Uchl1, Eef1a2, Cort, Grp, Stmn2, Rprm, Spink8, Mfge8 
#> Negative:  Mbp, Plp1, Apod, Mobp, Ptgds, Mog, Mal, Mag, Cnp, Aldh1a1 
#> 	   Opalin, Tcf7l2, Ddc, Lhx1os, Slc6a3, Ret, Th, Slc18a2, Sncg, Drd2 
#> 	   Chrna6, Slc10a4, Spp1, En1, Dlk1, Calb2, Hbb-bs, Pvalb, Col1a2, Tnnt1 
#> PC_ 2 
#> Positive:  Myoc, Gfap, Col1a2, Fmod, Slc13a4, Hba-a1, Hbb-bt, Slc6a20a, Hba-a2, Hbb-bs 
#> 	   Acta2, Tagln, Mgp, Ogn, Vtn, H2-Aa, Lyz2, Cd74, Myl9, Dcn 
#> 	   Myh11, Ptgds, Cytl1, H2-Eb1, Hmgcs2, Clu, Mfge8, Emp1, Npy, Cnn1 
#> Negative:  Th, Uchl1, Slc18a2, En1, Slc10a4, Slc6a3, Chrna6, Stmn2, Ret, Snap25 
#> 	   Drd2, Dlk1, Ddc, Scg2, Sncg, Eef1a2, Rtn1, Chga, Pcp4, Calb2 
#> 	   Mobp, Mbp, Chgb, Fabp5, Plp1, Pvalb, Mog, Mal, Mag, Snca 
#> PC_ 3 
#> Positive:  Trbc2, Arc, Egr1, Myl4, Nr4a1, Mbp, Mobp, Pvalb, Plp1, Opalin 
#> 	   Mog, Mal, Cnp, Mag, Snap25, Lamp5, Ighm, Tcf7l2, Cplx3, Tgm3 
#> 	   Ighg2c, Pcp4, Hpca, Ly6d, Eef1a2, Tnnt1, Chga, Neurod6, Prph, Ctgf 
#> Negative:  Nnat, Slc18a2, Dlk1, Slc6a3, Slc10a4, En1, Th, Chrna6, Dcn, Sncg 
#> 	   Cpne7, Drd2, Ddc, Ret, Hpcal1, Ecel1, Cpne6, Col1a2, Trh, Calb2 
#> 	   Cd24a, Fmod, Mgp, Snca, Lypd1, Slc13a4, Fibcd1, Crym, Spink8, Slc6a20a 
#> PC_ 4 
#> Positive:  Nr4a1, Arc, Lamp5, Egr1, Myl4, Trbc2, Chrna6, Tagln, En1, Snap25 
#> 	   Th, Slc18a2, Acta2, Col1a2, Myh11, Fmod, Hba-a2, Slc10a4, Slc6a3, Slc13a4 
#> 	   Ret, Tgm3, Hbb-bt, Slc6a20a, Ighm, Hbb-bs, Hba-a1, Vtn, Mgp, Drd2 
#> Negative:  Spink8, Fibcd1, Tmsb4x, Nnat, Lefty1, Crym, Cpne7, Nos1, Dcn, Cpne6 
#> 	   Grp, Homer3, Htr3a, Tac1, Fabp5, C1ql2, Trh, Opalin, Mog, Plp1 
#> 	   Mag, Calb2, Ecel1, Gfap, Cnp, Tcf7l2, Lypd1, Vgll3, Hpcal1, Mal 
#> PC_ 5 
#> Positive:  Pcp4, Tcf7l2, Snap25, Uchl1, Eef1a2, Chga, Stmn2, Lhx1os, Calb2, Scg2 
#> 	   Fabp5, Bok, Prkcd, Pvalb, Cartpt, Chgb, Tnnt1, Gpx3, Slc20a1, Rtn1 
#> 	   C1ql2, Spp1, Hpcal1, Ptgds, Pitx2, Lypd1, Aldh1a1, Ecel1, Vtn, Nme7 
#> Negative:  En1, Chrna6, Th, Slc18a2, Slc10a4, Ddc, Lefty1, Arc, Slc6a3, Neurod6 
#> 	   Grp, Nov, Lamp5, Fibcd1, Nr4a1, Drd2, Spink8, Vip, Myl4, Ret 
#> 	   Egr1, Dlk1, Nrgn, Gfap, Trbc2, Tgm3, Myh7, Tac2, Sncg, Npy 
#> Computing nearest neighbor graph
#> Computing SNN
#> Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
#> 
#> Number of nodes: 2560
#> Number of edges: 107827
#> 
#> Running Louvain algorithm...
#> Maximum modularity in 10 random starts: 0.8228
#> Number of communities: 12
#> Elapsed time: 0 seconds

# Run Label Assortativity Analysis
res <- RunLabelAssortativityTest(object = se,
                                 column_name = "seurat_clusters",
                                 n_permutations = 100,
                                 nCores = 1)
#> 
#> ── Running Label Assortativity Test ──
#> 
#>  Generating neighborhood adjacency data from observed labels in column 'seurat_clusters'
#>  Observed label average degree calculations complete
#>  Generating neighborhood adjacency data from randomized labels
#>  Randomized label adjacency calculations complete from 100 iterations
#> ! The standard deviation of some of the permuted results is relatively high (>0.1) which may indicate unreliable results.
#> A possible solution could be to increase the number of permutations ('n_permutations').
#>  Scores calculated for each label and returned as output tibble

res |> arrange(desc(avg_k_scaled))
#> # A tibble: 12 × 6
#>    label avg_k_scaled avg_k min_avg_k_mean min_avg_k_sd k_max
#>    <fct>        <dbl> <dbl>          <dbl>        <dbl> <dbl>
#>  1 0            0.814  5.06           1.52       0.0610  5.88
#>  2 10           0.793  4.88           1.05       0.121   5.88
#>  3 7            0.764  4.75           1.10       0.0898  5.88
#>  4 4            0.739  4.68           1.30       0.0650  5.88
#>  5 11           0.724  4.54           1.02       0.100   5.88
#>  6 2            0.712  4.59           1.40       0.0641  5.88
#>  7 1            0.697  4.53           1.44       0.0651  5.88
#>  8 5            0.639  4.18           1.19       0.0624  5.88
#>  9 3            0.615  4.14           1.36       0.0669  5.88
#> 10 9            0.598  3.94           1.06       0.120   5.88
#> 11 6            0.361  2.86           1.16       0.0792  5.88
#> 12 8            0.180  1.95           1.09       0.0888  5.88
# }