mantispy.pp.feature_select_chatterjee

mantispy.pp.feature_select_chatterjee#

mantispy.pp.feature_select_chatterjee(adata, by='Metadata_Perturbation', threshold=0.1, m=1, seed=0, min_finite=40, key_added='selected_chatterjee', copy=False)[source]#

Keep features whose values depend on the group, monotonically or otherwise.

Parameters:
  • adata (AnnData) – Object to select features on.

  • by (str (default: 'Metadata_Perturbation')) – obs column the features are tested against.

  • threshold (float (default: 0.1)) – Keep features scoring above this. xi is near zero under independence and approaches one when the feature is a deterministic function of the group, so the threshold is comparable across datasets in a way a correlation cutoff is not.

  • m (int (default: 1)) – Right nearest neighbors [Lin and Han, 2022]. m=1 is the coefficient of Chatterjee [2020] up to a term of order 1/n; larger values lower the noise floor without changing what the statistic converges to.

  • seed (int (default: 0)) – Seed for breaking ties between rows of the same group.

  • min_finite (int (default: 40)) – Fewest finite values a feature may be scored on. A feature measured fewer times than this scores NaN, which is above no threshold and so is never selected.

  • key_added (str (default: 'selected_chatterjee')) – Name of the boolean var column written.

  • copy (bool (default: False)) – Return a modified copy instead of mutating in place.

Return type:

AnnData | None

Returns:

None, or the modified copy. Writes var[key_added] and the statistic itself to var["chatterjee_xi"], which is NaN for a feature that is constant or too sparsely measured to score.

Raises:

ValueError – If by has a single group, so that no feature can depend on it.

Notes

Run it after feature_select(), which drops redundant or unmeasurable features; this keeps the features that carry information about the perturbation. Subset with mt.pp.subset_features(adata, key="selected_chatterjee").

A feature is scored on the rows where it was measured, so one that is missing in a whole group is scored against the groups that do have it rather than against the pattern of what is missing.

xi reaches one only for a noiseless function of the group, so real values are much lower and the default threshold of 0.1 is permissive. Check the distribution in var["chatterjee_xi"] before relying on a fixed cutoff.

With shuffled group labels xi collapses toward zero while the real values barely change, so the score reflects dependence on the group rather than noise. m=1 is the default because the threshold was calibrated there. scmorph uses m=5, and on input free of ties the two implementations agree to 1e-9. scmorph breaks ties in y at random, so on tied input the two differ.