From 70f027dd22d6522b777d10c250f951e5e416b93a Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Thu, 16 Apr 2020 10:25:14 -0700 Subject: bpo-40290: Add zscore() to statistics.NormalDist. (GH-19547) --- Doc/library/statistics.rst | 10 ++++++++++ Lib/statistics.py | 11 +++++++++++ Lib/test/test_statistics.py | 15 +++++++++++++++ .../next/Library/2020-04-15-16-43-48.bpo-40290.eqCMGJ.rst | 1 + 4 files changed, 37 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2020-04-15-16-43-48.bpo-40290.eqCMGJ.rst diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 026f4aa..38a499a 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -696,6 +696,16 @@ of applications in statistics. Set *n* to 100 for percentiles which gives the 99 cuts points that separate the normal distribution into 100 equal sized groups. + .. method:: NormalDist.zscore(x) + + Compute the + `Standard Score `_ + describing *x* in terms of the number of standard deviations + above or below the mean of the normal distribution: + ``(x - mean) / stdev``. + + .. versionadded:: 3.9 + Instances of :class:`NormalDist` support addition, subtraction, multiplication and division by a constant. These operations are used for translation and scaling. For example: diff --git a/Lib/statistics.py b/Lib/statistics.py index 1e95c0b..9beafb3 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -999,6 +999,17 @@ class NormalDist: x2 = (a - b) / dv return 1.0 - (fabs(Y.cdf(x1) - X.cdf(x1)) + fabs(Y.cdf(x2) - X.cdf(x2))) + def zscore(self, x): + """Compute the Standard Score. (x - mean) / stdev + + Describes *x* in terms of the number of standard deviations + above or below the mean of the normal distribution. + """ + # https://www.statisticshowto.com/probability-and-statistics/z-score/ + if not self._sigma: + raise StatisticsError('zscore() not defined when sigma is zero') + return (x - self._mu) / self._sigma + @property def mean(self): "Arithmetic mean of the normal distribution." diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index a9a427b..0e46a71 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -2602,6 +2602,21 @@ class TestNormalDist: with self.assertRaises(self.module.StatisticsError): NormalDist(1, 0).overlap(X) # left operand sigma is zero + def test_zscore(self): + NormalDist = self.module.NormalDist + X = NormalDist(100, 15) + self.assertEqual(X.zscore(142), 2.8) + self.assertEqual(X.zscore(58), -2.8) + self.assertEqual(X.zscore(100), 0.0) + with self.assertRaises(TypeError): + X.zscore() # too few arguments + with self.assertRaises(TypeError): + X.zscore(1, 1) # too may arguments + with self.assertRaises(TypeError): + X.zscore(None) # non-numeric type + with self.assertRaises(self.module.StatisticsError): + NormalDist(1, 0).zscore(100) # sigma is zero + def test_properties(self): X = self.module.NormalDist(100, 15) self.assertEqual(X.mean, 100) diff --git a/Misc/NEWS.d/next/Library/2020-04-15-16-43-48.bpo-40290.eqCMGJ.rst b/Misc/NEWS.d/next/Library/2020-04-15-16-43-48.bpo-40290.eqCMGJ.rst new file mode 100644 index 0000000..a930cee --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-04-15-16-43-48.bpo-40290.eqCMGJ.rst @@ -0,0 +1 @@ +Added zscore() to statistics.NormalDist(). -- cgit v0.12