Skip to content

Commit 4e7942d

Browse files
authored
Merge pull request #94 from igerber/fix/tutorial-notebook-and-skill
Fix tutorial notebook syntax error and clean up metadata
2 parents ff10253 + d8fb598 commit 4e7942d

11 files changed

Lines changed: 507 additions & 1530 deletions

.claude/commands/validate-tutorial.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ The user may provide an optional argument: `$ARGUMENTS`
5555
- Success: "01_basic_did.ipynb - PASSED"
5656
- Failure: Show the error message and which cell failed
5757

58-
4. **Clear outputs** after validation completes (regardless of pass/fail):
58+
4. **Clear outputs and metadata** after validation completes (regardless of pass/fail):
5959
```bash
60-
jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace "docs/tutorials/NOTEBOOK.ipynb"
60+
jupyter nbconvert --ClearOutputPreprocessor.enabled=True --ClearMetadataPreprocessor.enabled=True --inplace "docs/tutorials/NOTEBOOK.ipynb"
6161
```
6262

63-
This ensures notebook outputs are not committed to git.
63+
This ensures notebook outputs and execution metadata (timestamps, execution counts) are not committed to git.
6464

6565
5. **Summary**: After all notebooks complete, show a summary like:
6666
```
@@ -72,7 +72,7 @@ The user may provide an optional argument: `$ARGUMENTS`
7272

7373
## Notes
7474

75-
- Notebooks are executed to validate they work, then outputs are cleared
75+
- Notebooks are executed to validate they work, then outputs and metadata are cleared
7676
- If a notebook fails, continue to the next one (don't stop early)
7777
- The working directory should be the project root
7878
- Some notebooks may take a while to run (especially those with bootstrap)

docs/tutorials/01_basic_did.ipynb

Lines changed: 20 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,7 @@
1919
{
2020
"cell_type": "code",
2121
"execution_count": null,
22-
"metadata": {
23-
"execution": {
24-
"iopub.execute_input": "2026-01-18T18:10:35.801900Z",
25-
"iopub.status.busy": "2026-01-18T18:10:35.801757Z",
26-
"iopub.status.idle": "2026-01-18T18:10:36.233206Z",
27-
"shell.execute_reply": "2026-01-18T18:10:36.232925Z"
28-
}
29-
},
22+
"metadata": {},
3023
"outputs": [],
3124
"source": [
3225
"import numpy as np\n",
@@ -47,14 +40,7 @@
4740
{
4841
"cell_type": "code",
4942
"execution_count": null,
50-
"metadata": {
51-
"execution": {
52-
"iopub.execute_input": "2026-01-18T18:10:36.234607Z",
53-
"iopub.status.busy": "2026-01-18T18:10:36.234517Z",
54-
"iopub.status.idle": "2026-01-18T18:10:36.239917Z",
55-
"shell.execute_reply": "2026-01-18T18:10:36.239725Z"
56-
}
57-
},
43+
"metadata": {},
5844
"outputs": [],
5945
"source": [
6046
"# Generate synthetic DiD data with known ATT of 5.0\n",
@@ -75,14 +61,7 @@
7561
{
7662
"cell_type": "code",
7763
"execution_count": null,
78-
"metadata": {
79-
"execution": {
80-
"iopub.execute_input": "2026-01-18T18:10:36.251493Z",
81-
"iopub.status.busy": "2026-01-18T18:10:36.251420Z",
82-
"iopub.status.idle": "2026-01-18T18:10:36.254312Z",
83-
"shell.execute_reply": "2026-01-18T18:10:36.254088Z"
84-
}
85-
},
64+
"metadata": {},
8665
"outputs": [],
8766
"source": [
8867
"# Examine the data structure\n",
@@ -102,14 +81,7 @@
10281
{
10382
"cell_type": "code",
10483
"execution_count": null,
105-
"metadata": {
106-
"execution": {
107-
"iopub.execute_input": "2026-01-18T18:10:36.255333Z",
108-
"iopub.status.busy": "2026-01-18T18:10:36.255268Z",
109-
"iopub.status.idle": "2026-01-18T18:10:36.257620Z",
110-
"shell.execute_reply": "2026-01-18T18:10:36.257437Z"
111-
}
112-
},
84+
"metadata": {},
11385
"outputs": [],
11486
"source": [
11587
"# Create the estimator\n",
@@ -144,14 +116,7 @@
144116
{
145117
"cell_type": "code",
146118
"execution_count": null,
147-
"metadata": {
148-
"execution": {
149-
"iopub.execute_input": "2026-01-18T18:10:36.258588Z",
150-
"iopub.status.busy": "2026-01-18T18:10:36.258510Z",
151-
"iopub.status.idle": "2026-01-18T18:10:36.260137Z",
152-
"shell.execute_reply": "2026-01-18T18:10:36.259955Z"
153-
}
154-
},
119+
"metadata": {},
155120
"outputs": [],
156121
"source": [
157122
"# Access individual components\n",
@@ -176,14 +141,7 @@
176141
{
177142
"cell_type": "code",
178143
"execution_count": null,
179-
"metadata": {
180-
"execution": {
181-
"iopub.execute_input": "2026-01-18T18:10:36.261002Z",
182-
"iopub.status.busy": "2026-01-18T18:10:36.260952Z",
183-
"iopub.status.idle": "2026-01-18T18:10:36.262794Z",
184-
"shell.execute_reply": "2026-01-18T18:10:36.262624Z"
185-
}
186-
},
144+
"metadata": {},
187145
"outputs": [],
188146
"source": [
189147
"# Using formula interface (R-style)\n",
@@ -199,14 +157,7 @@
199157
{
200158
"cell_type": "code",
201159
"execution_count": null,
202-
"metadata": {
203-
"execution": {
204-
"iopub.execute_input": "2026-01-18T18:10:36.263682Z",
205-
"iopub.status.busy": "2026-01-18T18:10:36.263631Z",
206-
"iopub.status.idle": "2026-01-18T18:10:36.265008Z",
207-
"shell.execute_reply": "2026-01-18T18:10:36.264810Z"
208-
}
209-
},
160+
"metadata": {},
210161
"outputs": [],
211162
"source": [
212163
"# Verify both methods give the same result\n",
@@ -227,14 +178,7 @@
227178
{
228179
"cell_type": "code",
229180
"execution_count": null,
230-
"metadata": {
231-
"execution": {
232-
"iopub.execute_input": "2026-01-18T18:10:36.265866Z",
233-
"iopub.status.busy": "2026-01-18T18:10:36.265814Z",
234-
"iopub.status.idle": "2026-01-18T18:10:36.268138Z",
235-
"shell.execute_reply": "2026-01-18T18:10:36.267940Z"
236-
}
237-
},
181+
"metadata": {},
238182
"outputs": [],
239183
"source": [
240184
"# Add some covariates to our data\n",
@@ -258,14 +202,7 @@
258202
{
259203
"cell_type": "code",
260204
"execution_count": null,
261-
"metadata": {
262-
"execution": {
263-
"iopub.execute_input": "2026-01-18T18:10:36.269011Z",
264-
"iopub.status.busy": "2026-01-18T18:10:36.268965Z",
265-
"iopub.status.idle": "2026-01-18T18:10:36.270317Z",
266-
"shell.execute_reply": "2026-01-18T18:10:36.270123Z"
267-
}
268-
},
205+
"metadata": {},
269206
"outputs": [],
270207
"source": [
271208
"# All coefficient estimates are available\n",
@@ -289,14 +226,7 @@
289226
{
290227
"cell_type": "code",
291228
"execution_count": null,
292-
"metadata": {
293-
"execution": {
294-
"iopub.execute_input": "2026-01-18T18:10:36.271191Z",
295-
"iopub.status.busy": "2026-01-18T18:10:36.271130Z",
296-
"iopub.status.idle": "2026-01-18T18:10:36.274752Z",
297-
"shell.execute_reply": "2026-01-18T18:10:36.274501Z"
298-
}
299-
},
229+
"metadata": {},
300230
"outputs": [],
301231
"source": [
302232
"# Generate data with more structure\n",
@@ -334,14 +264,7 @@
334264
{
335265
"cell_type": "code",
336266
"execution_count": null,
337-
"metadata": {
338-
"execution": {
339-
"iopub.execute_input": "2026-01-18T18:10:36.275657Z",
340-
"iopub.status.busy": "2026-01-18T18:10:36.275605Z",
341-
"iopub.status.idle": "2026-01-18T18:10:36.277635Z",
342-
"shell.execute_reply": "2026-01-18T18:10:36.277443Z"
343-
}
344-
},
267+
"metadata": {},
345268
"outputs": [],
346269
"source": [
347270
"# Using fixed effects with dummy variables\n",
@@ -360,14 +283,7 @@
360283
{
361284
"cell_type": "code",
362285
"execution_count": null,
363-
"metadata": {
364-
"execution": {
365-
"iopub.execute_input": "2026-01-18T18:10:36.278482Z",
366-
"iopub.status.busy": "2026-01-18T18:10:36.278432Z",
367-
"iopub.status.idle": "2026-01-18T18:10:36.280535Z",
368-
"shell.execute_reply": "2026-01-18T18:10:36.280352Z"
369-
}
370-
},
286+
"metadata": {},
371287
"outputs": [],
372288
"source": [
373289
"# Using absorbed fixed effects (within-transformation)\n",
@@ -396,14 +312,7 @@
396312
{
397313
"cell_type": "code",
398314
"execution_count": null,
399-
"metadata": {
400-
"execution": {
401-
"iopub.execute_input": "2026-01-18T18:10:36.281443Z",
402-
"iopub.status.busy": "2026-01-18T18:10:36.281372Z",
403-
"iopub.status.idle": "2026-01-18T18:10:36.284078Z",
404-
"shell.execute_reply": "2026-01-18T18:10:36.283923Z"
405-
}
406-
},
315+
"metadata": {},
407316
"outputs": [],
408317
"source": [
409318
"# Two-Way Fixed Effects estimator\n",
@@ -433,14 +342,7 @@
433342
{
434343
"cell_type": "code",
435344
"execution_count": null,
436-
"metadata": {
437-
"execution": {
438-
"iopub.execute_input": "2026-01-18T18:10:36.285055Z",
439-
"iopub.status.busy": "2026-01-18T18:10:36.284989Z",
440-
"iopub.status.idle": "2026-01-18T18:10:36.287340Z",
441-
"shell.execute_reply": "2026-01-18T18:10:36.287159Z"
442-
}
443-
},
345+
"metadata": {},
444346
"outputs": [],
445347
"source": [
446348
"# Create clustered data\n",
@@ -478,14 +380,7 @@
478380
{
479381
"cell_type": "code",
480382
"execution_count": null,
481-
"metadata": {
482-
"execution": {
483-
"iopub.execute_input": "2026-01-18T18:10:36.288239Z",
484-
"iopub.status.busy": "2026-01-18T18:10:36.288176Z",
485-
"iopub.status.idle": "2026-01-18T18:10:36.290659Z",
486-
"shell.execute_reply": "2026-01-18T18:10:36.290472Z"
487-
}
488-
},
383+
"metadata": {},
489384
"outputs": [],
490385
"source": [
491386
"# Compare standard errors: robust vs cluster-robust\n",
@@ -524,14 +419,7 @@
524419
{
525420
"cell_type": "code",
526421
"execution_count": null,
527-
"metadata": {
528-
"execution": {
529-
"iopub.execute_input": "2026-01-18T18:10:36.291566Z",
530-
"iopub.status.busy": "2026-01-18T18:10:36.291505Z",
531-
"iopub.status.idle": "2026-01-18T18:10:36.346217Z",
532-
"shell.execute_reply": "2026-01-18T18:10:36.346015Z"
533-
}
534-
},
422+
"metadata": {},
535423
"outputs": [],
536424
"source": [
537425
"# Wild cluster bootstrap inference\n",
@@ -556,14 +444,7 @@
556444
{
557445
"cell_type": "code",
558446
"execution_count": null,
559-
"metadata": {
560-
"execution": {
561-
"iopub.execute_input": "2026-01-18T18:10:36.347172Z",
562-
"iopub.status.busy": "2026-01-18T18:10:36.347118Z",
563-
"iopub.status.idle": "2026-01-18T18:10:36.348824Z",
564-
"shell.execute_reply": "2026-01-18T18:10:36.348617Z"
565-
}
566-
},
447+
"metadata": {},
567448
"outputs": [],
568449
"source": [
569450
"# Compare inference methods\n",
@@ -586,14 +467,7 @@
586467
{
587468
"cell_type": "code",
588469
"execution_count": null,
589-
"metadata": {
590-
"execution": {
591-
"iopub.execute_input": "2026-01-18T18:10:36.349842Z",
592-
"iopub.status.busy": "2026-01-18T18:10:36.349787Z",
593-
"iopub.status.idle": "2026-01-18T18:10:36.351291Z",
594-
"shell.execute_reply": "2026-01-18T18:10:36.351112Z"
595-
}
596-
},
470+
"metadata": {},
597471
"outputs": [],
598472
"source": [
599473
"# Export to dictionary\n",
@@ -609,14 +483,7 @@
609483
{
610484
"cell_type": "code",
611485
"execution_count": null,
612-
"metadata": {
613-
"execution": {
614-
"iopub.execute_input": "2026-01-18T18:10:36.352211Z",
615-
"iopub.status.busy": "2026-01-18T18:10:36.352147Z",
616-
"iopub.status.idle": "2026-01-18T18:10:36.355144Z",
617-
"shell.execute_reply": "2026-01-18T18:10:36.354965Z"
618-
}
619-
},
486+
"metadata": {},
620487
"outputs": [],
621488
"source": [
622489
"# Export to DataFrame (useful for combining multiple estimates)\n",
@@ -648,22 +515,8 @@
648515
}
649516
],
650517
"metadata": {
651-
"kernelspec": {
652-
"display_name": "Python 3",
653-
"language": "python",
654-
"name": "python3"
655-
},
656518
"language_info": {
657-
"codemirror_mode": {
658-
"name": "ipython",
659-
"version": 3
660-
},
661-
"file_extension": ".py",
662-
"mimetype": "text/x-python",
663-
"name": "python",
664-
"nbconvert_exporter": "python",
665-
"pygments_lexer": "ipython3",
666-
"version": "3.12.4"
519+
"name": "python"
667520
}
668521
},
669522
"nbformat": 4,

0 commit comments

Comments
 (0)