.normalize_median
- proteopy.pp.normalize_median(adata, *, log_space=True, target='median', fill_na=None, zero_to_na=False, group_by=None, key_added='normalization_factors', inplace=True, force=False, verbose=False)[source]
Median normalization of intensities.
Each sample is rescaled so that its median intensity matches a common target. Let \(m_s\) be the median over the finite (non-NaN) features of sample \(s\); NaNs are ignored when computing it.
In log space (
log_space=True) the rescaling is additive; in linear space (log_space=False) it is multiplicative:\[X'_{s,i} = X_{s,i} + (t - m_s) \qquad X'_{s,i} = X_{s,i} \cdot \frac{t}{m_s}\]The target \(t\) is derived from the per-sample medians (within each group when
group_byis set):\[t = \operatorname{median}_s(m_s) \qquad t = \max_s(m_s)\]for
target='median'andtarget='max'respectively. Thezero_to_naandfill_natransforms (mutually exclusive) are applied to.Xbefore normalization and persist in the output. A sample of only NaNs yields \(m_s = \mathrm{NaN}\) and thus a NaN factor; this is not an error and is surfaced throughverbose.- Parameters:
adata (AnnData) – Input AnnData in proteodata format.
log_space (bool) – Whether the input intensities are log-transformed. Mismatches with automatic detection raise unless
force=True. Defaults toTrue.target ({'max', 'median'}) – How to compute the scaling target from the per-sample medians.
'max'uses the maximum sample median,'median'the median of sample medians. Defaults to'median'.fill_na (float, optional) – Replace non-finite entries in
.Xwith this value before normalization.zero_to_na (bool, default False) – Treat zeros in
.Xas missing (NaN) before normalization (replaces zeros withnp.nan).group_by (str, optional) – Column in
adata.obsdefining sample groups; when set, normalization is performed independently within each group (e.g. batch, condition, or any other sample grouping).key_added (str, default 'normalization_factors') – Key of the
adata.unsslot in which the per-sample factors DataFrame is stored.inplace (bool, default True) – Modify
adatain place. If False, return a copy.force (bool, default False) – Proceed even if
log_spacedisagrees with automatic log detection.verbose (bool, default False) – If True, print the resolved log space, samples whose median is NaN (per group when
group_byis set), where the factors are stored (adata.uns[key_added]), and a run summary.
- Returns:
AnnData or None – Normalized AnnData when
inplaceis False; otherwise None.pandas.DataFrame, optional – Per-sample factors when
inplaceis False.
- Raises:
TypeError – If any argument has an unexpected type, or if
.Xis sparse.ValueError – If
targetis invalid,key_addedis empty,fill_nais non-finite,fill_naandzero_to_naare both set,group_bycontains NaN,log_spacedisagrees with automatic detection andforce=False, a sample median is exactly 0 in linear space (log_space=False), or the normalization produces infinite values.KeyError – If
group_byis not a column inadata.obs.
Examples
Build a minimal log-space, protein-level proteodata object:
>>> import numpy as np >>> import pandas as pd >>> import anndata as ad >>> import proteopy as pr >>> adata = ad.AnnData( ... X=np.array([[18.0, 20.0, 25.0], ... [19.0, 21.0, 22.0], ... [16.0, 19.0, 28.0]]), ... obs=pd.DataFrame({"sample_id": ["S0", "S1", "S2"]}, ... index=["S0", "S1", "S2"]), ... var=pd.DataFrame({"protein_id": ["P0", "P1", "P2"]}, ... index=["P0", "P1", "P2"]), ... )
Normalize using the median of sample medians (defaults), returning a copy together with the per-sample factors:
>>> adata_norm, factors = pr.pp.normalize_median( ... adata, inplace=False) >>> adata_norm.X array([[18., 20., 25.], [18., 20., 21.], [17., 20., 29.]])
Normalize in place using the maximum of sample medians:
>>> pr.pp.normalize_median(adata, target="max") >>> adata.X array([[19., 21., 26.], [19., 21., 22.], [18., 21., 30.]])