Skip to content

DEP: stats.ttest_ind: deprecate random_state and permutation in favor of method; require keywords for most args #21921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Dec 6, 2024

Conversation

mdhaber
Copy link
Contributor

@mdhaber mdhaber commented Nov 21, 2024

Reference issue

Toward gh-21833

What does this implement/fix?

The permutation and random_state arguments of ttest_ind were added in gh-4824 to enable the user to perform a permutation version of the t-test. A standard API for performing resampling versions of tests using a method argument was developed in gh-18227. The SPEC 7 deprecation of the random_state arguments provides some impetus for transitioning from permutation and random_state to method.

This PR makes the following changes to ttest_ind:

  • adds a method argument that allows the user to configure permutation and Monte Carlo versions of the test
  • deprecates permutation and random_state arguments in favor of method
  • deprecates positional use of all arguments of ttest_ind after x and y. The removal of permutation and random_state would also require later arguments (alternative and trim) to become keyword-only, anyway; we might as well make all the optional parameters keyword-only at the same time.

The transition to the new interface is quite simple:

from scipy import stats
... # define variables

# This:
stats.ttest_ind(a, b, 0, True, 'propagate', 9999, rng, 'two-sided', 0)

# becomes
method = stats.PermutationMethod(n_resamples=9999, rng=rng)
stats.ttest_ind(a, b, axis=0, equal_var=True, nan_policy='propagate',
                method=method, trim=0)

@mdhaber mdhaber added scipy.stats maintenance Items related to regular maintenance tasks labels Nov 21, 2024
@github-actions github-actions bot added scipy._lib deprecated Items related to behavior that has been deprecated labels Nov 21, 2024
Copy link
Contributor Author

@mdhaber mdhaber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments to aid the reviewer.

Comment on lines +235 to +236
kwonly_extra_args = set(kwonly_args[:extra_args]) - deprecated_args
args_msg = ", ".join(kwonly_extra_args)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This warns about the deprecated positional use of arguments passed by position. We don't want the deprecated_args (which are completely decorated) to be included in that list; warn about those separately.

Comment on lines +253 to +256
admonition = f"""
.. deprecated:: {version}
Use of argument(s) ``{kwonly_extra_args}`` by position is deprecated; beginning in
SciPy {version}, these will be keyword-only. """
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugly indentation; I know, but it makes it easy to keep Sphinx happy.

(In the following, note that the argument `permutations` itself is
deprecated, but a nearly identical test may be performed by creating
an instance of `scipy.stats.PermutationMethod` with ``n_resamples=permutuations``
and passing it as the `method` argument.)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could just remove all of this temporarily. We will be writing an interactive notebook tutorial for permutation and Monte Carlo versions of the t-test (like https://scipy.github.io/devdocs/tutorial/stats/hypothesis_normaltest.html) shortly, and we will link to that from here.

# here in permutation_test.
@pytest.mark.parametrize('permutations', (30, 1e9))
@pytest.mark.parametrize('axis', (0, 1, 2))
def test_against_permutation_ttest(self, alternative, permutations, axis):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tested scipy.stats.permutation_test against using the permutations argument of ttest_ind, but there are other, stronger tests now.

@@ -5343,6 +5343,7 @@ def test_ttest_ind_scalar():
assert np.isnan(p)


@pytest.mark.filterwarnings("ignore:Arguments...:DeprecationWarning")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We test for the warning about deprecated permutations below.

I suppose there are no tests for deprecated positional use, but I assume the _deprecate_positional_args decorator was already tested, so I'm just testing the new part.


@pytest.mark.parametrize("alternative", ['less', 'greater', 'two-sided'])
@pytest.mark.parametrize("shape", [(12,), (2, 12)])
def test_monte_carlo_method(self, alternative, shape):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried combining this with the previous test, but this is really more readable.

We could also consider removing the Monte Carlo version of the test entirely during this (complicated) transition period, just to keep things a little simpler.

@mdhaber mdhaber mentioned this pull request Nov 21, 2024
50 tasks
@lucascolley lucascolley changed the title DEP: stats.ttest_ind: deprecate random_state and permutation in favor of method; require keywords for most args DEP: stats.ttest_ind: deprecate random_state and permutation in favor of method; require keywords for most args Nov 21, 2024
@j-bowhay
Copy link
Member

Could you write a post to the forum regarding the deprecation?

if not isinstance(method, PermutationMethod | MonteCarloMethod | None):
message = ("`method` must be an instance of `PermutationMethod`, an instance "
"of `MonteCarloMethod`, or None (default).")
raise ValueError(message)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a test for this


if not is_numpy(xp) and method is not None:
message = "Use of resampling methods is compatible only with NumPy arrays."
raise NotImplementedError(message)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this

stats.ttest_ind([1, 2], [2, 3], trim=.2, permutations=2)
message = "Arguments {'permutations'} are deprecated, whether..."
with pytest.warns(DeprecationWarning, match=message):
stats.ttest_ind([1, 2], [2, 3], trim=.2, permutations=2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we test randomatate also raises a warning

Copy link
Member

@j-bowhay j-bowhay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments about tests but otherwise looks good

assert_allclose(res.pvalue, ref.pvalue, rtol=6e-2)

def test_resampling_input_validation(self):
rng = np.random.default_rng(328924823)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will commit with [lint only] if the rest looks good.

Suggested change
rng = np.random.default_rng(328924823)

Copy link
Member

@j-bowhay j-bowhay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Can you make sure this makes it into the release notes

@j-bowhay j-bowhay added this to the 1.15.0 milestone Dec 6, 2024
@j-bowhay j-bowhay merged commit abdadb7 into scipy:main Dec 6, 2024
37 checks passed
@tylerjereddy tylerjereddy added the needs-release-note a maintainer should add a release note written by a reviewer/author to the wiki label Dec 6, 2024
@mdhaber
Copy link
Contributor Author

mdhaber commented Dec 6, 2024

Done. Thanks @j-bowhay!

@lucascolley lucascolley removed the needs-release-note a maintainer should add a release note written by a reviewer/author to the wiki label Jun 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deprecated Items related to behavior that has been deprecated maintenance Items related to regular maintenance tasks scipy._lib scipy.stats
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants