Skip to contents

Asymptotic normal approximation

Let the vector ${\bf p}$ be the true fractions across DD categories. Consider CC total counts sampled from a Dirichlet-multinomial (DMN) distribution with overdispersion τ\tau, where τ=1\tau=1 reduces to the multinomial distribution. The centered log ratio (CLR) of the ithi^{th} estimated fraction in ${\bf \hat p}$ is

$$\begin{equation} \tag{1} \text{clr}_i({\bf \hat p}) = \log(\hat p_i) - \frac{1}{D}\sum_{j=1}^D \log(\hat p_j) \end{equation}$$ and we show that the sampling variance is

$$\begin{equation} \tag{2} \text{var}[\text{clr}_i({\bf \hat p})] = \frac{\tau}{C} \left[ \frac{1}{\hat p_i} - \frac{2}{ D \hat p_i} + \frac{1}{D^2}\sum_{j=1}^D \frac{1}{\hat p_j} \right]. \label{eqn2} \end{equation}$$

Simulations

The sampling variance is derived from asymototic theory, so we examine its behavior for finite total counts. Here we evaluate the empirical variance from 1,0001,000 draws from a Dirichlet-multinomial distribution while varying DD, τ\tau, CC. A pseudocount of 0.5 is added to the observed counts since the asymptotic theory is not defined for counts of zero.

Here we plot the standard deviation after CLR transform from the empirical DMN and the asymptotic normal approximation under a range of conditions. Results are shown for instances with at least 2 counts.

D=2 categories

D=15 categories

Interpretation

The asymptotic standard deviation shows good agreement with the empirical results even for small values of CC, when at least 2 counts are observed. In practice, it is often reasonable to assume a sufficient number of counts before a variable is included in an analysis. Importantly, with less than 2 counts the asymptotic theory gives a larger standard deviation than the emprical results (results not shown). Therefore, this approach is conservative and should not underestimate the true amount of variation. The asymptotic normal approximation is most accurate for large total counts CC, large proportions pp, and small overdispersion τ\tau.

Consideration of overdispersion

Based on Equation (2), the variance of the CLR-transformed proportions is a linear function of τ\tau. Importantly, downstream analysis of the CLR-transformed proportions with a precision-weighted linear (mixed) model or a variance stabilizing transform depends only on the relative variances. Since relative variances are invariant to the scale of τ\tau, for these applications the value of τ\tau can be set to 1 instead of being estimated from the data.

For other applications, crumblr can estimate τ\tau from the data by using crumblr(counts, tau=NULL). This calls dmn.mle() to estimate the parameters of the DMN distribution and is substantially faster than alternatives.

Session Info

## R version 4.4.1 (2024-06-14)
## Platform: aarch64-apple-darwin23.5.0
## Running under: macOS Sonoma 14.7.1
## 
## Matrix products: default
## BLAS:   /Users/gabrielhoffman/prog/R-4.4.1/lib/libRblas.dylib 
## LAPACK: /opt/homebrew/Cellar/r/4.4.2_2/lib/R/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/New_York
## tzcode source: internal
## 
## attached base packages:
## [1] parallel  stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] lubridate_1.9.4  forcats_1.0.0    stringr_1.5.1    dplyr_1.1.4      purrr_1.0.4     
##  [6] readr_2.1.5      tidyr_1.3.1      tibble_3.2.1     tidyverse_2.0.0  glue_1.8.0      
## [11] HMP_2.0.1        dirmult_0.1.3-5  crumblr_0.99.19  ggplot2_3.5.1    BiocStyle_2.34.0
## 
## loaded via a namespace (and not attached):
##   [1] jsonlite_1.8.9              magrittr_2.0.3              farver_2.1.2               
##   [4] nloptr_2.1.1                rmarkdown_2.29              fs_1.6.5                   
##   [7] zlibbioc_1.52.0             ragg_1.3.3                  vctrs_0.6.5                
##  [10] minqa_1.2.8                 ggtree_3.14.0               htmltools_0.5.8.1          
##  [13] S4Arrays_1.6.0              broom_1.0.7                 SparseArray_1.6.1          
##  [16] gridGraphics_0.5-1          variancePartition_1.36.3    sass_0.4.9                 
##  [19] KernSmooth_2.23-26          bslib_0.9.0                 htmlwidgets_1.6.4          
##  [22] desc_1.4.3                  pbkrtest_0.5.3              plyr_1.8.9                 
##  [25] cachem_1.1.0                lifecycle_1.0.4             iterators_1.0.14           
##  [28] pkgconfig_2.0.3             Matrix_1.7-2                R6_2.6.1                   
##  [31] fastmap_1.2.0               GenomeInfoDbData_1.2.13     rbibutils_2.3              
##  [34] MatrixGenerics_1.18.1       digest_0.6.37               numDeriv_2016.8-1.1        
##  [37] aplot_0.2.4                 colorspace_2.1-1            patchwork_1.3.0            
##  [40] S4Vectors_0.44.0            textshaping_1.0.0           GenomicRanges_1.58.0       
##  [43] vegan_2.6-10                labeling_0.4.3              RcppZiggurat_0.1.6         
##  [46] timechange_0.3.0            mgcv_1.9-1                  httr_1.4.7                 
##  [49] abind_1.4-8                 compiler_4.4.1              aod_1.3.3                  
##  [52] withr_3.0.2                 backports_1.5.0             BiocParallel_1.40.0        
##  [55] viridis_0.6.5               gplots_3.2.0                MASS_7.3-64                
##  [58] DelayedArray_0.32.0         corpcor_1.6.10              permute_0.9-7              
##  [61] gtools_3.9.5                caTools_1.18.3              tools_4.4.1                
##  [64] ape_5.8-1                   remaCor_0.0.18              nlme_3.1-167               
##  [67] grid_4.4.1                  cluster_2.1.8               reshape2_1.4.4             
##  [70] generics_0.1.3              gtable_0.3.6                tzdb_0.4.0                 
##  [73] hms_1.1.3                   XVector_0.46.0              BiocGenerics_0.52.0        
##  [76] foreach_1.5.2               pillar_1.10.1               yulab.utils_0.2.0          
##  [79] limma_3.62.2                splines_4.4.1               treeio_1.30.0              
##  [82] lattice_0.22-6              tidyselect_1.2.1            SingleCellExperiment_1.28.1
##  [85] knitr_1.49                  reformulas_0.4.0            gridExtra_2.3              
##  [88] bookdown_0.42               IRanges_2.40.1              SummarizedExperiment_1.36.0
##  [91] RhpcBLASctl_0.23-42         stats4_4.4.1                xfun_0.50                  
##  [94] Biobase_2.66.0              statmod_1.5.0               matrixStats_1.5.0          
##  [97] stringi_1.8.4               UCSC.utils_1.2.0            lazyeval_0.2.2             
## [100] ggfun_0.1.8                 yaml_2.3.10                 boot_1.3-31                
## [103] evaluate_1.0.3              codetools_0.2-20            rpart.plot_3.1.2           
## [106] BiocManager_1.30.25         ggplotify_0.1.2             cli_3.6.4                  
## [109] rpart_4.1.24                RcppParallel_5.1.10         systemfonts_1.2.1          
## [112] Rdpack_2.6.2                munsell_0.5.1               jquerylib_0.1.4            
## [115] Rcpp_1.0.14                 GenomeInfoDb_1.42.3         EnvStats_3.0.0             
## [118] Rfast_2.1.4                 pkgdown_2.1.1               bitops_1.0-9               
## [121] lme4_1.1-36                 viridisLite_0.4.2           mvtnorm_1.3-3              
## [124] tidytree_0.4.6              lmerTest_3.1-3              scales_1.3.0               
## [127] crayon_1.5.3                fANCOVA_0.6-1               rlang_1.1.5