From a9f66b2925f7d9aee4e38e877367ed156b5ae3e3 Mon Sep 17 00:00:00 2001 From: Daniel Danis Date: Wed, 4 Sep 2024 13:02:41 +0200 Subject: [PATCH 1/2] Add `TTestStatistic`. --- src/gpsea/analysis/pscore/stats/__init__.py | 4 +- src/gpsea/analysis/pscore/stats/_stats.py | 26 +++++++++- tests/analysis/pscore/test_stats.py | 54 +++++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 tests/analysis/pscore/test_stats.py diff --git a/src/gpsea/analysis/pscore/stats/__init__.py b/src/gpsea/analysis/pscore/stats/__init__.py index e46bfb5e4..0d3956fad 100644 --- a/src/gpsea/analysis/pscore/stats/__init__.py +++ b/src/gpsea/analysis/pscore/stats/__init__.py @@ -1,7 +1,7 @@ from ._stats import PhenotypeScoreStatistic -from ._stats import MannWhitneyStatistic +from ._stats import MannWhitneyStatistic, TTestStatistic __all__ = [ 'PhenotypeScoreStatistic', - 'MannWhitneyStatistic', + 'MannWhitneyStatistic', 'TTestStatistic', ] diff --git a/src/gpsea/analysis/pscore/stats/_stats.py b/src/gpsea/analysis/pscore/stats/_stats.py index 01cfa4d92..80f09fa48 100644 --- a/src/gpsea/analysis/pscore/stats/_stats.py +++ b/src/gpsea/analysis/pscore/stats/_stats.py @@ -1,7 +1,7 @@ import abc import typing -from scipy.stats import mannwhitneyu +from scipy.stats import mannwhitneyu, ttest_ind class PhenotypeScoreStatistic(metaclass=abc.ABCMeta): @@ -42,3 +42,27 @@ def compute_pval( ) return pval + + +class TTestStatistic(PhenotypeScoreStatistic): + """ + `TTestStatistic` is a wrapper around SciPy's + :func:`~scipy.stats.ttest_ind` function to apply + T test on 2 phenotype scores. + + See :ref:`phenotype-score-stats` for an example usage. + """ + + def compute_pval( + self, + scores: typing.Collection[typing.Sequence[float]], + ) -> float: + assert len(scores) == 2, 'T test only supports 2 categories at this time' + + x, y = scores + res = ttest_ind( + a=x, b=y, + alternative='two-sided', + ) + + return res.pvalue diff --git a/tests/analysis/pscore/test_stats.py b/tests/analysis/pscore/test_stats.py new file mode 100644 index 000000000..42fdd2ba6 --- /dev/null +++ b/tests/analysis/pscore/test_stats.py @@ -0,0 +1,54 @@ +import typing +import pytest + +from gpsea.analysis.pscore.stats import MannWhitneyStatistic, TTestStatistic + + +class TestMannWhitneyStatistic: + + @pytest.fixture(scope='class') + def statistic(self) -> MannWhitneyStatistic: + return MannWhitneyStatistic() + + @pytest.mark.parametrize( + 'x, y, expected', + [ + ((1., 2., 3., ), (1., 2., 3., ), 1.), + ((11., 15, 8., 12.,), (4., 2., 3., 3.5, 4.,), 0.01945103333136247), + ] + ) + def test_compute_pval( + self, + statistic: MannWhitneyStatistic, + x: typing.Sequence[float], + y: typing.Sequence[float], + expected: float, + ): + actual = statistic.compute_pval((x, y)) + + assert actual == pytest.approx(expected) + + +class TestTTestStatistic: + + @pytest.fixture(scope='class') + def statistic(self) -> TTestStatistic: + return TTestStatistic() + + @pytest.mark.parametrize( + 'x, y, expected', + [ + ((1., 2., 3., ), (1., 2., 3., ), 1.), + ((11., 15, 8., 12.,), (4., 2., 3., 3.5, 4.,), 0.0004749950471148506), + ] + ) + def test_compute_pval( + self, + statistic: TTestStatistic, + x: typing.Sequence[float], + y: typing.Sequence[float], + expected: float, + ): + actual = statistic.compute_pval((x, y)) + + assert actual == pytest.approx(expected) From cda263f6a31443aa4c187a279c6a71dbfee41ceb Mon Sep 17 00:00:00 2001 From: Daniel Danis Date: Wed, 4 Sep 2024 13:08:42 +0200 Subject: [PATCH 2/2] Mention the `pscore.stats` module in the docs. --- docs/user-guide/stats.rst | 6 ++++++ src/gpsea/analysis/pscore/stats/_stats.py | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/user-guide/stats.rst b/docs/user-guide/stats.rst index 5a8717f3b..55757ef30 100644 --- a/docs/user-guide/stats.rst +++ b/docs/user-guide/stats.rst @@ -463,6 +463,12 @@ We will use :ref:`mann-whitney-u-test` as described above. >>> score_statistic = MannWhitneyStatistic() +.. tip:: + + See :mod:`gpsea.analysis.pscore.stats` module for more statistical tests available + for using with phenotype scores. + + **Final analysis** We will put the final analysis together into :class:`~gpsea.analysis.pscore.PhenotypeScoreAnalysis`. diff --git a/src/gpsea/analysis/pscore/stats/_stats.py b/src/gpsea/analysis/pscore/stats/_stats.py index 80f09fa48..7a520e84c 100644 --- a/src/gpsea/analysis/pscore/stats/_stats.py +++ b/src/gpsea/analysis/pscore/stats/_stats.py @@ -49,8 +49,6 @@ class TTestStatistic(PhenotypeScoreStatistic): `TTestStatistic` is a wrapper around SciPy's :func:`~scipy.stats.ttest_ind` function to apply T test on 2 phenotype scores. - - See :ref:`phenotype-score-stats` for an example usage. """ def compute_pval(