alphapepttools.tl.diff_exp_ebayes

alphapepttools.tl.diff_exp_ebayes#

alphapepttools.tl.diff_exp_ebayes(adata, between_column, comparison, categorical_covariate_column=None, a_min_required=None, b_min_required=None)#

Run the Limma eBayes moderated t-test for differential expression.

Handles missing values without imputation, resolves several contrasts against a shared reference in one fit, and optionally adjusts for a covariate.

The two conditions in each comparison are referred to positionally as A (comparison[0]) and B (comparison[1]); the test is symmetric, so no condition is assumed to be a treatment or a control. Missingness handling inside this function is limited to gating the reported fold changes: per contrast, a feature’s fold change and p-value are suppressed (set to NaN, before FDR correction) unless both conditions have at least the required number of observed values (a_min_required for A and b_min_required for B). All features are still fit and contribute to the eBayes variance prior. Pre-fit completeness filtering, if wanted, is the caller’s responsibility and should be done upstream (e.g. alphapepttools.pp.filter_data_completeness).

Parameters:
  • adata (ad.AnnData) – AnnData object with expression data in .X and sample metadata in .obs.

  • between_column (str) – Column name in adata.obs containing the contrast levels.

  • comparison (tuple[str | list[str], str]) – Tuple specifying the pair of conditions to compare, ordered as (A, B): the first element is the A condition(s), the second is the single B reference each A is compared against, e.g. (“A”, “B”). Fold changes are reported as A - B. Multiple A conditions can be specified as a list in the first element: ([“A1”, “A2”], “B”). If the first element is set to “_ALL_”, all conditions except B are compared against it: (“_ALL_”, “B”).

  • categorical_covariate_column (str | None, optional) – Column name in adata.obs containing a categorical covariate to adjust for, by default None. Its levels are added to the design matrix as k-1 indicator columns, so the column must be categorical (numeric labels are fine, as long as they encode a small number of discrete groups). A continuous covariate would produce roughly one column per sample and leave the model with no residual degrees of freedom.

  • a_min_required (int | None, optional) – Minimum number of observed values required in the A condition (comparison[0]) of each contrast. Per contrast, features with fewer observed values in A have their fold change suppressed (set to NaN) before FDR correction. If None, the A gate is disabled. By default None.

  • b_min_required (int | None, optional) – Minimum number of observed values required in the B condition (comparison[1]). Per contrast, features with fewer observed values in B have their fold change suppressed (set to NaN) before FDR correction. If None, the B gate is disabled. By default None.

Return type:

DataFrame

Returns:

pd.DataFrame The standardized Limma eBayes results for every contrast, stacked into a single frame indexed by feature, carrying the shared tl_defaults.DIFF_EXP_COLS columns followed by this method’s own stat column (the moderated t-statistic). Fold changes are reported as A - B (i.e. comparison[0] - comparison[1]), and the condition_pair column names each contrast “A_VS_B”; select a single contrast by filtering on it.

Raises:
  • ImportError – If inmoose is not installed.

  • KeyError – If between_column is not in adata.obs, or any condition in comparison is not a level of it.

Examples

Compare two conditions:

de_results = at.tl.diff_exp_ebayes(
    adata=adata_protein,
    between_column="treatment",
    comparison=("treated", "control"),
)

significant = de_results[de_results["fdr"] < 0.05]

Adjust for a confounder that is unevenly distributed across the conditions, and require at least three observed values on each side before a fold change is reported:

de_results = at.tl.diff_exp_ebayes(
    adata=adata_protein,
    between_column="treatment",
    comparison=("treated", "control"),
    categorical_covariate_column="batch",
    a_min_required=3,
    b_min_required=3,
)

Compare several conditions against one shared reference in a single fit, then pick out one contrast. Passing "_ALL_" as the first element compares every other condition against the reference:

de_results = at.tl.diff_exp_ebayes(
    adata=adata_protein,
    between_column="timepoint",
    comparison=(["6h", "24h"], "0h"),  # or ("_ALL_", "0h")
)

late = de_results[de_results["condition_pair"] == "24h_VS_0h"]

See also

alphapepttools.tl.diff_exp_ttest

Plain Welch/Student t-test, without variance moderation.

alphapepttools.pp.filter_data_completeness

Upstream completeness filtering.