Microfactual API Reference

Core

Core data structures for microfactual.

class microfactual.core.MicrobiomeDataset(abundance, metadata, target_column, sample_column='Sample ID')

Bases: object

Central data structure for microbiome datasets.

This class provides a clean interface for microbiome data, building on the existing data processing functions while providing sklearn-compatible data access patterns.

abundance(pd.DataFrame)
Type:

Abundance data (features x samples)

metadata(pd.DataFrame)
Type:

Sample metadata

target_column(str)
Type:

Name of target variable column

sample_column(str)
Type:

Name of sample ID column

property X: DataFrame

Features matrix in sklearn format (samples x features).

Returns:

Transposed abundance matrix with samples as rows, features as columns

Return type:

pd.DataFrame

clr_transform(log_n0=1e-06, inplace=True)

Apply CLR transformation using existing clr_transform function.

Parameters:
  • log_n0 (float, optional) – Pseudocount for zero replacement, by default 1e-6

  • inplace (bool, optional) – Whether to modify dataset in place, by default True

Returns:

Transformed dataset if inplace=False, None otherwise

Return type:

MicrobiomeDataset or None

property feature_names: Index

Get feature names (e.g., species names).

Returns:

Feature names from abundance data index

Return type:

pd.Index

filter_features(abundance_cutoff=1e-06, prevalence_cutoff=0.05, inplace=True)

Apply feature filtering using existing filter_data function.

Parameters:
  • abundance_cutoff (float, optional) – Minimum mean abundance threshold, by default 1e-6

  • prevalence_cutoff (float, optional) – Minimum prevalence threshold, by default 0.05

  • inplace (bool, optional) – Whether to modify dataset in place, by default True

Returns:

Filtered dataset if inplace=False, None otherwise

Return type:

MicrobiomeDataset or None

classmethod from_files(abundance_file, metadata_file, target_column, sample_column='Sample ID')

Create MicrobiomeDataset from files using existing load_data function.

Parameters:
  • abundance_file (str) – Path to abundance data file (tab-separated)

  • metadata_file (str) – Path to metadata file (tab-separated)

  • target_column (str) – Column name for target variable

  • sample_column (str, optional) – Column name for sample IDs, by default “Sample ID”

Returns:

Initialized dataset object

Return type:

MicrobiomeDataset

get_info()

Get comprehensive dataset information.

Returns:

Dictionary containing dataset statistics and metadata

Return type:

dict

reset_preprocessing()

Reset to original data, removing all preprocessing steps.

Return type:

None

property sample_names: Index

Get sample names/IDs.

Returns:

Sample IDs from abundance data columns

Return type:

pd.Index

property target_names: list

Get the original target class names.

Returns:

List of unique target class names

Return type:

list

property y: Series

Target vector with encoded categorical labels.

Returns:

Encoded target labels as categorical codes

Return type:

pd.Series

Central data structure for microbiome datasets.

class microfactual.core.dataset.MicrobiomeDataset(abundance, metadata, target_column, sample_column='Sample ID')

Bases: object

Central data structure for microbiome datasets.

This class provides a clean interface for microbiome data, building on the existing data processing functions while providing sklearn-compatible data access patterns.

abundance(pd.DataFrame)
Type:

Abundance data (features x samples)

metadata(pd.DataFrame)
Type:

Sample metadata

target_column(str)
Type:

Name of target variable column

sample_column(str)
Type:

Name of sample ID column

property X: DataFrame

Features matrix in sklearn format (samples x features).

Returns:

Transposed abundance matrix with samples as rows, features as columns

Return type:

pd.DataFrame

clr_transform(log_n0=1e-06, inplace=True)

Apply CLR transformation using existing clr_transform function.

Parameters:
  • log_n0 (float, optional) – Pseudocount for zero replacement, by default 1e-6

  • inplace (bool, optional) – Whether to modify dataset in place, by default True

Returns:

Transformed dataset if inplace=False, None otherwise

Return type:

MicrobiomeDataset or None

property feature_names: Index

Get feature names (e.g., species names).

Returns:

Feature names from abundance data index

Return type:

pd.Index

filter_features(abundance_cutoff=1e-06, prevalence_cutoff=0.05, inplace=True)

Apply feature filtering using existing filter_data function.

Parameters:
  • abundance_cutoff (float, optional) – Minimum mean abundance threshold, by default 1e-6

  • prevalence_cutoff (float, optional) – Minimum prevalence threshold, by default 0.05

  • inplace (bool, optional) – Whether to modify dataset in place, by default True

Returns:

Filtered dataset if inplace=False, None otherwise

Return type:

MicrobiomeDataset or None

classmethod from_files(abundance_file, metadata_file, target_column, sample_column='Sample ID')

Create MicrobiomeDataset from files using existing load_data function.

Parameters:
  • abundance_file (str) – Path to abundance data file (tab-separated)

  • metadata_file (str) – Path to metadata file (tab-separated)

  • target_column (str) – Column name for target variable

  • sample_column (str, optional) – Column name for sample IDs, by default “Sample ID”

Returns:

Initialized dataset object

Return type:

MicrobiomeDataset

get_info()

Get comprehensive dataset information.

Returns:

Dictionary containing dataset statistics and metadata

Return type:

dict

reset_preprocessing()

Reset to original data, removing all preprocessing steps.

Return type:

None

property sample_names: Index

Get sample names/IDs.

Returns:

Sample IDs from abundance data columns

Return type:

pd.Index

property target_names: list

Get the original target class names.

Returns:

List of unique target class names

Return type:

list

property y: Series

Target vector with encoded categorical labels.

Returns:

Encoded target labels as categorical codes

Return type:

pd.Series

Preprocessing

Preprocessing module for microbiome data transformations.

class microfactual.preprocessing.AbundanceFilter(min_abundance=1e-06)

Bases: BaseEstimator, TransformerMixin

Filter features by minimum mean abundance.

Parameters:

min_abundance (float, default=1e-6) – Minimum mean abundance required to retain a feature.

Examples

>>> filt = AbundanceFilter(min_abundance=0.01)
>>> X_filtered = filt.fit_transform(X)
fit(X, y=None)

Learn which features pass the abundance threshold.

Parameters:
  • X (pd.DataFrame) – Abundance data (samples x features).

  • y (None) – Ignored; present for scikit-learn API compatibility.

get_feature_names_out(input_features=None)

Get output feature names for transformation.

Parameters:

input_features (array-like of str or None, default=None) – Input features.

Returns:

Transformed feature names.

Return type:

array of str

transform(X)

Apply the abundance filter.

Parameters:

X (pd.DataFrame) – Abundance data (samples x features).

Returns:

Filtered data with low-abundance features removed.

Return type:

pd.DataFrame

class microfactual.preprocessing.CLRTransform(pseudocount=1e-06)

Bases: BaseEstimator, TransformerMixin

Centered Log-Ratio (CLR) transformation for compositional data.

The CLR transformation is appropriate for microbiome abundance data which is compositional (relative abundances sum to 1).

Parameters:

pseudocount (float, default=1e-6) – Small value added to zeros before log transformation.

Examples

>>> clr = CLRTransform()
>>> X_transformed = clr.fit_transform(X)
fit(X, y=None)

Fit the transformer.

CLR is a stateless transformation, so this just validates input.

Parameters:
  • X (pd.DataFrame) – Abundance data (samples x features).

  • y (None) – Ignored; present for scikit-learn API compatibility.

get_feature_names_out(input_features=None)

Get output feature names for transformation.

Parameters:

input_features (array-like of str or None, default=None) – Input features.

Returns:

Transformed feature names.

Return type:

array of str

transform(X)

Apply the CLR transformation.

Parameters:

X (pd.DataFrame) – Abundance data (samples x features).

Returns:

CLR-transformed data with the same shape.

Return type:

pd.DataFrame

class microfactual.preprocessing.PrevalenceFilter(min_prevalence=0.05)

Bases: BaseEstimator, TransformerMixin

Filter features by minimum prevalence (fraction of non-zero samples).

Parameters:

min_prevalence (float, default=0.05) – Minimum fraction of samples in which a feature must be present. Must be between 0 and 1.

Examples

>>> filt = PrevalenceFilter(min_prevalence=0.1)
>>> X_filtered = filt.fit_transform(X)
fit(X, y=None)

Learn which features pass the prevalence threshold.

Parameters:
  • X (pd.DataFrame) – Abundance data (samples x features).

  • y (None) – Ignored; present for scikit-learn API compatibility.

get_feature_names_out(input_features=None)

Get output feature names for transformation.

Parameters:

input_features (array-like of str or None, default=None) – Input features.

Returns:

Transformed feature names.

Return type:

array of str

transform(X)

Apply the prevalence filter.

Parameters:

X (pd.DataFrame) – Abundance data (samples x features).

Returns:

Filtered data with rare features removed.

Return type:

pd.DataFrame

Sklearn-compatible preprocessing transforms for microbiome data.

All transforms follow sklearn’s fit/transform pattern and can be used in sklearn.pipeline.Pipeline.

class microfactual.preprocessing.transforms.AbundanceFilter(min_abundance=1e-06)

Bases: BaseEstimator, TransformerMixin

Filter features by minimum mean abundance.

Parameters:

min_abundance (float, default=1e-6) – Minimum mean abundance required to retain a feature.

Examples

>>> filt = AbundanceFilter(min_abundance=0.01)
>>> X_filtered = filt.fit_transform(X)
fit(X, y=None)

Learn which features pass the abundance threshold.

Parameters:
  • X (pd.DataFrame) – Abundance data (samples x features).

  • y (None) – Ignored; present for scikit-learn API compatibility.

get_feature_names_out(input_features=None)

Get output feature names for transformation.

Parameters:

input_features (array-like of str or None, default=None) – Input features.

Returns:

Transformed feature names.

Return type:

array of str

transform(X)

Apply the abundance filter.

Parameters:

X (pd.DataFrame) – Abundance data (samples x features).

Returns:

Filtered data with low-abundance features removed.

Return type:

pd.DataFrame

class microfactual.preprocessing.transforms.CLRTransform(pseudocount=1e-06)

Bases: BaseEstimator, TransformerMixin

Centered Log-Ratio (CLR) transformation for compositional data.

The CLR transformation is appropriate for microbiome abundance data which is compositional (relative abundances sum to 1).

Parameters:

pseudocount (float, default=1e-6) – Small value added to zeros before log transformation.

Examples

>>> clr = CLRTransform()
>>> X_transformed = clr.fit_transform(X)
fit(X, y=None)

Fit the transformer.

CLR is a stateless transformation, so this just validates input.

Parameters:
  • X (pd.DataFrame) – Abundance data (samples x features).

  • y (None) – Ignored; present for scikit-learn API compatibility.

get_feature_names_out(input_features=None)

Get output feature names for transformation.

Parameters:

input_features (array-like of str or None, default=None) – Input features.

Returns:

Transformed feature names.

Return type:

array of str

transform(X)

Apply the CLR transformation.

Parameters:

X (pd.DataFrame) – Abundance data (samples x features).

Returns:

CLR-transformed data with the same shape.

Return type:

pd.DataFrame

class microfactual.preprocessing.transforms.PrevalenceFilter(min_prevalence=0.05)

Bases: BaseEstimator, TransformerMixin

Filter features by minimum prevalence (fraction of non-zero samples).

Parameters:

min_prevalence (float, default=0.05) – Minimum fraction of samples in which a feature must be present. Must be between 0 and 1.

Examples

>>> filt = PrevalenceFilter(min_prevalence=0.1)
>>> X_filtered = filt.fit_transform(X)
fit(X, y=None)

Learn which features pass the prevalence threshold.

Parameters:
  • X (pd.DataFrame) – Abundance data (samples x features).

  • y (None) – Ignored; present for scikit-learn API compatibility.

get_feature_names_out(input_features=None)

Get output feature names for transformation.

Parameters:

input_features (array-like of str or None, default=None) – Input features.

Returns:

Transformed feature names.

Return type:

array of str

transform(X)

Apply the prevalence filter.

Parameters:

X (pd.DataFrame) – Abundance data (samples x features).

Returns:

Filtered data with rare features removed.

Return type:

pd.DataFrame

Models

Models module for microfactual.

class microfactual.models.MicrobiomeClassifier(algorithm='random_forest', preprocessing='auto', **model_params)

Bases: ClassifierMixin, BaseEstimator

Classifier with built-in microbiome preprocessing.

This provides a simple interface for microbiome classification with sensible defaults. It wraps sklearn classifiers with optional preprocessing steps.

_estimator_type

Type of estimator, set to “classifier” for sklearn compatibility.

Type:

str

Parameters:
  • algorithm (str, default="random_forest") – The classification algorithm to use. Options: “random_forest”, “svm”, “logistic”

  • preprocessing (str, list, or None, default="auto") – Preprocessing strategy: - “auto”: Apply abundance filter, prevalence filter, CLR transform - None: No preprocessing (use raw features) - list: Custom list of sklearn-compatible transformers

  • **model_params – Additional parameters passed to the underlying classifier.

Examples

>>> clf = MicrobiomeClassifier()
>>> clf.fit(X, y)
>>> predictions = clf.predict(X_test)
ALGORITHMS = {'logistic': <class 'sklearn.linear_model._logistic.LogisticRegression'>, 'random_forest': <class 'sklearn.ensemble._forest.RandomForestClassifier'>}
property feature_importances_

Get feature importances if available.

fit(X, y)

Fit the classifier.

Parameters:
  • X (pd.DataFrame or np.ndarray) – Feature matrix (samples x features).

  • y (pd.Series or np.ndarray) – Target vector.

Return type:

self

get_params(deep=True)

Get parameters for this estimator (sklearn-compatible).

Extends the default behaviour so that keyword arguments forwarded to the underlying classifier (e.g. n_estimators, max_depth) are exposed as top-level params. This makes the estimator usable with sklearn.clone, set_params and GridSearchCV over those params.

Parameters:

deep (bool, default=True) – Kept for sklearn API compatibility; has no nested effect here.

Returns:

Parameter names mapped to their values, including forwarded model params.

Return type:

dict

predict(X)

Predict class labels.

Parameters:

X (pd.DataFrame or np.ndarray) – Feature matrix (samples x features).

Returns:

y_pred – Predicted class labels.

Return type:

np.ndarray

predict_proba(X)

Predict class probabilities.

Parameters:

X (pd.DataFrame or np.ndarray) – Feature matrix (samples x features).

Returns:

proba – Probability for each class, shape (n_samples, n_classes).

Return type:

np.ndarray

set_params(**params)

Set the parameters of this estimator (sklearn-compatible).

Unknown parameters are treated as keyword arguments for the underlying classifier rather than raising, mirroring the **model_params accepted by __init__.

Parameters:

**params – Estimator parameters to set.

Returns:

self.

Return type:

MicrobiomeClassifier

set_score_request(*, sample_weight: bool | None | str = '$UNCHANGED$') MicrobiomeClassifier

Configure whether metadata should be requested to be passed to the score method.

Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with enable_metadata_routing=True (see sklearn.set_config()). Please check the User Guide on how the routing mechanism works.

The options for each parameter are:

  • True: metadata is requested, and passed to score if provided. The request is ignored if metadata is not provided.

  • False: metadata is not requested and the meta-estimator will not pass it to score.

  • None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.

  • str: metadata should be passed to the meta-estimator with this given alias instead of the original name.

The default (sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.

Added in version 1.3.

Parameters:

sample_weight (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for sample_weight parameter in score.

Returns:

self – The updated object.

Return type:

object

Microbiome-optimized classifiers with built-in preprocessing.

The MicrobiomeClassifier provides a batteries-included approach to microbiome classification with sensible defaults for preprocessing.

class microfactual.models.classifiers.MicrobiomeClassifier(algorithm='random_forest', preprocessing='auto', **model_params)

Bases: ClassifierMixin, BaseEstimator

Classifier with built-in microbiome preprocessing.

This provides a simple interface for microbiome classification with sensible defaults. It wraps sklearn classifiers with optional preprocessing steps.

_estimator_type

Type of estimator, set to “classifier” for sklearn compatibility.

Type:

str

Parameters:
  • algorithm (str, default="random_forest") – The classification algorithm to use. Options: “random_forest”, “svm”, “logistic”

  • preprocessing (str, list, or None, default="auto") – Preprocessing strategy: - “auto”: Apply abundance filter, prevalence filter, CLR transform - None: No preprocessing (use raw features) - list: Custom list of sklearn-compatible transformers

  • **model_params – Additional parameters passed to the underlying classifier.

Examples

>>> clf = MicrobiomeClassifier()
>>> clf.fit(X, y)
>>> predictions = clf.predict(X_test)
ALGORITHMS = {'logistic': <class 'sklearn.linear_model._logistic.LogisticRegression'>, 'random_forest': <class 'sklearn.ensemble._forest.RandomForestClassifier'>}
property feature_importances_

Get feature importances if available.

fit(X, y)

Fit the classifier.

Parameters:
  • X (pd.DataFrame or np.ndarray) – Feature matrix (samples x features).

  • y (pd.Series or np.ndarray) – Target vector.

Return type:

self

get_params(deep=True)

Get parameters for this estimator (sklearn-compatible).

Extends the default behaviour so that keyword arguments forwarded to the underlying classifier (e.g. n_estimators, max_depth) are exposed as top-level params. This makes the estimator usable with sklearn.clone, set_params and GridSearchCV over those params.

Parameters:

deep (bool, default=True) – Kept for sklearn API compatibility; has no nested effect here.

Returns:

Parameter names mapped to their values, including forwarded model params.

Return type:

dict

predict(X)

Predict class labels.

Parameters:

X (pd.DataFrame or np.ndarray) – Feature matrix (samples x features).

Returns:

y_pred – Predicted class labels.

Return type:

np.ndarray

predict_proba(X)

Predict class probabilities.

Parameters:

X (pd.DataFrame or np.ndarray) – Feature matrix (samples x features).

Returns:

proba – Probability for each class, shape (n_samples, n_classes).

Return type:

np.ndarray

set_params(**params)

Set the parameters of this estimator (sklearn-compatible).

Unknown parameters are treated as keyword arguments for the underlying classifier rather than raising, mirroring the **model_params accepted by __init__.

Parameters:

**params – Estimator parameters to set.

Returns:

self.

Return type:

MicrobiomeClassifier

set_score_request(*, sample_weight: bool | None | str = '$UNCHANGED$') MicrobiomeClassifier

Configure whether metadata should be requested to be passed to the score method.

Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with enable_metadata_routing=True (see sklearn.set_config()). Please check the User Guide on how the routing mechanism works.

The options for each parameter are:

  • True: metadata is requested, and passed to score if provided. The request is ignored if metadata is not provided.

  • False: metadata is not requested and the meta-estimator will not pass it to score.

  • None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.

  • str: metadata should be passed to the meta-estimator with this given alias instead of the original name.

The default (sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.

Added in version 1.3.

Parameters:

sample_weight (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for sample_weight parameter in score.

Returns:

self – The updated object.

Return type:

object

Explainability

Explainability module for interpretability methods.

class microfactual.explainability.BaseExplainer(model, data, **kwargs)

Bases: ABC

Abstract base class for model explainers.

abstractmethod explain(query_instance, **kwargs)

Generate explanations for a query instance.

Parameters:
  • query_instance (pd.DataFrame) – Instance(s) to explain.

  • **kwargs – Additional parameters for generating the explanation.

Returns:

The explanation object (framework specific).

Return type:

Any

class microfactual.explainability.CounterfactualResult(original, counterfactuals, model, feature_names, class_names=None, raw=None, atol=1e-08)

Bases: object

Interpretable wrapper around a set of counterfactuals for one sample.

Parameters:
  • original (array-like) – The query sample’s feature values.

  • counterfactuals (array-like) – Counterfactual rows (n_cfs x n_features), already sparsified if desired.

  • model (Any) – Fitted classifier used to (re)validate predictions.

  • feature_names (list of str) – Names of the features, in column order.

  • class_names (list of str, optional) – Human-readable class labels, indexed by predicted integer class.

  • raw (Any, optional) – The underlying DiCE explanation object, kept for advanced use.

  • atol (float, default=1e-8) – Tolerance below which a feature is considered unchanged.

changes(cf_index=None)

Return the per-feature changes for one or all counterfactuals.

Parameters:

cf_index (int, optional) – If given, return changes for that single counterfactual. Otherwise return the changes for all counterfactuals stacked, with a cf column identifying each.

Returns:

Columns: cf (omitted when cf_index given), feature, original, counterfactual, delta, direction. Only rows where the feature actually changed are included, sorted by descending absolute change.

Return type:

pd.DataFrame

property n_changes: list[int]

Number of features changed by each counterfactual.

property n_counterfactuals: int

Number of counterfactuals held.

property original_prediction: int

Predicted class for the original sample.

summary()

Return a short human-readable summary of the counterfactuals.

Return type:

str

property validity: float

Fraction of counterfactuals that actually flip the prediction.

visualize_as_dataframe(*args, **kwargs)

Delegate to the underlying DiCE explanation’s visualizer, if present.

Return type:

Any

class microfactual.explainability.DiCEExplainer(model, background_data, target_column, target_data=None, backend='sklearn', continuous_features=None, **kwargs)

Bases: BaseExplainer

Wrapper for DiCE (Diverse Counterfactual Explanations).

Generates counterfactual examples: “What changes to the input would flip the model prediction?”

explain(query_instance, total_CFs=5, desired_class='opposite', **kwargs)

Generate counterfactual explanations.

Parameters:
  • query_instance (pd.DataFrame) – The instance to explain.

  • total_CFs (int, default=5) – Number of counterfactuals to generate.

  • desired_class (str, default="opposite") – Desired target class (“opposite” or specific class index).

  • **kwargs – Additional parameters passed to exp.generate_counterfactuals()

Returns:

The explanation object containing counterfactuals.

Return type:

dice_ml.counterfactual_explanations.CounterfactualExplanations

microfactual.explainability.counterfactual_concordance(result, X, y, reference_class)

Fraction of changed taxa whose counterfactual moves toward the reference.

For each changed taxon, checks whether the counterfactual’s change is in the same direction as the gap between the sample’s original value and the reference-class median. A high score means the counterfactual shifts the sample toward the reference distribution rather than in some arbitrary model-exploiting direction — a cheap plausibility signal.

Parameters:
  • result (CounterfactualResult) – A result from explain_counterfactual().

  • X (pd.DataFrame) – Feature matrix used to compute the reference median.

  • y (array-like) – Class labels aligned with X.

  • reference_class (Any) – The label value in y to move toward.

Returns:

Concordance in [0, 1], or nan if there are no changes.

Return type:

float

microfactual.explainability.counterfactual_importance(model, X, y, *, background_data=None, target_column='outcome', total_CFs=3, desired_class='opposite', features_to_vary='all', permitted_range=None, sparse=True, method='genetic', backend='sklearn', top_n=None, **kwargs)

Aggregate counterfactuals across a cohort into per-taxon importance.

Generates counterfactuals for every sample in X and summarises how often each taxon has to change to flip predictions, and in which direction. This is a local-aggregated importance: unlike a global feature-importance score, it reflects the taxa that actually drive individual decisions across the cohort, with an interpretable direction of change.

As with explain_counterfactual(), pass everything in the model’s input feature space (e.g. CLR).

Parameters:
  • model (Any) – Fitted, sklearn-compatible classifier.

  • X (pd.DataFrame) – Samples to explain (samples x features).

  • y (pd.Series, pd.DataFrame, or array-like) – Targets aligned with background_data.

  • background_data (pd.DataFrame, optional) – Distribution DiCE samples from; defaults to X itself.

  • target_column (str, default="outcome") – See explain_counterfactual().

  • total_CFs (int, default=3) – Counterfactuals generated per sample before aggregation.

  • desired_class (str, default="opposite") – See explain_counterfactual().

  • features_to_vary (str or list of str, default="all") – See explain_counterfactual().

  • permitted_range (dict, optional) – See explain_counterfactual().

  • sparse (bool, default=True) – See explain_counterfactual().

  • method (str, default="genetic") – See explain_counterfactual().

  • backend (str, default="sklearn") – See explain_counterfactual().

  • top_n (int, optional) – If given, return only the top_n most frequently implicated taxa.

  • **kwargs (Any) – Forwarded to dice_ml.Dice.generate_counterfactuals.

Returns:

One row per implicated taxon, sorted by how many samples implicate it. Columns: feature, n_samples (samples whose counterfactuals change it), frequency (fraction of explained samples), mean_delta (mean signed change, averaged per sample), direction (net “increase”/ “decrease”).

Return type:

pd.DataFrame

microfactual.explainability.explain_counterfactual(model, query, background_data, y, *, target_column='outcome', total_CFs=5, desired_class='opposite', features_to_vary='all', permitted_range=None, sparse=True, class_names=None, continuous_features=None, method='genetic', backend='sklearn', return_raw=False, **kwargs)

Generate actionable counterfactual explanations for one or more samples.

This is MicroFactual’s headline entry point: it answers “what minimal change in feature values would flip this sample’s prediction?” in a single call, wrapping DiCEExplainer.

Two features make the result actionable rather than a wall of numbers:

  • features_to_vary / permitted_range restrict the search to the taxa you consider modifiable and to plausible value ranges;

  • sparse=True (default) post-processes each counterfactual to a near-minimal set of changes that still flips the prediction, so you get “change these few taxa” instead of “change everything”.

Because DiCE searches for counterfactuals in the model’s input space, pass model, query and background_data in the same feature space the model was trained on (e.g. CLR-transformed features, if the model was fit on CLR-transformed data).

Parameters:
  • model (Any) – A fitted, sklearn-compatible classifier (e.g. a MicrobiomeClassifier or a bare sklearn estimator) exposing predict/predict_proba.

  • query (pd.DataFrame) – Sample(s) to explain, as one or more rows with the same feature columns as background_data.

  • background_data (pd.DataFrame) – Training features (samples x features) used to describe the data distribution DiCE samples from.

  • y (pd.Series, pd.DataFrame, or array-like) – Training targets aligned with background_data.

  • target_column (str, default="outcome") – Name DiCE uses for the outcome column internally. Only needs to differ from the feature names; it is not a column in query.

  • total_CFs (int, default=5) – Number of counterfactuals to generate per query sample.

  • desired_class (str, default="opposite") – Target class for the counterfactuals (“opposite” flips the prediction).

  • features_to_vary (str or list of str, default="all") – Which features DiCE may change. Pass a list to restrict the search to modifiable taxa (e.g. diet-associated genera).

  • permitted_range (dict, optional) – Per-feature {name: [min, max]} bounds constraining counterfactual values to a plausible range.

  • sparse (bool, default=True) – If True, greedily reduce each counterfactual to a near-minimal set of changes that preserves the flipped prediction.

  • class_names (list of str, optional) – Human-readable class labels (indexed by integer class) for the summary.

  • continuous_features (list of str, optional) – Feature names to treat as continuous. Defaults to all columns of background_data (appropriate for abundance / CLR features).

  • method (str, default="genetic") – DiCE search method (“genetic”, “random”, or “kdtree”).

  • backend (str, default="sklearn") – DiCE model backend.

  • return_raw (bool, default=False) – If True, return the raw dice_ml explanation object instead of a CounterfactualResult.

  • **kwargs (Any) – Additional arguments forwarded to dice_ml.Dice.generate_counterfactuals.

Returns:

One result per query sample (a single result if query has one row). Only genuine counterfactuals — those that actually flip the prediction — are kept; DiCE rows that fail to flip are discarded. Each result exposes .changes(), .n_changes, .validity and .summary(). If return_raw=True, the raw DiCE object is returned instead.

Return type:

CounterfactualResult or list of CounterfactualResult

Raises:

ImportError – If the optional explainability extra (dice-ml) is not installed.

Examples

>>> import microfactual as mf
>>> model = mf.MicrobiomeClassifier(preprocessing=None).fit(X_clr, y)
>>> cf = mf.explain_counterfactual(model, X_clr.iloc[[0]], X_clr, y)
>>> print(cf.summary())
>>> cf.changes()
microfactual.explainability.plausible_range(X, y, reference_class, *, q=(0.05, 0.95), features=None)

Per-feature [low, high] bounds from a reference class’s quantiles.

Feed the result to explain_counterfactual(..., permitted_range=...) so counterfactuals are confined to values actually observed in the reference (e.g. control) class, rather than extrapolating to implausible extremes.

Parameters:
  • X (pd.DataFrame) – Feature matrix (samples x features), in the model’s input space.

  • y (array-like) – Class labels aligned with X.

  • reference_class (Any) – The label value in y whose distribution defines “plausible”.

  • q (tuple of float, default=(0.05, 0.95)) – Lower/upper quantiles used as the bounds.

  • features (list of str, optional) – Restrict to these features; defaults to all columns of X.

Returns:

{feature: [low, high]} suitable for DiCE’s permitted_range.

Return type:

dict

Base interface for all explanation methods.

Decouples the core library from specific explainability frameworks.

class microfactual.explainability.base.BaseExplainer(model, data, **kwargs)

Bases: ABC

Abstract base class for model explainers.

abstractmethod explain(query_instance, **kwargs)

Generate explanations for a query instance.

Parameters:
  • query_instance (pd.DataFrame) – Instance(s) to explain.

  • **kwargs – Additional parameters for generating the explanation.

Returns:

The explanation object (framework specific).

Return type:

Any

Counterfactual explanations using DiCE.

class microfactual.explainability.counterfactuals.DiCEExplainer(model, background_data, target_column, target_data=None, backend='sklearn', continuous_features=None, **kwargs)

Bases: BaseExplainer

Wrapper for DiCE (Diverse Counterfactual Explanations).

Generates counterfactual examples: “What changes to the input would flip the model prediction?”

explain(query_instance, total_CFs=5, desired_class='opposite', **kwargs)

Generate counterfactual explanations.

Parameters:
  • query_instance (pd.DataFrame) – The instance to explain.

  • total_CFs (int, default=5) – Number of counterfactuals to generate.

  • desired_class (str, default="opposite") – Desired target class (“opposite” or specific class index).

  • **kwargs – Additional parameters passed to exp.generate_counterfactuals()

Returns:

The explanation object containing counterfactuals.

Return type:

dice_ml.counterfactual_explanations.CounterfactualExplanations

microfactual.explainability.counterfactuals.counterfactual_importance(model, X, y, *, background_data=None, target_column='outcome', total_CFs=3, desired_class='opposite', features_to_vary='all', permitted_range=None, sparse=True, method='genetic', backend='sklearn', top_n=None, **kwargs)

Aggregate counterfactuals across a cohort into per-taxon importance.

Generates counterfactuals for every sample in X and summarises how often each taxon has to change to flip predictions, and in which direction. This is a local-aggregated importance: unlike a global feature-importance score, it reflects the taxa that actually drive individual decisions across the cohort, with an interpretable direction of change.

As with explain_counterfactual(), pass everything in the model’s input feature space (e.g. CLR).

Parameters:
  • model (Any) – Fitted, sklearn-compatible classifier.

  • X (pd.DataFrame) – Samples to explain (samples x features).

  • y (pd.Series, pd.DataFrame, or array-like) – Targets aligned with background_data.

  • background_data (pd.DataFrame, optional) – Distribution DiCE samples from; defaults to X itself.

  • target_column (str, default="outcome") – See explain_counterfactual().

  • total_CFs (int, default=3) – Counterfactuals generated per sample before aggregation.

  • desired_class (str, default="opposite") – See explain_counterfactual().

  • features_to_vary (str or list of str, default="all") – See explain_counterfactual().

  • permitted_range (dict, optional) – See explain_counterfactual().

  • sparse (bool, default=True) – See explain_counterfactual().

  • method (str, default="genetic") – See explain_counterfactual().

  • backend (str, default="sklearn") – See explain_counterfactual().

  • top_n (int, optional) – If given, return only the top_n most frequently implicated taxa.

  • **kwargs (Any) – Forwarded to dice_ml.Dice.generate_counterfactuals.

Returns:

One row per implicated taxon, sorted by how many samples implicate it. Columns: feature, n_samples (samples whose counterfactuals change it), frequency (fraction of explained samples), mean_delta (mean signed change, averaged per sample), direction (net “increase”/ “decrease”).

Return type:

pd.DataFrame

microfactual.explainability.counterfactuals.explain_counterfactual(model, query, background_data, y, *, target_column='outcome', total_CFs=5, desired_class='opposite', features_to_vary='all', permitted_range=None, sparse=True, class_names=None, continuous_features=None, method='genetic', backend='sklearn', return_raw=False, **kwargs)

Generate actionable counterfactual explanations for one or more samples.

This is MicroFactual’s headline entry point: it answers “what minimal change in feature values would flip this sample’s prediction?” in a single call, wrapping DiCEExplainer.

Two features make the result actionable rather than a wall of numbers:

  • features_to_vary / permitted_range restrict the search to the taxa you consider modifiable and to plausible value ranges;

  • sparse=True (default) post-processes each counterfactual to a near-minimal set of changes that still flips the prediction, so you get “change these few taxa” instead of “change everything”.

Because DiCE searches for counterfactuals in the model’s input space, pass model, query and background_data in the same feature space the model was trained on (e.g. CLR-transformed features, if the model was fit on CLR-transformed data).

Parameters:
  • model (Any) – A fitted, sklearn-compatible classifier (e.g. a MicrobiomeClassifier or a bare sklearn estimator) exposing predict/predict_proba.

  • query (pd.DataFrame) – Sample(s) to explain, as one or more rows with the same feature columns as background_data.

  • background_data (pd.DataFrame) – Training features (samples x features) used to describe the data distribution DiCE samples from.

  • y (pd.Series, pd.DataFrame, or array-like) – Training targets aligned with background_data.

  • target_column (str, default="outcome") – Name DiCE uses for the outcome column internally. Only needs to differ from the feature names; it is not a column in query.

  • total_CFs (int, default=5) – Number of counterfactuals to generate per query sample.

  • desired_class (str, default="opposite") – Target class for the counterfactuals (“opposite” flips the prediction).

  • features_to_vary (str or list of str, default="all") – Which features DiCE may change. Pass a list to restrict the search to modifiable taxa (e.g. diet-associated genera).

  • permitted_range (dict, optional) – Per-feature {name: [min, max]} bounds constraining counterfactual values to a plausible range.

  • sparse (bool, default=True) – If True, greedily reduce each counterfactual to a near-minimal set of changes that preserves the flipped prediction.

  • class_names (list of str, optional) – Human-readable class labels (indexed by integer class) for the summary.

  • continuous_features (list of str, optional) – Feature names to treat as continuous. Defaults to all columns of background_data (appropriate for abundance / CLR features).

  • method (str, default="genetic") – DiCE search method (“genetic”, “random”, or “kdtree”).

  • backend (str, default="sklearn") – DiCE model backend.

  • return_raw (bool, default=False) – If True, return the raw dice_ml explanation object instead of a CounterfactualResult.

  • **kwargs (Any) – Additional arguments forwarded to dice_ml.Dice.generate_counterfactuals.

Returns:

One result per query sample (a single result if query has one row). Only genuine counterfactuals — those that actually flip the prediction — are kept; DiCE rows that fail to flip are discarded. Each result exposes .changes(), .n_changes, .validity and .summary(). If return_raw=True, the raw DiCE object is returned instead.

Return type:

CounterfactualResult or list of CounterfactualResult

Raises:

ImportError – If the optional explainability extra (dice-ml) is not installed.

Examples

>>> import microfactual as mf
>>> model = mf.MicrobiomeClassifier(preprocessing=None).fit(X_clr, y)
>>> cf = mf.explain_counterfactual(model, X_clr.iloc[[0]], X_clr, y)
>>> print(cf.summary())
>>> cf.changes()

Structured, interpretable counterfactual results.

Wraps the raw DiCE output into an object that answers the questions a user actually has: which taxa changed, by how much, in which direction, and does the counterfactual really flip the model’s prediction?

class microfactual.explainability.result.CounterfactualResult(original, counterfactuals, model, feature_names, class_names=None, raw=None, atol=1e-08)

Bases: object

Interpretable wrapper around a set of counterfactuals for one sample.

Parameters:
  • original (array-like) – The query sample’s feature values.

  • counterfactuals (array-like) – Counterfactual rows (n_cfs x n_features), already sparsified if desired.

  • model (Any) – Fitted classifier used to (re)validate predictions.

  • feature_names (list of str) – Names of the features, in column order.

  • class_names (list of str, optional) – Human-readable class labels, indexed by predicted integer class.

  • raw (Any, optional) – The underlying DiCE explanation object, kept for advanced use.

  • atol (float, default=1e-8) – Tolerance below which a feature is considered unchanged.

changes(cf_index=None)

Return the per-feature changes for one or all counterfactuals.

Parameters:

cf_index (int, optional) – If given, return changes for that single counterfactual. Otherwise return the changes for all counterfactuals stacked, with a cf column identifying each.

Returns:

Columns: cf (omitted when cf_index given), feature, original, counterfactual, delta, direction. Only rows where the feature actually changed are included, sorted by descending absolute change.

Return type:

pd.DataFrame

property n_changes: list[int]

Number of features changed by each counterfactual.

property n_counterfactuals: int

Number of counterfactuals held.

property original_prediction: int

Predicted class for the original sample.

summary()

Return a short human-readable summary of the counterfactuals.

Return type:

str

property validity: float

Fraction of counterfactuals that actually flip the prediction.

visualize_as_dataframe(*args, **kwargs)

Delegate to the underlying DiCE explanation’s visualizer, if present.

Return type:

Any

microfactual.explainability.result.sparsify_counterfactual(original, counterfactual, model, atol=1e-08)

Greedily revert changed features while preserving the flipped prediction.

DiCE (especially the genetic method on continuous features) often perturbs every feature. This reduces a counterfactual to a near-minimal set of changes: changed features are reverted to their original value one at a time, smallest change first, keeping a revert only when the model’s prediction is unchanged. The result is a sparse, actionable counterfactual.

Parameters:
  • original (np.ndarray) – The original sample’s feature values (1D).

  • counterfactual (np.ndarray) – The counterfactual feature values (1D, same order as original).

  • model (Any) – Fitted classifier exposing predict on a 2D array.

  • atol (float, default=1e-8) – Absolute tolerance below which a feature is considered unchanged.

Returns:

A sparsified counterfactual with the same predicted class as the input counterfactual.

Return type:

np.ndarray

Reference-class plausibility helpers for counterfactuals.

Vanilla DiCE can propose counterfactual values far outside anything seen in the data. These helpers (1) derive a plausible value range from a reference class to constrain the search (permitted_range), and (2) score how well a counterfactual moves a sample toward that reference class.

microfactual.explainability.plausibility.counterfactual_concordance(result, X, y, reference_class)

Fraction of changed taxa whose counterfactual moves toward the reference.

For each changed taxon, checks whether the counterfactual’s change is in the same direction as the gap between the sample’s original value and the reference-class median. A high score means the counterfactual shifts the sample toward the reference distribution rather than in some arbitrary model-exploiting direction — a cheap plausibility signal.

Parameters:
  • result (CounterfactualResult) – A result from explain_counterfactual().

  • X (pd.DataFrame) – Feature matrix used to compute the reference median.

  • y (array-like) – Class labels aligned with X.

  • reference_class (Any) – The label value in y to move toward.

Returns:

Concordance in [0, 1], or nan if there are no changes.

Return type:

float

microfactual.explainability.plausibility.plausible_range(X, y, reference_class, *, q=(0.05, 0.95), features=None)

Per-feature [low, high] bounds from a reference class’s quantiles.

Feed the result to explain_counterfactual(..., permitted_range=...) so counterfactuals are confined to values actually observed in the reference (e.g. control) class, rather than extrapolating to implausible extremes.

Parameters:
  • X (pd.DataFrame) – Feature matrix (samples x features), in the model’s input space.

  • y (array-like) – Class labels aligned with X.

  • reference_class (Any) – The label value in y whose distribution defines “plausible”.

  • q (tuple of float, default=(0.05, 0.95)) – Lower/upper quantiles used as the bounds.

  • features (list of str, optional) – Restrict to these features; defaults to all columns of X.

Returns:

{feature: [low, high]} suitable for DiCE’s permitted_range.

Return type:

dict

Visualization

Visualization module for microfactual.

microfactual.visualization.explore(data, abundance_cutoff=1e-06, prevalence_cutoff=0.01, figsize=(16, 4))

Render a cutoff-diagnostics panel for a microbiome dataset.

Combines the abundance histogram, prevalence histogram, and the joint prevalence-vs-abundance scatter into one figure, all sharing the proposed AbundanceFilter / PrevalenceFilter cutoffs, so you can eyeball whether the defaults suit your data before fitting a model.

Parameters:
  • data (MicrobiomeDataset or pd.DataFrame) – Data to summarise (a MicrobiomeDataset or a features x samples abundance DataFrame).

  • abundance_cutoff (float, optional) – Proposed abundance cutoff (matches AbundanceFilter(min_abundance=...)).

  • prevalence_cutoff (float, optional) – Proposed prevalence cutoff (matches PrevalenceFilter(min_prevalence=...)).

  • figsize (tuple of float, default=(16, 4)) – Figure size in inches.

Returns:

The assembled 1x3 panel figure.

Return type:

matplotlib.figure.Figure

microfactual.visualization.plot_abundance_histogram(data, abundance_cutoff=1e-06, ax=None, bins=50)

Histogram of per-taxon mean abundance on a log10 axis.

Microbiome abundances span many orders of magnitude and the distribution is often bimodal; the trough is a natural place to set the abundance cutoff.

Parameters:
  • data (MicrobiomeDataset or pd.DataFrame) – Data to summarise (see _get_abundance()).

  • abundance_cutoff (float, optional) – If given, draw a vertical line at this abundance and annotate how many taxa fall at or above it.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on; a new figure/axes is created if omitted.

  • bins (int, default=50) – Number of histogram bins.

Returns:

The axes containing the plot.

Return type:

matplotlib.axes.Axes

microfactual.visualization.plot_confusion_matrix(y_true, y_pred, labels=None, title='Confusion Matrix', cmap='Blues')

Plot confusion matrix.

Parameters:
  • y_true (array-like) – True class labels.

  • y_pred (array-like) – Predicted class labels.

  • labels (list of str, optional) – Display labels for classes.

  • title (str, default="Confusion Matrix") – Plot title.

  • cmap (str, default="Blues") – Colormap for the matrix.

Returns:

fig – The matplotlib figure object.

Return type:

matplotlib.figure.Figure

Examples

>>> fig = plot_confusion_matrix(y_test, y_pred, labels=["Healthy", "Disease"])
microfactual.visualization.plot_counterfactual_heatmap(result, X, y, *, reference_class, comparison_class=None, cf_index=0, top_n=15, ax=None)

Heatmap of a counterfactual against class-reference distributions.

For the taxa a counterfactual changes, shows the sample’s original value, the counterfactual value, and the class medians — all expressed in reference-class standard deviations (0 = reference-class centre). This makes it easy to see whether the counterfactual moves the sample toward the reference (e.g. control) distribution, and whether it overshoots into implausible territory. The title reports the concordance-with-reference score.

Parameters:
  • result (CounterfactualResult) – A result from explain_counterfactual().

  • X (pd.DataFrame) – Feature matrix (samples x features) used to compute class references.

  • y (array-like) – Class labels aligned with X.

  • reference_class (Any) – Label value in y to treat as the reference (e.g. the control/healthy class the counterfactual should move toward).

  • comparison_class (Any, optional) – A second class whose median is shown for contrast (e.g. the disease class). If None, only the reference median is shown.

  • cf_index (int, default=0) – Which counterfactual (row) of result to display.

  • top_n (int, optional) – Show only the top_n taxa with the largest absolute change. None shows all changed taxa.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on; a new figure/axes is created if omitted.

Returns:

The axes containing the heatmap.

Return type:

matplotlib.axes.Axes

microfactual.visualization.plot_feature_importance(importance, feature_names=None, top_n=None, title='Feature Importance')

Plot feature importance as horizontal bar chart.

Parameters:
  • importance (pd.Series, np.ndarray, or model with feature_importances_) – Feature importance scores. Can be: - pd.Series with feature names as index - np.ndarray (requires feature_names) - Model object with a feature_importances_ attribute

  • feature_names (list of str, optional) – Feature names (required if importance is array or model).

  • top_n (int, optional) – Show only top N most important features.

  • title (str, default="Feature Importance") – Plot title.

Returns:

fig – The matplotlib figure object.

Return type:

matplotlib.figure.Figure

Examples

>>> fig = plot_feature_importance(model.feature_importances_, feature_names)
>>> fig = plot_feature_importance(importance_series, top_n=20)
microfactual.visualization.plot_prevalence_abundance(data, abundance_cutoff=1e-06, prevalence_cutoff=0.01, ax=None)

Joint scatter of per-taxon prevalence vs. mean abundance.

Each point is one taxon. With both cutoffs supplied, the retained region is shaded and the number of surviving taxa is annotated — the clearest single view for choosing both filters together.

Parameters:
  • data (MicrobiomeDataset or pd.DataFrame) – Data to summarise.

  • abundance_cutoff (float, optional) – Abundance threshold; drawn as a vertical line.

  • prevalence_cutoff (float, optional) – Prevalence threshold; drawn as a horizontal line.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on; a new figure/axes is created if omitted.

Returns:

The axes containing the plot.

Return type:

matplotlib.axes.Axes

microfactual.visualization.plot_prevalence_histogram(data, prevalence_cutoff=0.01, ax=None, bins=50)

Histogram of per-taxon prevalence (fraction of samples present).

Prevalence distributions are typically U-shaped (taxa present in almost no samples or almost all). The plot helps place the prevalence cutoff.

Parameters:
  • data (MicrobiomeDataset or pd.DataFrame) – Data to summarise.

  • prevalence_cutoff (float, optional) – If given, draw a vertical line at this prevalence and annotate how many taxa fall at or above it.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on; a new figure/axes is created if omitted.

  • bins (int, default=50) – Number of histogram bins.

Returns:

The axes containing the plot.

Return type:

matplotlib.axes.Axes

microfactual.visualization.plot_roc(y_true, y_proba, title='ROC Curve')

Plot ROC curve with AUC score.

Parameters:
  • y_true (array-like) – True binary labels.

  • y_proba (array-like) – Predicted probabilities for the positive class.

  • title (str, default="ROC Curve") – Plot title.

Returns:

fig – The matplotlib figure object.

Return type:

matplotlib.figure.Figure

Examples

>>> fig = plot_roc(y_test, model.predict_proba(X_test)[:, 1])
>>> fig.savefig("roc.png")

Visualizations for counterfactual explanations.

microfactual.visualization.counterfactual_plots.plot_counterfactual_heatmap(result, X, y, *, reference_class, comparison_class=None, cf_index=0, top_n=15, ax=None)

Heatmap of a counterfactual against class-reference distributions.

For the taxa a counterfactual changes, shows the sample’s original value, the counterfactual value, and the class medians — all expressed in reference-class standard deviations (0 = reference-class centre). This makes it easy to see whether the counterfactual moves the sample toward the reference (e.g. control) distribution, and whether it overshoots into implausible territory. The title reports the concordance-with-reference score.

Parameters:
  • result (CounterfactualResult) – A result from explain_counterfactual().

  • X (pd.DataFrame) – Feature matrix (samples x features) used to compute class references.

  • y (array-like) – Class labels aligned with X.

  • reference_class (Any) – Label value in y to treat as the reference (e.g. the control/healthy class the counterfactual should move toward).

  • comparison_class (Any, optional) – A second class whose median is shown for contrast (e.g. the disease class). If None, only the reference median is shown.

  • cf_index (int, default=0) – Which counterfactual (row) of result to display.

  • top_n (int, optional) – Show only the top_n taxa with the largest absolute change. None shows all changed taxa.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on; a new figure/axes is created if omitted.

Returns:

The axes containing the heatmap.

Return type:

matplotlib.axes.Axes