(self)
| 2355 | |
| 2356 | @support.requires_resource('cpu') |
| 2357 | def test_kde(self): |
| 2358 | kde = statistics.kde |
| 2359 | StatisticsError = statistics.StatisticsError |
| 2360 | |
| 2361 | kernels = ['normal', 'gauss', 'logistic', 'sigmoid', 'rectangular', |
| 2362 | 'uniform', 'triangular', 'parabolic', 'epanechnikov', |
| 2363 | 'quartic', 'biweight', 'triweight', 'cosine'] |
| 2364 | |
| 2365 | sample = [-2.1, -1.3, -0.4, 1.9, 5.1, 6.2] |
| 2366 | |
| 2367 | # The approximate integral of a PDF should be close to 1.0 |
| 2368 | |
| 2369 | def integrate(func, low, high, steps=10_000): |
| 2370 | "Numeric approximation of a definite function integral." |
| 2371 | dx = (high - low) / steps |
| 2372 | midpoints = (low + (i + 1/2) * dx for i in range(steps)) |
| 2373 | return sum(map(func, midpoints)) * dx |
| 2374 | |
| 2375 | for kernel in kernels: |
| 2376 | with self.subTest(kernel=kernel): |
| 2377 | f_hat = kde(sample, h=1.5, kernel=kernel) |
| 2378 | area = integrate(f_hat, -20, 20) |
| 2379 | self.assertAlmostEqual(area, 1.0, places=4) |
| 2380 | |
| 2381 | # Check CDF against an integral of the PDF |
| 2382 | |
| 2383 | data = [3, 5, 10, 12] |
| 2384 | h = 2.3 |
| 2385 | x = 10.5 |
| 2386 | for kernel in kernels: |
| 2387 | with self.subTest(kernel=kernel): |
| 2388 | cdf = kde(data, h, kernel, cumulative=True) |
| 2389 | f_hat = kde(data, h, kernel) |
| 2390 | area = integrate(f_hat, -20, x, 100_000) |
| 2391 | self.assertAlmostEqual(cdf(x), area, places=4) |
| 2392 | |
| 2393 | # Check error cases |
| 2394 | |
| 2395 | with self.assertRaises(StatisticsError): |
| 2396 | kde([], h=1.0) # Empty dataset |
| 2397 | with self.assertRaises(TypeError): |
| 2398 | kde(['abc', 'def'], 1.5) # Non-numeric data |
| 2399 | with self.assertRaises(TypeError): |
| 2400 | kde(iter(sample), 1.5) # Data is not a sequence |
| 2401 | with self.assertRaises(StatisticsError): |
| 2402 | kde(sample, h=0.0) # Zero bandwidth |
| 2403 | with self.assertRaises(StatisticsError): |
| 2404 | kde(sample, h=-1.0) # Negative bandwidth |
| 2405 | with self.assertRaises(TypeError): |
| 2406 | kde(sample, h='str') # Wrong bandwidth type |
| 2407 | with self.assertRaises(StatisticsError): |
| 2408 | kde(sample, h=1.0, kernel='bogus') # Invalid kernel |
| 2409 | with self.assertRaises(TypeError): |
| 2410 | kde(sample, 1.0, 'gauss', True) # Positional cumulative argument |
| 2411 | |
| 2412 | # Test name and docstring of the generated function |
| 2413 | |
| 2414 | h = 1.5 |
nothing calls this directly
no test coverage detected