Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions inst/pages/transformation.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,119 @@ than the minimum abundance value before transformation. Some tools, like
values. See [@sec-differential-abundance].
:::

## Rarefaction {#sec-rarefaction}

Another approach to control uneven sampling depths is to apply rarefaction with `rarefyAssay()`, which resamples the samples to an equal number of reads. This remains controversial, however, and strategies to mitigate the information loss in rarefaction have been proposed [@Schloss_2024a; @Schloss_2024b]. Moreover, this practice has been discouraged for the analysis of differentially abundant microorganisms [@McMurdie_and_Holmes_2014].

Rarefaction can be performed iteratively by using the `niter` parameter in `rarefyAssay()`. This creates multiple rarefied versions of the data, which can help account for the stochasticity introduced by random subsampling. The resulting rarefied assays can then be used for downstream analyses such as alpha and beta diversity calculations. For alpha and beta diversity, the same repeated subsampling can also be done directly within `addAlpha()` and `addMDS()` by setting `niter`.

### Using rarefaction with alpha diversity

When calculating alpha diversity indices, you can first create rarefied assays with `rarefyAssay()` and reuse them later. This is useful when you want to inspect or store the rarefied data itself:

```{r}
#| label: rarefaction-alpha
#| eval: true

# Load example data
library(mia)
data("Tengeler2020")
tse <- Tengeler2020

# Get minimum read depth for rarefaction
min_reads <- min(colSums(assay(tse, "counts")))

# Perform iterative rarefaction
tse <- rarefyAssay(
tse,
method = "subsample",
sample = min_reads,
niter = 100
)
```

If you only need alpha diversity, `addAlpha()` can do the iterative subsampling directly from the count assay. It stores the values in the object, while `getAlpha()` returns them separately:

```{r}
#| label: rarefaction-alpha-direct
#| eval: true

# Reload example data so this chunk is self-contained.
library(mia)
data("Tengeler2020")
tse <- Tengeler2020

# Calculate alpha diversity with iterative rarefaction
tse <- addAlpha(
tse,
assay.type = "counts",
index = "shannon",
niter = 100
)
Comment on lines +171 to +197

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addAlpha can be used independently of rarefyAssay.

Hence I am thinking that it might be more clear to show these as two separate operations that can both be feasible but each on their own right. Shall we split this chunk in two parts?

```

### Using rarefaction with beta diversity

Similarly, rarefaction can be applied before calculating beta diversity and performing ordination. If you want to store a rarefied assay first, `rarefyAssay()` still works as above. For ordination, `addMDS()` can also perform the repeated subsampling directly from the count assay:

```{r}
#| label: rarefaction-beta
#| eval: true

# Reload example data so this chunk is self-contained.
library(mia)
data("Tengeler2020")
tse <- Tengeler2020

# Perform MDS ordination with iterative rarefaction
tse <- addMDS(
tse,
assay.type = "counts",
method = "bray",
niter = 100
)
```

When you combine iterative rarefaction with a transformation, keep the input as counts and pass the transformation through `transf` instead of pre-transforming the assay. The same pattern can be used for different transformations by swapping the helper function, for example a relative-abundance or clr-style transformation.

```{r}
#| label: rarefaction-beta-transf
#| eval: true

# Reload example data so this chunk is self-contained.
library(mia)
library(vegan)
data("Tengeler2020")
tse <- Tengeler2020

# Define a custom transformation function.
clr <- function(x) {
vegan::decostand(x, method = "clr", pseudocount = 1)
}

# Apply the transformation after rarefaction and before the beta diversity calculation.
tse <- addMDS(
tse,
assay.type = "counts",
FUN = getDissimilarity,
method = "euclidean",
niter = 100,
sample = min(colSums(assay(tse, "counts"))),
transf = clr,
replace = TRUE,
name = "MDS_clr_rarefied"
)
```

### Function comparison

**`addAlpha()` vs `getAlpha()`**: Both functions calculate alpha diversity indices, but `addAlpha()` stores the results directly into the `colData` of the TreeSummarizedExperiment object, while `getAlpha()` returns the diversity values as a separate vector or matrix. Use `addAlpha()` when you want to keep all data together in one object, and `getAlpha()` when you need the diversity values for immediate use in other calculations.

Comment on lines +255 to +256

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to explain this earlier, where the rarified alpha diversity analysis is shown.

**`runMDS()` vs `addMDS()`**: The `runMDS()` function calculates multidimensional scaling coordinates and returns them as a separate matrix, whereas `addMDS()` calculates the MDS coordinates and stores them directly into the `reducedDim` slot of the TreeSummarizedExperiment object. Using `addMDS()` is generally preferred as it maintains all results within the same data object, making downstream analyses and visualization more straightforward.

Comment on lines +257 to +258

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also comment whether this is available for other ordination functions e.g. runPCA, runNMDS..?

The same add/get pattern is also used for other ordination workflows where available, for example `runNMDS()` / `addNMDS()` in the community similarity chapter.


## Transformations in practice

Below, we apply relative transformation to counts table.
Expand Down