Skip to contents

Flags samples within each stratum; nothing is removed. The rule is the one of the Python package's tage.pp.flag_outliers, and both give the same numbers.

Usage

flag_outliers(
  eset,
  split_by = NULL,
  method = c("distance", "pca_iqr"),
  threshold = 5,
  iqr_factor = 1.5,
  min_cpm = 10,
  min_samples = 6
)

Arguments

eset

ExpressionSet of raw counts (bulk or pseudobulk).

split_by

Column of the phenoData defining the strata (tissue, dataset, cell type) that are scored separately, as in tAge_preprocessing. NULL: one stratum.

method

"distance" or "pca_iqr".

threshold

Robust z-score above which "distance" flags a sample. Default 5.

iqr_factor

Interquartile ranges beyond the quartiles for "pca_iqr". Default 1.5.

min_cpm

Genes with a lower mean CPM in the stratum are left out. Default 10.

min_samples

Strata with fewer samples are not scored (a warning says which). Default 6.

Value

The ExpressionSet with phenoData columns tage_outlier (logical) and, for "distance", tage_outlier_distance and tage_outlier_z; for "pca_iqr", tage_outlier_pc1 and tage_outlier_pc2. Samples of unscored strata get FALSE and NA.

Details

method = "distance" (default) scores every sample by 1 - r, the Pearson correlation of its log2(CPM + 1) profile with the median profile of its stratum, and flags it when the robust z-score of that distance (median and MAD within the stratum) exceeds threshold. It is the paper's "correlation with the median profile of the tissue" rule with a threshold relative to the stratum instead of a fixed rho < 0.5, which passes even a sample from another tissue. Only samples further from the median than the rest are flagged.

method = "pca_iqr" is the paper's rule: PC1 or PC2 more than iqr_factor interquartile ranges beyond the quartiles. The paper applied it to hundreds of samples; with a dozen, the first components pick out the noisiest sample and 1.5 IQR flags a normal sample in most strata.

Both work on log2(CPM + 1) of the genes with a mean CPM of at least min_cpm in the stratum. Depth only moves a sample's log profile by a constant, which the correlation ignores, but low-count genes add noise that grows as depth falls, and PCA on unnormalised counts mostly finds depth.

Remove the flagged samples explicitly, after looking at them: eset <- eset[, !eset$tage_outlier].

Examples

eset <- make_ExpressionSet(load_example_expression_data(), load_example_metadata(),
                           verbose = FALSE)
eset <- flag_outliers(eset, split_by = "Tissue")
Biobase::pData(eset)[eset$tage_outlier, c("Tissue", "tage_outlier_z")]
#>                  Tissue tage_outlier_z
#> RNA_93M Skeletal muscle       9.443985
#> RNA_99M Skeletal muscle       7.983690
eset <- eset[, !eset$tage_outlier]