6 Vertical Integration
In horizontal integration, we have many datasets, all with the same features. They only differ because they were gathered at different times. In contrast, for vertical integration, we instead have many datasets all with the same samples. They differ because they measure different aspects of those samples. Our goal in this situation is not to remove differences across datasets, like it was in horizontal integration, but instead to clarify the relationships across sources.
One important question that often arises in vertical integration is – are the data even alignable? That is, in our effort to look for relationships across datasets, we might accidentally miss out on interesting variation that exists within the individual assays. If the technologies are measuring very different things, we might be better off simply analyzing the data separately. To help us gauge which setting we might be in, we can simulate data where we know that we shouldn’t align the sources. If our integration methods are giving similar outputs as they give on this simulated data, then we should be more cautious.
There are a few ways in which a dataset might not be ``alignable.’’ The most general reason is that there may be no latent sources of variation in common between the sources. A simpler reason is that something that influenced one assay substantially (e.g., disease state) might not influence the other by much. Let’s see how an integration method might work in this setting.
6.1 ICU Dataset
We’ll work with the ICU sepsis dataset previously studied by Haak et al. (2021) and documented within a vignette for the MOFA package. The three datasets here are 16S bacterial, ITS fungal, and Virome assays, all applied to different healthy and sepsis patient populations. Moreover, some participants were on a course of antibiotics while others were not. The question is how either sepsis, antibiotics, or their interaction affects the microbiome viewed through these three assays. The data are printed below, they have already been filtered and CLR transformed following the MOFA vignette.
data(icu)
icu
## $Bacteria
## # A SummarizedExperiment-tibble abstraction: 10,260 × 19
## # Features=180 | Samples=57 | Assays=clr
## .feature .sample clr Age Sexs Diagnosis Category Penicillins Cephalosporins Carbapenems Macrolides Aminoglycosides Quinolones Co_trimoxazole Metronidazole Vancomycin Acetate Propionate
## <chr> <chr> <dbl> <int> <chr> <chr> <chr> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <dbl> <dbl>
## 1 Acidamino… TKI_F1 -0.717 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 2 Actinomyc… TKI_F1 -0.717 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 3 Adlercreu… TKI_F1 -0.717 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 4 Agathobac… TKI_F1 -0.717 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 5 Akkermans… TKI_F1 1.68 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 6 Alistipes TKI_F1 10.9 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 7 Allisonel… TKI_F1 -0.717 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 8 Alloprevo… TKI_F1 -0.717 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 9 Anaerofil… TKI_F1 -0.717 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 10 Anaerofus… TKI_F1 -0.717 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## # ℹ 40 more rows
## # ℹ 1 more variable: Butyrate <dbl>
##
## $Fungi
## # A SummarizedExperiment-tibble abstraction: 1,026 × 19
## # Features=18 | Samples=57 | Assays=clr
## .feature .sample clr Age Sexs Diagnosis Category Penicillins Cephalosporins Carbapenems Macrolides Aminoglycosides Quinolones Co_trimoxazole Metronidazole Vancomycin Acetate Propionate
## <chr> <chr> <dbl> <int> <chr> <chr> <chr> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <dbl> <dbl>
## 1 Agaricus TKI_F1 -1.21 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 2 Aspergill… TKI_F1 6.63 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 3 Aureobasi… TKI_F1 -4.25 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 4 Candida TKI_F1 8.16 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 5 Cladospor… TKI_F1 1.05 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 6 Debaryomy… TKI_F1 -0.540 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 7 Dipodascus TKI_F1 -1.86 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 8 Filobasid… TKI_F1 -1.21 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 9 Issatchen… TKI_F1 0.141 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 10 Malassezia TKI_F1 0.764 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## # ℹ 350 more rows
## # ℹ 1 more variable: Butyrate <dbl>
##
## $Viruses
## # A SummarizedExperiment-tibble abstraction: 2,394 × 19
## # Features=42 | Samples=57 | Assays=clr
## .feature .sample clr Age Sexs Diagnosis Category Penicillins Cephalosporins Carbapenems Macrolides Aminoglycosides Quinolones Co_trimoxazole Metronidazole Vancomycin Acetate Propionate
## <chr> <chr> <dbl> <int> <chr> <chr> <chr> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <dbl> <dbl>
## 1 Acidovora… TKI_F1 -0.602 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 2 Acinetoba… TKI_F1 -0.602 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 3 Aeromonas… TKI_F1 -0.602 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 4 Anellovir… TKI_F1 -0.602 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 5 Arthrobac… TKI_F1 -0.602 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 6 Bacillus … TKI_F1 -0.602 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 7 Bacteroid… TKI_F1 -0.602 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 8 Bacteroid… TKI_F1 -0.602 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 9 Brochothr… TKI_F1 -0.602 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## 10 Burkholde… TKI_F1 -0.602 89 Fema… Sepsis, … Sepsis FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE 6.44 2.40
## # ℹ 32 more rows
## # ℹ 1 more variable: Butyrate <dbl>
We can simultaneously analyze these data sources using block sPLS-DA. This is
the multi-assay version of the analysis that we saw in the previous session.
exper_splsda
is a very light wrapper of a mixOmics function call, which you
can read
here.
The output plot below shows that each assay differs across groups, and this is
quantitatively summarized by the high estimated weights between each category
and the estimated PLS directions.
fit <- exper_splsda(icu)
plotIndiv(fit)
fit$weights
## comp1 comp2
## Bacteria 0.8580402 0.8191458
## Fungi 0.6513668 0.4845247
## Viruses 0.6118091 0.8047067
6.2 Interlude: Using map
In the examples below, we’ll find it helpful to use the function map
in the
purrr package. This function gives a one-line replacement for simple for-loops;
it is analogous to list comprehensions in python. It can be useful many places
besides the topic of this tutorial. For example, if we want to convert the
vector c(1, 2, 3)
into c(1, 4, 9)
, we can use this map:
map(1:3, ~ .^2)
## [[1]]
## [1] 1
##
## [[2]]
## [1] 4
##
## [[3]]
## [1] 9
The ~
notation is shorthand for defining a function, and the .
represents
the current vector element. More generally, we can apply map to lists. This
line will update the list so that 1 is added to each element.
## $a
## [1] 2
##
## $b
## [1] 3
##
## $c
## [1] 4
Exercise: To test your understanding, can you write a map that computes the
*mean for each
vector in the list x
below? What about the mean of the 10 smallest elements?
map(x, mean)
## $a
## [1] 0.1177328
##
## $b
## [1] 1.128995
## $a
## [1] -1.920247
##
## $b
## [1] -0.8639795
6.3 Simulation Question
How would the output have looked if 16S community composition had not been related to disease or antibiotics groups? Since integrative analysis prioritizes similarities across sources, we expect this to mask some of the real differences in the fungal and virus data as well. We can use simulation to gauge the extent of this masking.
Our first step is to train a simulator. We’re just learning four different
setes of parameters for each of the four observed groups. This is not as nuanced
as learning separate effects for sepsis and antibiotics, but it will be enough
for illustration. We have used map
to estimate a simulator for each assay in
the icu
list.
simulator <- map(
icu,
~ setup_simulator(., ~Category, ~ GaussianLSS()) |>
estimate(nu = 0.05)
)
So far, we haven’t tried removing any relationships present in the 16S assay, and indeed our integrative analysis output on the simulated data looks comparable to that from the original study.
icu_sim <- join_copula(simulator, copula_adaptive()) |>
sample() |>
split_assays()
fit_sim <- exper_splsda(icu_sim)
plotIndiv(fit_sim)
fit$weights
## comp1 comp2
## Bacteria 0.8580402 0.8191458
## Fungi 0.6513668 0.4845247
## Viruses 0.6118091 0.8047067
Exercise: Modify the simulator above so that the 16S group no longer depends on disease cateogry. This will allow us to study how the integrative analysis output changes when the data are not alignable.
null_simulator <- simulator
# fill this in
# null_simulator[[1]] <- ???
Solution: We need to define a new link that no longer depends on Category
. One solution
is to modify the existing simulator in place using mutate
.
null_simulator[[1]] <- simulator[[1]] |>
mutate(1:180, link = ~1) |>
estimate(nu = 0.05)
Since we are modifying all taxa, a simpler solution is to just define a new simulator from scratch.
null_simulator[[1]] <- setup_simulator(icu[[1]], ~1, ~ GaussianLSS()) |>
estimate(nu = 0.05)
6.4 Simulation Results
We can rerun the integrative analysis using the modified simulator. Somewhat surprisingly, the disease association in the bacteria group hasn’t been erased. This is an artifact of the integration. The other assays have associations with disease group, and since the method encourages outputs across tables to be consistent with one another, we have artificially introduced some structure into the bacteria visualization (even if it is quite weak.) Nonetheless, we still observe a large dropoff in weight for the bacterial table. Further, there seems to be a minor deterioration in the group separations for the fungal and virus communities, and the component weights are higher when we work with only the fungal and virus assays. Altogether, this suggests that we may want to check table-level associations with the response variable, especially if any of the integration outputs are ambiguous. In this case, we might be able to increase power by focusing only on class-associated assays. Nonetheless, the block sPLS-DA also seems relatively robust – considering the dramatic change in the microbiome table, the output for the remaining tables still surfaces interesting relationships.
icu_sim <- join_copula(null_simulator, copula_adaptive()) |>
sample() |>
split_assays()
fit_null <- exper_splsda(icu_sim)
plotIndiv(fit)
fit_null$weights
## comp1 comp2
## Bacteria 0.6658170 0.6571177
## Fungi 0.7479665 0.6797712
## Viruses 0.7015960 0.7929047
6.5 Alignability
How do the canonical correlations compare between the real data and a reference null? First, we can compute the CCA canonical correlations using the real Bacteria and Virus data.
merged <- simulator[c(1, 3)] |>
join_copula(copula_adaptive(thr = 0.01))
xy <- sample(merged) |>
assay() |>
t()
ix <- map(icu, rownames)
cca_result <- rcc(xy[, ix[[1]]], xy[, ix[[3]]], method = "shrinkage")
Next, we define a reference null and compute canonical correlations on ten replicates from this null. To define the reference null, we zero out any correlations across tables. We then draw 100 samples from the resulting distribution and compute canonical correlations for each.
rho_null <- copula_parameters(merged)
dimnames(rho_null) <- list(colnames(xy), colnames(xy))
rho_null[ix[[1]], ix[[3]]] <- 0
rho_null[ix[[3]], ix[[1]]] <- 0
null_cancor <- merged |>
mutate_correlation(rho_null)
B <- 100
cancors <- list()
for (b in seq_len(B)) {
xy_null <- sample(null_cancor) |>
assay() |>
t()
cancors[[glue("sim_{b}")]] <- rcc(xy_null[, ix[[1]]], xy_null[, ix[[3]]], method = "shrinkage")$cor
}
To help with later visualization, we combine both the real and reference canonical correlations into a tidy data.frame. These are visualized in a hidden chunk below – if you want to see the source code, you can review it here.
cancors[["true"]] <- cca_result$cor
contrast_data <- bind_rows(cancors, .id = "rep") |>
pivot_longer(-rep, names_to = "loading") |>
mutate(
source = grepl("true", rep),
loading = as.integer(loading)
)
head(contrast_data)
## # A tibble: 6 × 4
## rep loading value source
## <chr> <int> <dbl> <lgl>
## 1 sim_1 1 0.913 FALSE
## 2 sim_1 2 0.880 FALSE
## 3 sim_1 3 0.848 FALSE
## 4 sim_1 4 0.826 FALSE
## 5 sim_1 5 0.815 FALSE
## 6 sim_1 6 0.797 FALSE
## R version 4.4.1 Patched (2024-08-21 r87049)
## Platform: aarch64-apple-darwin20
## Running under: macOS Sonoma 14.5
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.0
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: America/Chicago
## tzcode source: internal
##
## attached base packages:
## [1] splines parallel stats4 stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] lubridate_1.9.3 readr_2.1.5 tidyverse_2.0.0 doRNG_1.8.6 rngtools_1.5.2
## [6] foreach_1.5.2 ggpubr_0.6.0 ggrepel_0.9.6 edgeR_4.3.16 limma_3.61.10
## [11] ANCOMBC_2.7.0 stringr_1.5.1 ks_1.14.3 tidySummarizedExperiment_1.15.1 ttservice_0.4.1
## [16] SimBench_0.99.1 wesanderson_0.3.7 mia_1.13.36 MultiAssayExperiment_1.31.5 TreeSummarizedExperiment_2.13.0
## [21] Biostrings_2.73.1 XVector_0.45.0 SingleCellExperiment_1.27.2 gamlss_5.4-22 nlme_3.1-166
## [26] gamlss.dist_6.1-1 gamlss.data_6.0-6 scDesigner_0.0.0.9000 purrr_1.0.2 MIGsim_0.0.0.9000
## [31] tidyr_1.3.1 tibble_3.2.1 scico_1.5.0 pwr_1.3-0 patchwork_1.3.0
## [36] mutoss_0.1-13 mvtnorm_1.3-1 mixOmics_6.29.0 lattice_0.22-6 MASS_7.3-61
## [41] glue_1.8.0 ggplot2_3.5.1 ggdist_3.3.2 gamboostLSS_2.0-7 mboost_2.9-11
## [46] stabs_0.6-4 forcats_1.0.0 dplyr_1.1.4 SummarizedExperiment_1.35.1 Biobase_2.65.1
## [51] GenomicRanges_1.57.1 GenomeInfoDb_1.41.1 IRanges_2.39.2 S4Vectors_0.43.2 BiocGenerics_0.51.1
## [56] MatrixGenerics_1.17.0 matrixStats_1.4.1 SpiecEasi_1.1.3 CovTools_0.5.4
##
## loaded via a namespace (and not attached):
## [1] igraph_2.0.3 ica_1.0-3 plotly_4.10.4 Formula_1.2-5 scater_1.33.4 BiocBaseUtils_1.7.3
## [7] zlibbioc_1.51.1 tidyselect_1.2.1 bit_4.5.0 doParallel_1.0.17 pspline_1.0-20 blob_1.2.4
## [13] S4Arrays_1.5.8 png_0.1-8 plotrix_3.8-4 cli_3.6.3 CVXR_1.0-14 pulsar_0.3.11
## [19] arrayhelpers_1.1-0 multtest_2.61.0 goftest_1.2-3 textshaping_0.4.0 bluster_1.15.1 BiocNeighbors_1.99.1
## [25] uwot_0.2.2 mime_0.12 evaluate_1.0.0 tidytree_0.4.6 leiden_0.4.3.1 stringi_1.8.4
## [31] backports_1.5.0 XML_3.99-0.17 lmerTest_3.1-3 Exact_3.3 gsl_2.1-8 httpuv_1.6.15
## [37] AnnotationDbi_1.67.0 magrittr_2.0.3 mclust_6.1.1 ADGofTest_0.3 pcaPP_2.0-5 rootSolve_1.8.2.4
## [43] sctransform_0.4.1 lpSolve_5.6.21 ggbeeswarm_0.7.2 DBI_1.2.3 genefilter_1.87.0 jquerylib_0.1.4
## [49] withr_3.0.1 corpcor_1.6.10 systemfonts_1.1.0 class_7.3-22 lmtest_0.9-40 sva_3.53.0
## [55] compositions_2.0-8 htmlwidgets_1.6.4 fs_1.6.4 labeling_0.4.3 SparseArray_1.5.38 DEoptimR_1.1-3
## [61] cellranger_1.1.0 DESeq2_1.45.3 tidybayes_3.0.7 extrafont_0.19 annotate_1.83.0 lmom_3.0
## [67] flare_1.7.0.1 reticulate_1.39.0 minpack.lm_1.2-4 geigen_2.3 zoo_1.8-12 knitr_1.48
## [73] nnls_1.5 UCSC.utils_1.1.0 svUnit_1.0.6 SHT_0.1.8 timechange_0.3.0 decontam_1.25.0
## [79] fansi_1.0.6 grid_4.4.1 rhdf5_2.49.0 data.table_1.16.0 ruv_0.9.7.1 vegan_2.6-8
## [85] RSpectra_0.16-2 irlba_2.3.5.1 extrafontdb_1.0 DescTools_0.99.56 ellipsis_0.3.2 fastDummies_1.7.4
## [91] ade4_1.7-22 lazyeval_0.2.2 yaml_2.3.10 survival_3.7-0 scattermore_1.2 crayon_1.5.3
## [97] mediation_4.5.0 tensorA_0.36.2.1 phyloseq_1.49.0 RcppAnnoy_0.0.22 RColorBrewer_1.1-3 progressr_0.14.0
## [103] later_1.3.2 ggridges_0.5.6 codetools_0.2-20 base64enc_0.1-3 Seurat_5.1.0 KEGGREST_1.45.1
## [109] Rtsne_0.17 shape_1.4.6.1 randtoolbox_2.0.4 foreign_0.8-87 pkgconfig_2.0.3 xml2_1.3.6
## [115] spatstat.univar_3.0-1 downlit_0.4.4 scatterplot3d_0.3-44 spatstat.sparse_3.1-0 ape_5.8 viridisLite_0.4.2
## [121] xtable_1.8-4 highr_0.11 car_3.1-2 fastcluster_1.2.6 plyr_1.8.9 httr_1.4.7
## [127] rbibutils_2.2.16 tools_4.4.1 globals_0.16.3 SeuratObject_5.0.2 kde1d_1.0.7 beeswarm_0.4.0
## [133] htmlTable_2.4.3 broom_1.0.6 checkmate_2.3.2 rgl_1.3.1 assertthat_0.2.1 lme4_1.1-35.5
## [139] rngWELL_0.10-9 digest_0.6.37 bayesm_3.1-6 permute_0.9-7 numDeriv_2016.8-1.1 bookdown_0.40
## [145] Matrix_1.7-0 tzdb_0.4.0 farver_2.1.2 reshape2_1.4.4 yulab.utils_0.1.7 viridis_0.6.5
## [151] DirichletMultinomial_1.47.0 rpart_4.1.23 cachem_1.1.0 polyclip_1.10-7 WGCNA_1.73 Hmisc_5.1-3
## [157] generics_0.1.3 dynamicTreeCut_1.63-1 parallelly_1.38.0 biomformat_1.33.0 statmod_1.5.0 impute_1.79.0
## [163] huge_1.3.5 ragg_1.3.3 RcppHNSW_0.6.0 ScaledMatrix_1.13.0 carData_3.0-5 minqa_1.2.8
## [169] pbapply_1.7-2 glmnet_4.1-8 spam_2.10-0 utf8_1.2.4 gtools_3.9.5 shapes_1.2.7
## [175] readxl_1.4.3 preprocessCore_1.67.0 inum_1.0-5 ggsignif_0.6.4 energy_1.7-12 gridExtra_2.3
## [181] shiny_1.9.1 GenomeInfoDbData_1.2.12 rhdf5filters_1.17.0 memoise_2.0.1 rmarkdown_2.28 scales_1.3.0
## [187] gld_2.6.6 stabledist_0.7-2 partykit_1.2-22 svglite_2.1.3 future_1.34.0 RANN_2.6.2
## [193] spatstat.data_3.1-2 rstudioapi_0.16.0 cluster_2.1.6 spatstat.utils_3.1-0 hms_1.1.3 fitdistrplus_1.2-1
## [199] munsell_0.5.1 cowplot_1.1.3 colorspace_2.1-1 ellipse_0.5.0 rlang_1.1.4 quadprog_1.5-8
## [205] copula_1.1-4 DelayedMatrixStats_1.27.3 sparseMatrixStats_1.17.2 dotCall64_1.1-1 scuttle_1.15.4 mgcv_1.9-1
## [211] xfun_0.47 coda_0.19-4.1 e1071_1.7-16 TH.data_1.1-2 posterior_1.6.0 iterators_1.0.14
## [217] rARPACK_0.11-0 abind_1.4-8 libcoin_1.0-10 treeio_1.29.1 gmp_0.7-5 Rhdf5lib_1.27.0
## [223] DECIPHER_3.1.4 Rdpack_2.6.1 promises_1.3.0 RSQLite_2.3.7 sandwich_3.1-1 proxy_0.4-27
## [229] DelayedArray_0.31.11 Rmpfr_0.9-5 GO.db_3.20.0 compiler_4.4.1 prettyunits_1.2.0 boot_1.3-31
## [235] distributional_0.5.0 beachmat_2.21.6 rbiom_1.0.3 listenv_0.9.1 Rcpp_1.0.13 Rttf2pt1_1.3.12
## [241] BiocSingular_1.21.4 tensor_1.5 progress_1.2.3 BiocParallel_1.39.0 insight_0.20.5 spatstat.random_3.3-2
## [247] R6_2.5.1 fastmap_1.2.0 multcomp_1.4-26 rstatix_0.7.2 vipor_0.4.7 ROCR_1.0-11
## [253] rsvd_1.0.5 nnet_7.3-19 gtable_0.3.5 KernSmooth_2.23-24 miniUI_0.1.1.1 deldir_2.0-4
## [259] htmltools_0.5.8.1 ggthemes_5.1.0 RcppParallel_5.1.9 bit64_4.5.2 spatstat.explore_3.3-2 lifecycle_1.0.4
## [265] nloptr_2.1.1 sass_0.4.9 vctrs_0.6.5 robustbase_0.99-4 VGAM_1.1-12 slam_0.1-53
## [271] spatstat.geom_3.3-3 sp_2.1-4 future.apply_1.11.2 pracma_2.4.4 rvinecopulib_0.6.3.1.1 bslib_0.8.0
## [277] pillar_1.9.0 locfit_1.5-9.10 jsonlite_1.8.9 expm_1.0-0