summaryrefslogtreecommitdiff
path: root/Lib/test/test_statistics.py
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2019-03-06 22:59:40 -0800
committerGitHub <noreply@github.com>2019-03-06 22:59:40 -0800
commit318d537daabf2bd5f781255c7e25bfce260cf227 (patch)
tree05255317e7fd489c1fc22bd4164285e9234d1a11 /Lib/test/test_statistics.py
parente942e7b5c91995ae1ad967ef2c0f116a5d8555de (diff)
downloadcpython-git-318d537daabf2bd5f781255c7e25bfce260cf227.tar.gz
bpo-36169 : Add overlap() method to statistics.NormalDist (GH-12149)
Diffstat (limited to 'Lib/test/test_statistics.py')
-rw-r--r--Lib/test/test_statistics.py62
1 files changed, 62 insertions, 0 deletions
diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py
index 3f14e63c23..132b9823fd 100644
--- a/Lib/test/test_statistics.py
+++ b/Lib/test/test_statistics.py
@@ -2162,6 +2162,68 @@ class TestNormalDist(unittest.TestCase):
self.assertEqual(X.cdf(float('Inf')), 1.0)
self.assertTrue(math.isnan(X.cdf(float('NaN'))))
+ def test_overlap(self):
+ NormalDist = statistics.NormalDist
+
+ # Match examples from Imman and Bradley
+ for X1, X2, published_result in [
+ (NormalDist(0.0, 2.0), NormalDist(1.0, 2.0), 0.80258),
+ (NormalDist(0.0, 1.0), NormalDist(1.0, 2.0), 0.60993),
+ ]:
+ self.assertAlmostEqual(X1.overlap(X2), published_result, places=4)
+ self.assertAlmostEqual(X2.overlap(X1), published_result, places=4)
+
+ # Check against integration of the PDF
+ def overlap_numeric(X, Y, *, steps=8_192, z=5):
+ 'Numerical integration cross-check for overlap() '
+ fsum = math.fsum
+ center = (X.mu + Y.mu) / 2.0
+ width = z * max(X.sigma, Y.sigma)
+ start = center - width
+ dx = 2.0 * width / steps
+ x_arr = [start + i*dx for i in range(steps)]
+ xp = list(map(X.pdf, x_arr))
+ yp = list(map(Y.pdf, x_arr))
+ total = max(fsum(xp), fsum(yp))
+ return fsum(map(min, xp, yp)) / total
+
+ for X1, X2 in [
+ # Examples from Imman and Bradley
+ (NormalDist(0.0, 2.0), NormalDist(1.0, 2.0)),
+ (NormalDist(0.0, 1.0), NormalDist(1.0, 2.0)),
+ # Example from https://www.rasch.org/rmt/rmt101r.htm
+ (NormalDist(0.0, 1.0), NormalDist(1.0, 2.0)),
+ # Gender heights from http://www.usablestats.com/lessons/normal
+ (NormalDist(70, 4), NormalDist(65, 3.5)),
+ # Misc cases with equal standard deviations
+ (NormalDist(100, 15), NormalDist(110, 15)),
+ (NormalDist(-100, 15), NormalDist(110, 15)),
+ (NormalDist(-100, 15), NormalDist(-110, 15)),
+ # Misc cases with unequal standard deviations
+ (NormalDist(100, 12), NormalDist(110, 15)),
+ (NormalDist(100, 12), NormalDist(150, 15)),
+ (NormalDist(100, 12), NormalDist(150, 35)),
+ # Misc cases with small values
+ (NormalDist(1.000, 0.002), NormalDist(1.001, 0.003)),
+ (NormalDist(1.000, 0.002), NormalDist(1.006, 0.0003)),
+ (NormalDist(1.000, 0.002), NormalDist(1.001, 0.099)),
+ ]:
+ self.assertAlmostEqual(X1.overlap(X2), overlap_numeric(X1, X2), places=5)
+ self.assertAlmostEqual(X2.overlap(X1), overlap_numeric(X1, X2), places=5)
+
+ # Error cases
+ X = NormalDist()
+ with self.assertRaises(TypeError):
+ X.overlap() # too few arguments
+ with self.assertRaises(TypeError):
+ X.overlap(X, X) # too may arguments
+ with self.assertRaises(TypeError):
+ X.overlap(None) # right operand not a NormalDist
+ with self.assertRaises(statistics.StatisticsError):
+ X.overlap(NormalDist(1, 0)) # right operand sigma is zero
+ with self.assertRaises(statistics.StatisticsError):
+ NormalDist(1, 0).overlap(X) # left operand sigma is zero
+
def test_properties(self):
X = statistics.NormalDist(100, 15)
self.assertEqual(X.mean, 100)