alphapepttools.pp.filter_data_completeness

alphapepttools.pp.filter_data_completeness#

alphapepttools.pp.filter_data_completeness(adata, max_missing_fraction=None, max_missing_count=None, group_column=None, groups=None, keep_strategy='all', action='flag', var_colname='passed_threshold_missing_values', **kwargs)#

Filter features based on missing values.

The missingness threshold is given either as a fraction (max_missing_fraction) or as an absolute number of missing values (max_missing_count). Exactly one of the two must be provided.

Operates globally, or per-group when group_column is set.

Under group-wise filtering the threshold is evaluated within each group, not across the whole dataset. For max_missing_count this means the same absolute count corresponds to different completeness levels in groups of different size - e.g. max_missing_count=1 allows 1 of 3 missing in a three-sample group and 1 of 20 in a twenty-sample group. Use max_missing_fraction if you want a size-independent criterion.

Parameters:
  • adata (AnnData) – AnnData object

  • max_missing_fraction (float | None (default: None)) – Maximum fraction of missing values allowed to pass, in the interval [0.0, 1.0]. Features with a fraction of missing values greater than (>) max_missing_fraction are filtered out. Mutually exclusive with max_missing_count; exactly one of the two must be provided.

  • max_missing_count (int | None (default: None)) – Maximum absolute number of missing values allowed to pass. Features with more than (>) max_missing_count missing values are filtered out. Mutually exclusive with max_missing_fraction; exactly one of the two must be provided.

  • group_column (str | None (default: None)) – Column name in adata.obs defining groups for group-wise filtering. If None (default), computes missingness across all samples. If specified, computes statistics separately for each group. This is useful to retain features that are exclusive to a specific sample group.

  • groups (list[str] | None (default: None)) – List of levels of the group_column to consider in filtering. E.g. if the column has the levels ['A', 'B', 'C'], and groups = ['A', 'B'], only missingness of features in these groups is considered. If None, all groups are considered. Silently ignored if group_column is None.

  • keep_strategy (Literal['any', 'all'] (default: 'all')) – Only relevant for groupwise filtering: it decides how the per-group results are combined. Silently ignored if group_column is None, since there is only one result to combine. - all : keep a feature only if it passes in every group. - any : keep a feature if it passes the threshold in at least one group.

  • action (Literal['flag', 'drop'] (default: 'flag')) – Action to perform. Can be flag (default) or drop. If flag, a boolean column in adata.var is added to indicate whether the feature passed the missingness threshold. If drop, features that do not pass the threshold are dropped from the AnnData object.

  • var_colname (str (default: 'passed_threshold_missing_values')) – Name of the adata.var boolean column to add if action is flag.

Return type:

AnnData

Returns:

AnnData AnnData object with either a new adata.var column added (if flag) or filtered features (if drop). Note that flag adds the column to the object that was passed in and returns that same object, whereas drop leaves the input untouched and returns a filtered copy.

Raises:
  • TypeError – If adata is not an AnnData object.

  • ValueError – If not exactly one of max_missing_fraction / max_missing_count is provided, if a threshold is out of range, if keep_strategy or action is invalid, if adata has no features, non-numeric values in X or duplicated indices in obs.

  • KeyError – If a requested group is not present in group_column.

Examples

Flag features with too many missing values:

import anndata as ad
import pandas as pd
import numpy as np
import alphapepttools as apt

# Create data with missing values
X = np.array(
    [[1.0, np.nan, 3.0, 4.0], [2.0, np.nan, 6.0, 8.0], [3.0, 5.0, np.nan, 12.0], [4.0, 6.0, 9.0, 16.0]]
)
adata = ad.AnnData(
    X=X,
    obs=pd.DataFrame({"group": ["A", "A", "B", "B"]}),
    var=pd.DataFrame(index=["prot1", "prot2", "prot3", "prot4"]),
)

# Missing values per feature: prot1=0, prot2=2, prot3=1, prot4=0 (out of 4 samples)

# Mark which features have <=30% missing values in `adata.var`, without dropping any:
# prot2 (50% missing) is marked False, the rest True
adata = apt.pp.filter_data_completeness(adata, max_missing_fraction=0.3, action="flag")

# Drop features with more than 1 missing value: removes prot2
adata = apt.pp.filter_data_completeness(adata, max_missing_count=1, action="drop")

# Consider missingness in group B only: removes prot3, which is missing in 1 of the 2
# group-B samples (50%) even though it is only 25% missing overall
adata = apt.pp.filter_data_completeness(
    adata, max_missing_fraction=0.3, group_column="group", groups=["B"], action="drop"
)

Groupwise filtering — keep_strategy controls how per-group results are combined:

# No grouping: keep features with ≤50% missingness across the whole study
apt.pp.filter_data_completeness(adata, max_missing_fraction=0.5)

# Logical AND (default): keep features with ≤50% missingness in *every* condition.
# A feature with 5/5 missing in condition A and 0/995 missing in condition B is removed
# despite being 99.5% complete overall.
apt.pp.filter_data_completeness(adata, max_missing_fraction=0.5, group_column="condition", keep_strategy="all")

# Logical OR: keep features with ≤50% missingness in *at least one* condition.
# Retains condition-specific features, which are often the most interesting
# candidates in clinical studies.
apt.pp.filter_data_completeness(adata, max_missing_fraction=0.5, group_column="condition", keep_strategy="any")