Skip to content

Commit b03dcd4

Browse files
Auto-sync ecc-statistics + regenerate _toc.yml
1 parent 3adf64c commit b03dcd4

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

ecc-statistics/confidence_interval/.OTTER_LOG

Whitespace-only changes.
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
"""
2+
Otter Grader utilities for the Confidence Interval notebook.
3+
Run run_tests(globals()) from the notebook after completing the exercises.
4+
"""
5+
6+
import numpy as np
7+
from scipy import stats
8+
import otter
9+
10+
grader = otter.Notebook()
11+
12+
13+
def run_tests(env):
14+
"""
15+
Run all exercise tests using variables from the notebook namespace.
16+
Call from the notebook as: run_tests(globals())
17+
"""
18+
print("Running tests...\n")
19+
20+
try:
21+
_test_exercise1(env)
22+
print("Exercise 1: ✅ Passed")
23+
except Exception as e:
24+
print(f"Exercise 1: ❌ {e}")
25+
26+
try:
27+
_test_exercise2(env)
28+
print("Exercise 2: ✅ Passed")
29+
except Exception as e:
30+
print(f"Exercise 2: ❌ {e}")
31+
32+
try:
33+
_test_exercise3(env)
34+
print("Exercise 3: ✅ Passed")
35+
except Exception as e:
36+
print(f"Exercise 3: ❌ {e}")
37+
38+
print("\nAll tests completed. Great work!")
39+
40+
41+
def _test_exercise1(env):
42+
"""Check z, ci_lower, ci_upper for the 95% CI formula."""
43+
z = env.get("z")
44+
ci_lower = env.get("ci_lower")
45+
ci_upper = env.get("ci_upper")
46+
n = env.get("n")
47+
sample_mean = env.get("sample_mean")
48+
sample_std = env.get("sample_std")
49+
50+
if z is None or ci_lower is None or ci_upper is None:
51+
raise AssertionError("Define z, ci_lower, and ci_upper in the Exercise 1 cell.")
52+
53+
if n is None or sample_mean is None or sample_std is None:
54+
raise AssertionError("Run the earlier cells that define n, sample_mean, and sample_std.")
55+
56+
# Expected z for 95% two-tailed
57+
alpha = 0.05
58+
expected_z = stats.norm.ppf(1 - alpha / 2)
59+
if not np.isclose(z, expected_z, atol=1e-5):
60+
raise AssertionError(
61+
f"z should be the 97.5% quantile of the standard normal (about {expected_z:.4f}). "
62+
"Use stats.norm.ppf(1 - alpha/2)."
63+
)
64+
65+
standard_error = sample_std / np.sqrt(n)
66+
expected_lower = sample_mean - z * standard_error
67+
expected_upper = sample_mean + z * standard_error
68+
69+
if not np.isclose(ci_lower, expected_lower, atol=1e-5):
70+
raise AssertionError("ci_lower should equal sample_mean - z * standard_error.")
71+
if not np.isclose(ci_upper, expected_upper, atol=1e-5):
72+
raise AssertionError("ci_upper should equal sample_mean + z * standard_error.")
73+
74+
75+
def _test_exercise2(env):
76+
"""Check bootstrap_mean output and 95% bootstrap CI percentiles."""
77+
boot_means = env.get("boot_means")
78+
boot_ci_lower = env.get("boot_ci_lower")
79+
boot_ci_upper = env.get("boot_ci_upper")
80+
81+
if boot_means is None:
82+
raise AssertionError("Define boot_means by calling bootstrap_mean(sample, reps=5000).")
83+
if boot_ci_lower is None or boot_ci_upper is None:
84+
raise AssertionError("Define boot_ci_lower and boot_ci_upper using np.percentile.")
85+
86+
if len(boot_means) != 5000:
87+
raise AssertionError("boot_means should have 5000 bootstrap sample means.")
88+
89+
expected_lower, expected_upper = np.percentile(boot_means, [2.5, 97.5])
90+
if not np.isclose(boot_ci_lower, expected_lower, atol=1e-5):
91+
raise AssertionError(
92+
"boot_ci_lower should be the 2.5th percentile of boot_means. "
93+
"Use np.percentile(boot_means, [2.5, 97.5])."
94+
)
95+
if not np.isclose(boot_ci_upper, expected_upper, atol=1e-5):
96+
raise AssertionError(
97+
"boot_ci_upper should be the 97.5th percentile of boot_means. "
98+
"Use np.percentile(boot_means, [2.5, 97.5])."
99+
)
100+
if boot_ci_lower >= boot_ci_upper:
101+
raise AssertionError("boot_ci_lower should be less than boot_ci_upper.")
102+
103+
104+
def _test_exercise3(env):
105+
"""Check bootstrap CI for the mean drop."""
106+
ci_drop_lower = env.get("ci_drop_lower")
107+
ci_drop_upper = env.get("ci_drop_upper")
108+
boot_drop_means = env.get("boot_drop_means")
109+
110+
if boot_drop_means is None:
111+
raise AssertionError("Define boot_drop_means by calling bootstrap_mean(drop, reps=5000).")
112+
if ci_drop_lower is None or ci_drop_upper is None:
113+
raise AssertionError("Define ci_drop_lower and ci_drop_upper using np.percentile.")
114+
115+
expected_lower, expected_upper = np.percentile(boot_drop_means, [2.5, 97.5])
116+
if not np.isclose(ci_drop_lower, expected_lower, atol=1e-5):
117+
raise AssertionError(
118+
"ci_drop_lower should be the 2.5th percentile of boot_drop_means. "
119+
"Use np.percentile(boot_drop_means, [2.5, 97.5])."
120+
)
121+
if not np.isclose(ci_drop_upper, expected_upper, atol=1e-5):
122+
raise AssertionError(
123+
"ci_drop_upper should be the 97.5th percentile of boot_drop_means. "
124+
"Use np.percentile(boot_drop_means, [2.5, 97.5])."
125+
)
126+
if ci_drop_lower >= ci_drop_upper:
127+
raise AssertionError("ci_drop_lower should be less than ci_drop_upper.")

0 commit comments

Comments
 (0)