ltc-paper-scripts 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. ltc_paper_scripts/README.md +87 -0
  2. ltc_paper_scripts/TICK_ALGORITHM_LICENSE.txt +26 -0
  3. ltc_paper_scripts/build_latex.py +293 -0
  4. ltc_paper_scripts/data/codex_synthetic/new_release_preview.xlsx +0 -0
  5. ltc_paper_scripts/exhibit_selection.py +52 -0
  6. ltc_paper_scripts/figure_ticks.py +51 -0
  7. ltc_paper_scripts/fonts/DejaVuSans-Bold.ttf +0 -0
  8. ltc_paper_scripts/fonts/DejaVuSans.ttf +0 -0
  9. ltc_paper_scripts/fonts/LICENSE.txt +96 -0
  10. ltc_paper_scripts/latex_figures.py +250 -0
  11. ltc_paper_scripts/latex_requirements.txt +4 -0
  12. ltc_paper_scripts/latex_source/outputs/tables/output/age25_earnings_table.tex +38 -0
  13. ltc_paper_scripts/latex_source/outputs/tables/output/balance_table.tex +54 -0
  14. ltc_paper_scripts/latex_source/outputs/tables/output/college_data_comparison_table.tex +20 -0
  15. ltc_paper_scripts/latex_source/outputs/tables/output/college_enrollment_completion_table.tex +31 -0
  16. ltc_paper_scripts/latex_source/outputs/tables/output/college_heterogeneity_table.tex +36 -0
  17. ltc_paper_scripts/latex_source/outputs/tables/output/college_mediation_additional_specs_table.tex +30 -0
  18. ltc_paper_scripts/latex_source/outputs/tables/output/college_test_score_mediation_table.tex +18 -0
  19. ltc_paper_scripts/latex_source/outputs/tables/output/earnings_heterogeneity_table.tex +54 -0
  20. ltc_paper_scripts/latex_source/outputs/tables/output/earnings_robustness_table.tex +29 -0
  21. ltc_paper_scripts/latex_source/outputs/tables/output/earnings_threshold_table.tex +27 -0
  22. ltc_paper_scripts/latex_source/outputs/tables/output/other_mediators_table.tex +31 -0
  23. ltc_paper_scripts/latex_source/outputs/tables/output/peer_family_comparisons_table.tex +20 -0
  24. ltc_paper_scripts/latex_source/outputs/tables/output/summary_statistics_table.tex +60 -0
  25. ltc_paper_scripts/latex_source/paper/appendix.tex +138 -0
  26. ltc_paper_scripts/latex_source/paper/preamble.tex +502 -0
  27. ltc_paper_scripts/latex_source/paper/tables-and-figures.tex +147 -0
  28. ltc_paper_scripts/mappings.py +328 -0
  29. ltc_paper_scripts/paths.py +23 -0
  30. ltc_paper_scripts/run_latex.sh +4 -0
  31. ltc_paper_scripts/split_inputs.py +163 -0
  32. ltc_paper_scripts/table_bindings.json +4084 -0
  33. ltc_paper_scripts-0.1.0.dist-info/METADATA +94 -0
  34. ltc_paper_scripts-0.1.0.dist-info/RECORD +35 -0
  35. ltc_paper_scripts-0.1.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,250 @@
1
+ # --- Import necessary packages ---
2
+ import math
3
+ import os
4
+ from pathlib import Path
5
+ from reportlab.pdfgen import canvas
6
+ from reportlab.lib.colors import black, HexColor
7
+ from reportlab.pdfbase import pdfmetrics
8
+ from reportlab.pdfbase.ttfonts import TTFont
9
+ from figure_ticks import extended_breaks
10
+
11
+ # Port of charter-schools/code/r/{constants,helpers}.R: same colors, physical
12
+ # canvas sizes, discrete scales, cropped bar axes, centered CIs and gain brackets.
13
+ # Prefer the manuscript font where installed. The open fallback ships with the
14
+ # package; proprietary Office/Windows font files are read locally, not copied.
15
+ BLUE = HexColor('#29B6A4')
16
+ ORANGE = HexColor('#FAA523')
17
+ GRAY = HexColor('#999999')
18
+ FONT, BOLD = 'PaperSans', 'PaperSans-Bold'
19
+ font_root=Path(__file__).parent/'fonts'
20
+ office_fonts=Path('/Applications/Microsoft Word.app/Contents/Resources/DFonts')
21
+ windows_fonts=Path(os.environ.get('WINDIR','C:/Windows'))/'Fonts'
22
+ font_pairs=[
23
+ (font_root/'Lucida Sans.ttf',font_root/'Lucida Sans Demibold Roman.ttf'),
24
+ (office_fonts/'Lucida Sans.ttf',office_fonts/'Lucida Sans Demibold Roman.ttf'),
25
+ (windows_fonts/'LSANS.TTF',windows_fonts/'LSANSD.TTF'),
26
+ (font_root/'DejaVuSans.ttf',font_root/'DejaVuSans-Bold.ttf'),
27
+ ]
28
+ regular,bold=next(pair for pair in font_pairs if all(p.is_file() for p in pair))
29
+ for name,path in [(FONT,regular),(BOLD,bold)]:pdfmetrics.registerFont(TTFont(name,str(path)))
30
+
31
+ FIGURE_EXHIBITS = {
32
+ 'f1_bars':'earnings-early-adulthood', 'f1_observed':'earnings-early-adulthood',
33
+ 'f1_surrogate':'earnings-early-adulthood', 'f2':'earnings-distribution',
34
+ 'f3_attendance':'college-attendance-completion', 'f3_completion':'college-attendance-completion',
35
+ 'a2':'appendix-college-by-age-placeholder', 'a3_networks':'appendix-cmo-leave-one-out',
36
+ 'a3_baseline':'appendix-cmo-leave-one-out', 'a4_observed':'appendix-earnings-by-age-firm-chars',
37
+ 'a4_surrogate':'appendix-earnings-by-age-firm-chars',
38
+ }
39
+
40
+
41
+ def label(c, x, y, text, size=22, align='center', bold=False, color=black):
42
+ c.setFillColor(color); c.setFont(BOLD if bold else FONT,size)
43
+ method = {'center':c.drawCentredString,'left':c.drawString,'right':c.drawRightString}[align]
44
+ method(x,y,text)
45
+
46
+
47
+ def vertical_title(c, x, y, text):
48
+ c.saveState(); c.translate(x,y); c.rotate(90)
49
+ lines=text.split('\n')
50
+ for i,line in enumerate(lines):label(c,0,(len(lines)-1)*14-i*28,line,size=26)
51
+ c.restoreState()
52
+
53
+
54
+ def axes(c, left, bottom, right, top, y, ticks, formatter):
55
+ c.setStrokeColor(black); c.setLineWidth(1.067); c.setDash([])
56
+ c.line(left,bottom,right,bottom); c.line(left,bottom,left,top)
57
+ for tick in ticks:
58
+ c.line(left-8,y(tick),left,y(tick))
59
+ label(c,left-13,y(tick)-8,formatter(tick),align='right')
60
+
61
+
62
+ def make_figures(data, figures, folder):
63
+ folder.mkdir(parents=True, exist_ok=True)
64
+ audit = {}
65
+ for name, series, filename, ylabel in [
66
+ ('f1', [('f1_observed', BLUE, 'Observed Earnings'), ('f1_surrogate', ORANGE, 'Surrogate Index Prediction')], 'earnings_by_age.pdf', 'Local Average Treatment Effect on\nEarnings'),
67
+ ('a2', [('a2', BLUE, None)], 'college_attendance_by_age.pdf', 'Local Average Treatment Effect on\nCollege Attendance'),
68
+ ('a4', [('a4_observed', BLUE, 'Observed Earnings'), ('a4_surrogate', ORANGE, 'Firm-Characteristics Surrogate')], 'firm_surrogate_by_age.pdf', 'Local Average Treatment Effect on\nEarnings'),
69
+ ]:
70
+ if not all(key in figures for key, _, _ in series):continue
71
+ prepared=[]
72
+ for key,color,legend in series:
73
+ points=[]
74
+ for b in figures[key]:
75
+ coef=data.value(dict(b,field='coef'));se=data.value(dict(b,field='se'))
76
+ if coef is None or se is None:
77
+ raise ValueError(f'{key}, age {b["age"]}: supply the coefficient and standard error in the mapped workbook.')
78
+ points.append((b['age'],coef,se))
79
+ if not points or len({p[0] for p in points}) != len(points):
80
+ raise ValueError(f'{key}: expected a nonempty series with unique ages in the figure mapping')
81
+ points.sort()
82
+ audit[key]=[{'age':age,'coef':e,'se':se,**data.used[b['record']]}
83
+ for (age,e,se),b in zip(points,sorted(figures[key],key=lambda b:b['age']))]
84
+ prepared.append((points,color,legend))
85
+ line_figure(prepared,folder/filename,ylabel,dollars=name!='a2')
86
+ for key,filename,dollars in [
87
+ ('f1_bars','earnings_age25.pdf',True),
88
+ ('f2','earnings_distribution.pdf',False),
89
+ ('f3_attendance','college_attendance.pdf',False),
90
+ ('f3_completion','college_completion.pdf',False),
91
+ ]:
92
+ if key in figures:audit[key]=paired_bars(data,figures[key],folder/filename,dollars)
93
+ if 'a3_networks' in figures:
94
+ audit['a3']=leave_one_out(data,figures['a3_networks'],figures['a3_baseline'][0],folder/'network_leave_one_out.pdf')
95
+ return audit
96
+
97
+
98
+ def line_figure(prepared,path,ylabel,dollars=True):
99
+ ages=sorted({a for points,_,_ in prepared for a,_,_ in points})
100
+ low=min(0,*(e-1.96*se for points,_,_ in prepared for _,e,se in points))
101
+ high=max(0,*(e+1.96*se for points,_,_ in prepared for _,e,se in points))
102
+ span=max(high-low,1);lo,hi=low-.05*span,high+.05*span
103
+ width,height=1296,648
104
+ left,bottom,right,top=159,74,1285,637
105
+ x=lambda age:left+(ages.index(age)+.6)*(right-left)/(len(ages)-1+1.2)
106
+ y=lambda val:bottom+(val-lo)*(top-bottom)/(hi-lo)
107
+ c=canvas.Canvas(str(path),pagesize=(width,height),invariant=1)
108
+ axes(c,left,bottom,right,top,y,extended_breaks(lo,hi),
109
+ (lambda v:f'${v/1000:.1f}K') if dollars else (lambda v:f'{v:.1f}%'))
110
+ for age in ages:
111
+ c.line(x(age),bottom-8,x(age),bottom);label(c,x(age),bottom-29,str(age))
112
+ label(c,(left+right)/2,16,'Age')
113
+ vertical_title(c,44,(bottom+top)/2,ylabel)
114
+ c.setStrokeColor(HexColor('#808080'));c.setLineWidth(1.067);c.setDash([4.27,4.27]);c.line(left,y(0),right,y(0));c.setDash([])
115
+ for points,color,_ in prepared:
116
+ c.setStrokeColor(color);c.setLineCap(0)
117
+ for sign in [-1,1,0]:
118
+ # R's dotted linetype uses one unit on / three off, scaled by width.
119
+ c.setLineWidth(3.201 if sign else 2.134)
120
+ c.setDash([3.201,9.603] if sign else [])
121
+ p=c.beginPath()
122
+ for i,(age,e,se) in enumerate(points):
123
+ (p.moveTo if i==0 else p.lineTo)(x(age),y(e+sign*1.96*se))
124
+ c.drawPath(p)
125
+ c.setFillColor(color)
126
+ for age,e,se in points:c.circle(x(age),y(e),6,stroke=0,fill=1)
127
+ legends=[(color,text) for _,color,text in prepared if text]
128
+ if legends:
129
+ legend_width=max(pdfmetrics.stringWidth(text,FONT,22) for _,text in legends)+30
130
+ lx=right-.02*(right-left)-legend_width
131
+ for i,(color,text) in enumerate(legends):
132
+ ly=bottom+.02*(top-bottom)+10+(len(legends)-1-i)*29
133
+ c.setStrokeColor(color);c.setFillColor(color);c.setDash([]);c.setLineWidth(2.134)
134
+ c.line(lx,ly+7,lx+17,ly+7);c.circle(lx+8.5,ly+7,6,stroke=0,fill=1)
135
+ label(c,lx+23,ly,text,align='left')
136
+ c.save()
137
+
138
+
139
+ def paired_bars(data,bindings,path,dollars=False):
140
+ """Match create_barplot_panel: move the mean label, never the CI center."""
141
+ prepared=[]
142
+ for b in bindings:
143
+ row={field:data.value(dict(b,field=field)) for field in ['coef','se','ccm']}
144
+ if any(v is None for v in row.values()):
145
+ raise ValueError(f'{b["record"]}: the bar figure requires coef, se, and ccm.')
146
+ row.update(label=b['label'],treated=row['ccm']+row['coef'],
147
+ percent_gain=100*row['coef']/row['ccm'] if row['ccm'] else None,
148
+ record=b['record'],source=data.used[b['record']])
149
+ prepared.append(row)
150
+ count=len(prepared);width,height=(1296/2.1,648) if dollars else (1296,648)
151
+ gap=.025 if count==4 else .1
152
+ panel_width=width/(count+(count-1)*gap)
153
+ c=canvas.Canvas(str(path),pagesize=(width,height),invariant=1)
154
+ for i,row in enumerate(prepared):
155
+ origin=i*panel_width*(1+gap)
156
+ left=origin+11+61.2+(72 if dollars else 0)
157
+ right=origin+panel_width-11;bottom=86.6;top=637 if dollars else 613.2
158
+ control,treated,se=row['ccm'],row['treated'],row['se']
159
+ ci_lo,ci_hi=treated-1.96*se,treated+1.96*se
160
+ padding=.02*max(abs(v) for v in [control,treated,ci_lo,ci_hi])
161
+ lo=min(.75*min(control,treated),ci_lo-padding)
162
+ upper=max(control,ci_hi)
163
+ # Same fractional headroom and expansion as the R source. No zero floor.
164
+ span=max((upper-lo)/(1-.05-.12),1e-6)
165
+ hi=lo+1.05*span
166
+ y=lambda v:bottom+(v-lo)*(top-bottom)/(hi-lo)
167
+ x=lambda v:left+(v-.4)*(right-left)/(2.5 if count==4 else 2.2)
168
+ # The R labels round ticks to whole $K / whole percent, even when the
169
+ # extended-break locations include halves. This also preserves its fixed
170
+ # y-axis label width (long decimal labels would extend off the canvas).
171
+ fmt=(lambda v:f'${v/1000:,.0f}K') if dollars else (lambda v:f'{v:.0f}%')
172
+ axes(c,left,bottom,right,top,y,extended_breaks(lo,hi),fmt)
173
+ # coord_cartesian crops bars at the lower axis, including negative values.
174
+ c.saveState();clip=c.beginPath();clip.rect(left,bottom,right-left,top-bottom);c.clipPath(clip,stroke=0)
175
+ for pos,value,color in [(1,control,ORANGE),(2,treated,BLUE)]:
176
+ c.setFillColor(color)
177
+ c.rect(x(pos-.35),min(y(0),y(value)),x(pos+.35)-x(pos-.35),abs(y(value)-y(0)),stroke=0,fill=1)
178
+ c.restoreState()
179
+ c.setStrokeColor(black);c.setLineWidth(1.067);c.line(left,bottom,right,bottom)
180
+ c.setStrokeColor(black);c.setLineWidth(2.134)
181
+ c.line(x(2),y(ci_lo),x(2),y(ci_hi))
182
+ for end in [ci_lo,ci_hi]:c.line(x(1.95),y(end),x(2.05),y(end))
183
+ mean=lambda v:f'${v/1000:.1f}K' if dollars else f'{v:.1f}%'
184
+ label(c,x(1),y(control)+5,mean(control))
185
+ label(c,x(2.05),y(treated)+5,mean(treated),align='left')
186
+ bracket=upper+.05*span
187
+ # ggpubr tip.length is a fraction of its data range, before coord zoom.
188
+ tip=.03*(bracket-min(ci_lo,control))
189
+ c.setLineWidth(2.134)
190
+ c.lines([(x(1),y(bracket-tip),x(1),y(bracket)),
191
+ (x(1),y(bracket),x(2),y(bracket)),
192
+ (x(2),y(bracket),x(2),y(bracket-tip))])
193
+ if dollars:
194
+ raw=f'{"+" if row["coef"]>=0 else "−"}${abs(row["coef"])/1000:.1f}K (s.e.=${se/1000:.1f}K)'
195
+ label(c,x(1.5),y(bracket)+7,raw)
196
+ if row['percent_gain'] is not None:
197
+ label(c,x(1.5),y(bracket+.055*span)+5,f'{row["percent_gain"]:+.1f}%',size=26)
198
+ else:label(c,x(1.5),y(bracket+.055*span)+5,'—',size=26)
199
+ vertical_title(c,29,(bottom+top)/2,'Mean Wage Earnings at Age 25')
200
+ names=['Control\nComplier Mean','Treated Mean\n(CCM + LATE)']
201
+ else:
202
+ label(c,x(1.5),y(bracket)+36,f'{row["coef"]:+.1f}pp')
203
+ label(c,x(1.5),y(bracket)+7,f'(s.e.={se:.1f}pp)')
204
+ label(c,(left+right)/2,height-27,row['label'],bold=True)
205
+ names=['Control\nComplier\nMean','Treated\nMean']
206
+ c.setStrokeColor(black);c.setLineWidth(1.067)
207
+ for pos,text in enumerate(names,1):
208
+ c.line(x(pos),bottom-8,x(pos),bottom)
209
+ for j,line in enumerate(text.split('\n')):label(c,x(pos),bottom-29-j*23.8,line)
210
+ row['layout']={'control_x':x(1),'treated_x':x(2),'ci_x':x(2),
211
+ 'bracket_left':x(1),'bracket_right':x(2),'axis_min':lo,'axis_max':hi}
212
+ c.save()
213
+ return prepared
214
+
215
+
216
+ def leave_one_out(data,bindings,baseline,path):
217
+ if len(bindings)<2:raise ValueError('Figure A3 requires at least two networks in input_mapping().')
218
+ rows=[]
219
+ for b in bindings:
220
+ coef=data.value(dict(b,field='coef'));se=data.value(dict(b,field='se'))
221
+ if coef is None or se is None or se<=0:
222
+ raise ValueError(f'{b["record"]}: Figure A3 requires a coefficient and positive standard error.')
223
+ rows.append(dict(label=b['label'],coef=coef,se=se,source=data.used[b['record']]))
224
+ if len({tuple(sorted(row['source']['where'].items())) for row in rows}) != len(rows):
225
+ raise ValueError('Figure A3 network samples must identify distinct rows.')
226
+ pooled=data.value(dict(baseline,field='coef'))
227
+ if pooled is None:raise ValueError('Figure A3 requires the pooled baseline earnings coefficient.')
228
+ estimates=[]
229
+ for i,row in enumerate(rows):
230
+ others=[r for j,r in enumerate(rows) if j!=i]
231
+ precision=sum(1/r['se']**2 for r in others)
232
+ estimates.append({'label':row['label'],'coef':sum(r['coef']/r['se']**2 for r in others)/precision,
233
+ 'se':math.sqrt(1/precision)})
234
+ # The paper sorts the bars and suppresses network names, CIs and reference line.
235
+ ordered=sorted(estimates,key=lambda r:r['coef'])
236
+ low=min(0,*(r['coef'] for r in estimates));high=max(4.5,*(1.15*r['coef'] for r in estimates))
237
+ span=high-low;lo,hi=low-.05*span,high+.05*span
238
+ left,bottom,right,top=159,89,1285,637
239
+ y=lambda v:bottom+(v-lo)*(top-bottom)/(hi-lo)
240
+ x=lambda pos:left+(pos-.4)*(right-left)/(len(ordered)+.2)
241
+ c=canvas.Canvas(str(path),pagesize=(1296,648),invariant=1)
242
+ axes(c,left,bottom,right,top,y,extended_breaks(lo,hi),lambda v:f'${v:.1f}K')
243
+ for i,row in enumerate(ordered,1):
244
+ c.setFillColor(GRAY);c.rect(x(i-.35),min(y(0),y(row['coef'])),x(i+.35)-x(i-.35),abs(y(row['coef'])-y(0)),stroke=0,fill=1)
245
+ label(c,right-20,top-32,f'Baseline Pooled Estimate: ${pooled:.1f}K',align='right',color=BLUE)
246
+ label(c,(left+right)/2,23,'Each Bar Plots LATE Leaving Out One Charter Network')
247
+ vertical_title(c,44,(bottom+top)/2,'Treatment Effect on Mean Wage Earnings\nat Age 25')
248
+ c.save()
249
+ return {'networks':rows,'leave_one_out':estimates,'baseline':pooled,
250
+ 'baseline_source':data.used[baseline['record']]}
@@ -0,0 +1,4 @@
1
+ openpyxl>=3.1
2
+ reportlab>=4,<5; python_version < '3.10'
3
+ reportlab>=4; python_version >= '3.10'
4
+ pypdf>=4
@@ -0,0 +1,38 @@
1
+ \setlength{\tabcolsep}{5pt}
2
+ \begin{tabular}{L{3.5cm} *{5}{C{2cm}}}
3
+ \toprule
4
+ & \shortstack{First\\Stage}
5
+ & \shortstack{Earnings\\ITT}
6
+ & \shortstack{Earnings\\LATE}
7
+ & \shortstack{Earnings\\LATE with\\Controls}
8
+ & AGI \\
9
+ & (1) & (2) & (3) & (4) & (5) \\
10
+ \midrule
11
+ Offered vs. Control
12
+ & @@age25_earnings_table.0.0@@
13
+ & @@age25_earnings_table.2.0@@
14
+ & & & \\
15
+ & @@age25_earnings_table.1.0@@
16
+ & @@age25_earnings_table.3.0@@
17
+ & & & \\
18
+ Control Mean
19
+ & @@age25_earnings_table.0.1@@
20
+ & @@age25_earnings_table.2.1@@
21
+ & & & \\
22
+ \addlinespace
23
+ Enrolled vs. Control
24
+ & &
25
+ & @@age25_earnings_table.4.0@@
26
+ & @@age25_earnings_table.6.0@@
27
+ & @@age25_earnings_table.8.0@@ \\
28
+ & &
29
+ & @@age25_earnings_table.5.0@@
30
+ & @@age25_earnings_table.7.0@@
31
+ & @@age25_earnings_table.9.0@@ \\
32
+ Control Complier Mean
33
+ & &
34
+ & @@age25_earnings_table.4.1@@
35
+ & @@age25_earnings_table.6.1@@
36
+ & @@age25_earnings_table.8.1@@ \\
37
+ \bottomrule
38
+ \end{tabular}
@@ -0,0 +1,54 @@
1
+ % Workbook-driven table; source variable mappings are in build_latex.py.
2
+ % Edit labels, row order, panels, and column structure here.
3
+
4
+
5
+ \begin{tabular}{L{6.4cm} *{4}{C{2.2cm}}}
6
+ \toprule
7
+ & \multicolumn{2}{c}{Age 20+ Sample}
8
+ & \multicolumn{2}{c}{Age 25+ Sample} \\
9
+ \cmidrule(lr){2-3}\cmidrule(lr){4-5}
10
+ & Control Group Mean & Offered vs. Control & Control Group Mean & Offered vs. Control
11
+ \\
12
+ & (1) & (2) & (3) & (4) \\
13
+ \midrule
14
+
15
+
16
+ \addlinespace
17
+ \textit{A. Tax-Data Linkage} & & & & \\
18
+ \hspace{0.1cm}Linked to tax data (\%) & @@balance_table.14.0@@ & @@balance_table.14.1@@ & @@balance_table.14.2@@ & @@balance_table.14.3@@ \\
19
+ & & @@balance_table.15.1@@ & & @@balance_table.15.3@@ \\
20
+
21
+ \addlinespace
22
+
23
+ \textit{B. Demographic Characteristics} & & & & \\
24
+ \hspace{0.1cm}Black (\%)
25
+ & @@balance_table.0.0@@ & @@balance_table.0.1@@ & @@balance_table.0.2@@ & @@balance_table.0.3@@ \\
26
+ & & @@balance_table.1.1@@ & & @@balance_table.1.3@@ \\
27
+ \hspace{0.1cm}Hispanic (\%)
28
+ & @@balance_table.2.0@@ & @@balance_table.2.1@@ & @@balance_table.2.2@@ & @@balance_table.2.3@@ \\
29
+ & & @@balance_table.3.1@@ & & @@balance_table.3.3@@ \\
30
+ \hspace{0.1cm}White (\%)
31
+ & @@balance_table.4.0@@ & @@balance_table.4.1@@ & @@balance_table.4.2@@ & @@balance_table.4.3@@ \\
32
+ & & @@balance_table.5.1@@ & & @@balance_table.5.3@@ \\
33
+ \hspace{0.1cm}Female (\%)
34
+ & @@balance_table.6.0@@ & @@balance_table.6.1@@ & @@balance_table.6.2@@ & @@balance_table.6.3@@ \\
35
+ & & @@balance_table.7.1@@ & & @@balance_table.7.3@@ \\
36
+
37
+ \addlinespace
38
+ \textit{C. Family and Neighborhood Characteristics} & & & & \\
39
+ \hspace{0.1cm}Parent income rank (percentile)
40
+ & @@balance_table.8.0@@ & @@balance_table.8.1@@ & @@balance_table.8.2@@ & @@balance_table.8.3@@ \\
41
+ & & @@balance_table.9.1@@ & & @@balance_table.9.3@@ \\
42
+ \hspace{0.1cm}Median tract household income (\$)
43
+ & @@balance_table.10.0@@ & @@balance_table.10.1@@ & @@balance_table.10.2@@ & @@balance_table.10.3@@ \\
44
+ & & @@balance_table.11.1@@ & & @@balance_table.11.3@@ \\
45
+ \hspace{0.1cm}Predicted age 25 earnings (\$)
46
+ & @@balance_table.12.0@@ & @@balance_table.12.1@@ & @@balance_table.12.2@@ & @@balance_table.12.3@@ \\
47
+ & & @@balance_table.13.1@@ & & @@balance_table.13.3@@ \\
48
+
49
+ \addlinespace[4pt]
50
+ Number of applicants
51
+ & & @@balance_table.16.1@@ & & @@balance_table.16.3@@ \\
52
+
53
+ \bottomrule
54
+ \end{tabular}
@@ -0,0 +1,20 @@
1
+ % Synthetic review overlay; restore originals from data/codex_synthetic/review_source.
2
+ % The Form 1098-T benchmark is shared by both NSC comparisons.
3
+
4
+
5
+ \setlength{\tabcolsep}{8pt}
6
+ \begin{tabular}{L{4cm} *{3}{C{3cm}}}
7
+ \toprule
8
+ & \shortstack{Form 1098-T\\Benchmark}
9
+ & \shortstack{NSC\\Original Sample}
10
+ & \shortstack{NSC\\Aligned Sample} \\
11
+ & (1) & (2) & (3) \\
12
+ \midrule
13
+ Enrolled vs. Control
14
+ & @@college_data_comparison_table.0.0@@ & @@college_data_comparison_table.0.1@@ & @@college_data_comparison_table.0.2@@ \\
15
+ & @@college_data_comparison_table.1.0@@ & @@college_data_comparison_table.1.1@@ & @@college_data_comparison_table.1.2@@ \\
16
+ \addlinespace
17
+ Control Complier Mean
18
+ & @@college_data_comparison_table.2.0@@ & @@college_data_comparison_table.2.1@@ & @@college_data_comparison_table.2.2@@ \\
19
+ \bottomrule
20
+ \end{tabular}
@@ -0,0 +1,31 @@
1
+ % Synthetic review overlay; restore originals from data/codex_synthetic/review_source.
2
+ % Table layout backed by outputs/tables/input/college_enrollment_completion_table_input.csv.
3
+
4
+
5
+ \setlength{\tabcolsep}{2.5pt}
6
+ \begin{tabular}{L{3.2cm} *{8}{C{1.45cm}}}
7
+ \toprule
8
+ & \multicolumn{4}{c}{College Enrollment by Age 20}
9
+ & \multicolumn{4}{c}{College Completion by Age 24} \\
10
+ \cmidrule(lr){2-5}\cmidrule(lr){6-9}
11
+ & Any
12
+ & \shortstack{Two-\\ Year}
13
+ & \shortstack{Four-\\ Year}
14
+ & \shortstack{Highly\\ Selective}
15
+ & Any
16
+ & \shortstack{Associate's\\ Degree}
17
+ & \shortstack{Bachelor's\\ Degree}
18
+ & \shortstack{Highly\\ Selective} \\
19
+ & (1) & (2) & (3) & (4) & (5) & (6) & (7) & (8) \\
20
+ \midrule
21
+
22
+ Enrolled vs. Control
23
+ & @@college_enrollment_completion_table.0.0@@ & @@college_enrollment_completion_table.0.1@@ & @@college_enrollment_completion_table.0.2@@ & @@college_enrollment_completion_table.0.3@@ & @@college_enrollment_completion_table.0.4@@ & @@college_enrollment_completion_table.0.5@@ & @@college_enrollment_completion_table.0.6@@ & @@college_enrollment_completion_table.0.7@@ \\
24
+ & @@college_enrollment_completion_table.1.0@@ & @@college_enrollment_completion_table.1.1@@ & @@college_enrollment_completion_table.1.2@@ & @@college_enrollment_completion_table.1.3@@ & @@college_enrollment_completion_table.1.4@@ & @@college_enrollment_completion_table.1.5@@ & @@college_enrollment_completion_table.1.6@@ & @@college_enrollment_completion_table.1.7@@ \\
25
+
26
+ \addlinespace
27
+ Control Complier Mean
28
+ & @@college_enrollment_completion_table.2.0@@ & @@college_enrollment_completion_table.2.1@@ & @@college_enrollment_completion_table.2.2@@ & @@college_enrollment_completion_table.2.3@@ & @@college_enrollment_completion_table.2.4@@ & @@college_enrollment_completion_table.2.5@@ & @@college_enrollment_completion_table.2.6@@ & @@college_enrollment_completion_table.2.7@@ \\
29
+
30
+ \bottomrule
31
+ \end{tabular}
@@ -0,0 +1,36 @@
1
+ % Synthetic review overlay; restore originals from data/codex_synthetic/review_source.
2
+ % Table layout backed by outputs/tables/input/college_heterogeneity_table_input.csv.
3
+
4
+
5
+ \setlength{\tabcolsep}{2pt}
6
+ \begin{tabular}{L{3cm} *{10}{C{1.15cm}}}
7
+ \toprule
8
+ & \multicolumn{2}{c}{Parent Income}
9
+ & \multicolumn{2}{c}{Neighborhood Income}
10
+ & \multicolumn{2}{c}{Sex}
11
+ & \multicolumn{2}{c}{Race/Ethnicity}
12
+ & \multicolumn{2}{c}{Entry Grade} \\
13
+ \cmidrule(lr){2-3}\cmidrule(lr){4-5}\cmidrule(lr){6-7}\cmidrule(lr){8-9}\cmidrule(lr){10-11}
14
+ & Low & High
15
+ & Low & High
16
+ & Boys & Girls
17
+ & Black & Hispanic
18
+ & \shortstack{High\\ School} & \shortstack{Middle\\ School} \\
19
+ & (1) & (2) & (3) & (4) & (5) & (6) & (7) & (8) & (9) & (10) \\
20
+ \midrule
21
+
22
+ \multicolumn{11}{l}{\textit{Panel A. College Attendance by Age 20}} \\
23
+ \addlinespace[2pt]
24
+ Enrolled vs. Control
25
+ & @@college_heterogeneity_table.0.0@@ & @@college_heterogeneity_table.0.1@@ & @@college_heterogeneity_table.0.2@@ & @@college_heterogeneity_table.0.3@@ & @@college_heterogeneity_table.0.4@@ & @@college_heterogeneity_table.0.5@@ & @@college_heterogeneity_table.0.6@@ & @@college_heterogeneity_table.0.7@@ & @@college_heterogeneity_table.0.8@@ & @@college_heterogeneity_table.0.9@@ \\
26
+ & @@college_heterogeneity_table.1.0@@ & @@college_heterogeneity_table.1.1@@ & @@college_heterogeneity_table.1.2@@ & @@college_heterogeneity_table.1.3@@ & @@college_heterogeneity_table.1.4@@ & @@college_heterogeneity_table.1.5@@ & @@college_heterogeneity_table.1.6@@ & @@college_heterogeneity_table.1.7@@ & @@college_heterogeneity_table.1.8@@ & @@college_heterogeneity_table.1.9@@ \\
27
+
28
+ \addlinespace
29
+ \multicolumn{11}{l}{\textit{Panel B. Four-Year Degree Completion}} \\
30
+ \addlinespace[2pt]
31
+ Enrolled vs. Control
32
+ & @@college_heterogeneity_table.2.0@@ & @@college_heterogeneity_table.2.1@@ & @@college_heterogeneity_table.2.2@@ & @@college_heterogeneity_table.2.3@@ & @@college_heterogeneity_table.2.4@@ & @@college_heterogeneity_table.2.5@@ & @@college_heterogeneity_table.2.6@@ & @@college_heterogeneity_table.2.7@@ & @@college_heterogeneity_table.2.8@@ & @@college_heterogeneity_table.2.9@@ \\
33
+ & @@college_heterogeneity_table.3.0@@ & @@college_heterogeneity_table.3.1@@ & @@college_heterogeneity_table.3.2@@ & @@college_heterogeneity_table.3.3@@ & @@college_heterogeneity_table.3.4@@ & @@college_heterogeneity_table.3.5@@ & @@college_heterogeneity_table.3.6@@ & @@college_heterogeneity_table.3.7@@ & @@college_heterogeneity_table.3.8@@ & @@college_heterogeneity_table.3.9@@ \\
34
+
35
+ \bottomrule
36
+ \end{tabular}
@@ -0,0 +1,30 @@
1
+ % Synthetic review overlay; restore originals from data/codex_synthetic/review_source.
2
+ % Placeholder layout: all estimates await disclosure.
3
+ \setlength{\tabcolsep}{3pt}
4
+ \begin{tabular}{L{3cm} *{8}{C{1.45cm}}}
5
+ \toprule
6
+ & \multicolumn{2}{c}{Earnings Baseline Spec.}
7
+ & \multicolumn{3}{c}{Actual Completion: 25+ Sample}
8
+ & \multicolumn{3}{c}{Predicted Completion: 25+ Sample} \\
9
+ \cmidrule(lr){2-3}\cmidrule(lr){4-6}\cmidrule(lr){7-9}
10
+ & \shortstack{Earnings\\Ever\\College}
11
+ & \shortstack{Earnings\\Never\\College}
12
+ & \shortstack{Any College\\Completion}
13
+ & \shortstack{BA\\Completion}
14
+ & \shortstack{Two-Year\\Completion}
15
+ & \shortstack{Any College\\Completion}
16
+ & \shortstack{Four-Year\\Completion}
17
+ & \shortstack{Two-Year\\Completion} \\
18
+ & (1) & (2) & (3) & (4) & (5) & (6) & (7) & (8) \\
19
+ \midrule
20
+
21
+ Enrolled vs. Control
22
+ & @@college_mediation_additional_specs_table.0.0@@ & @@college_mediation_additional_specs_table.0.1@@ & @@college_mediation_additional_specs_table.0.2@@ & @@college_mediation_additional_specs_table.0.3@@ & @@college_mediation_additional_specs_table.0.4@@ & @@college_mediation_additional_specs_table.0.5@@ & @@college_mediation_additional_specs_table.0.6@@ & @@college_mediation_additional_specs_table.0.7@@ \\
23
+ & @@college_mediation_additional_specs_table.1.0@@ & @@college_mediation_additional_specs_table.1.1@@ & @@college_mediation_additional_specs_table.1.2@@ & @@college_mediation_additional_specs_table.1.3@@ & @@college_mediation_additional_specs_table.1.4@@ & @@college_mediation_additional_specs_table.1.5@@ & @@college_mediation_additional_specs_table.1.6@@ & @@college_mediation_additional_specs_table.1.7@@ \\
24
+
25
+ \addlinespace
26
+ Control Complier Mean
27
+ & @@college_mediation_additional_specs_table.2.0@@ & @@college_mediation_additional_specs_table.2.1@@ & @@college_mediation_additional_specs_table.2.2@@ & @@college_mediation_additional_specs_table.2.3@@ & @@college_mediation_additional_specs_table.2.4@@ & @@college_mediation_additional_specs_table.2.5@@ & @@college_mediation_additional_specs_table.2.6@@ & @@college_mediation_additional_specs_table.2.7@@ \\
28
+
29
+ \bottomrule
30
+ \end{tabular}
@@ -0,0 +1,18 @@
1
+ \setlength{\tabcolsep}{4pt}
2
+ \begin{tabular}{L{4.7cm} C{1.8cm} C{2.5cm} C{2.5cm} C{2.7cm}}
3
+ \toprule
4
+ \textit{A. College} & Effect (pp) & Earnings Return (\% per pp) & Implied Earnings Gain (\%) & Observed Gain Explained (\%) \\
5
+ \midrule
6
+ BA completion & @@college_test_score_mediation_table.0.0@@ & @@college_test_score_mediation_table.0.1@@ & @@college_test_score_mediation_table.0.2@@ & @@college_test_score_mediation_table.0.3@@ \\ \addlinespace
7
+ Selective BA completion & @@college_test_score_mediation_table.1.0@@ & @@college_test_score_mediation_table.1.1@@ & @@college_test_score_mediation_table.1.2@@ & @@college_test_score_mediation_table.1.3@@ \\ \addlinespace
8
+ Highly selective BA completion & @@college_test_score_mediation_table.2.0@@ & @@college_test_score_mediation_table.2.1@@ & @@college_test_score_mediation_table.2.2@@ & @@college_test_score_mediation_table.2.3@@ \\ \addlinespace
9
+ \cmidrule(lr){4-5}
10
+ Total college contribution & & & @@college_test_score_mediation_table.3.2@@ & @@college_test_score_mediation_table.3.3@@ \\
11
+
12
+ \addlinespace[10pt]
13
+ \textit{B. Test Scores} & Effect (SD/year) & Earnings Return (\% per SD) & Implied Earnings Gain (\%) & Observed Gain Explained (\%) \\
14
+ \midrule
15
+ \hspace{0.1cm}Annual math gain
16
+ & @@college_test_score_mediation_table.4.0@@ & @@college_test_score_mediation_table.4.1@@ & @@college_test_score_mediation_table.4.2@@ & @@college_test_score_mediation_table.4.3@@ \\
17
+ \bottomrule
18
+ \end{tabular}
@@ -0,0 +1,54 @@
1
+ % Workbook-driven table; source variable mappings are in build_latex.py.
2
+ \setlength{\tabcolsep}{2pt}
3
+ \begin{tabular}{L{3cm} *{10}{C{1.15cm}}}
4
+ \toprule
5
+ & \multicolumn{2}{c}{Parent Income}
6
+ & \multicolumn{2}{c}{Neighborhood Income}
7
+ & \multicolumn{2}{c}{Sex}
8
+ & \multicolumn{2}{c}{Race/Ethnicity}
9
+ & \multicolumn{2}{c}{Entry Grade} \\
10
+ \cmidrule(lr){2-3}\cmidrule(lr){4-5}\cmidrule(lr){6-7}\cmidrule(lr){8-9}\cmidrule(lr){10-11}
11
+ & Low & High
12
+ & Low & High
13
+ & Boys & Girls
14
+ & Black & Hispanic
15
+ & \shortstack{High\\ School} & \shortstack{Middle\\ School} \\
16
+ & (1) & (2) & (3) & (4) & (5) & (6) & (7) & (8) & (9) & (10) \\
17
+ \midrule
18
+ \multicolumn{11}{l}{\textit{Panel A. Earnings at Age 25}} \\
19
+ \addlinespace[2pt]
20
+
21
+ Enrolled vs. Control
22
+ & @@earnings_heterogeneity_table.0.0@@ & @@earnings_heterogeneity_table.0.1@@ & @@earnings_heterogeneity_table.0.2@@ & @@earnings_heterogeneity_table.0.3@@ & @@earnings_heterogeneity_table.0.4@@ & @@earnings_heterogeneity_table.0.5@@ & @@earnings_heterogeneity_table.0.6@@ & @@earnings_heterogeneity_table.0.7@@ & @@earnings_heterogeneity_table.0.8@@ & @@earnings_heterogeneity_table.0.9@@ \\
23
+ & @@earnings_heterogeneity_table.1.0@@ & @@earnings_heterogeneity_table.1.1@@ & @@earnings_heterogeneity_table.1.2@@ & @@earnings_heterogeneity_table.1.3@@ & @@earnings_heterogeneity_table.1.4@@ & @@earnings_heterogeneity_table.1.5@@ & @@earnings_heterogeneity_table.1.6@@ & @@earnings_heterogeneity_table.1.7@@ & @@earnings_heterogeneity_table.1.8@@ & @@earnings_heterogeneity_table.1.9@@ \\
24
+
25
+ Control Complier Mean
26
+ & @@earnings_heterogeneity_table.2.0@@ & @@earnings_heterogeneity_table.2.1@@ & @@earnings_heterogeneity_table.2.2@@ & @@earnings_heterogeneity_table.2.3@@ & @@earnings_heterogeneity_table.2.4@@ & @@earnings_heterogeneity_table.2.5@@ & @@earnings_heterogeneity_table.2.6@@ & @@earnings_heterogeneity_table.2.7@@ & @@earnings_heterogeneity_table.2.8@@ & @@earnings_heterogeneity_table.2.9@@ \\
27
+
28
+ \addlinespace[8pt]
29
+ \multicolumn{11}{l}{\textit{Panel B. Surrogate Earnings at Age 31}} \\
30
+ \addlinespace[2pt]
31
+ Enrolled vs. Control & @@earnings_heterogeneity_table.3.0@@ & @@earnings_heterogeneity_table.3.1@@ & @@earnings_heterogeneity_table.3.2@@ & @@earnings_heterogeneity_table.3.3@@ & @@earnings_heterogeneity_table.3.4@@ & @@earnings_heterogeneity_table.3.5@@ & @@earnings_heterogeneity_table.3.6@@ & @@earnings_heterogeneity_table.3.7@@ & @@earnings_heterogeneity_table.3.8@@ & @@earnings_heterogeneity_table.3.9@@ \\
32
+ & @@earnings_heterogeneity_table.4.0@@ & @@earnings_heterogeneity_table.4.1@@ & @@earnings_heterogeneity_table.4.2@@ & @@earnings_heterogeneity_table.4.3@@ & @@earnings_heterogeneity_table.4.4@@ & @@earnings_heterogeneity_table.4.5@@ & @@earnings_heterogeneity_table.4.6@@ & @@earnings_heterogeneity_table.4.7@@ & @@earnings_heterogeneity_table.4.8@@ & @@earnings_heterogeneity_table.4.9@@ \\
33
+ Control Complier Mean & @@earnings_heterogeneity_table.5.0@@ & @@earnings_heterogeneity_table.5.1@@ & @@earnings_heterogeneity_table.5.2@@ & @@earnings_heterogeneity_table.5.3@@ & @@earnings_heterogeneity_table.5.4@@ & @@earnings_heterogeneity_table.5.5@@ & @@earnings_heterogeneity_table.5.6@@ & @@earnings_heterogeneity_table.5.7@@ & @@earnings_heterogeneity_table.5.8@@ & @@earnings_heterogeneity_table.5.9@@ \\
34
+ \addlinespace
35
+ \multicolumn{11}{l}{\textit{Panel C. College Attendance by Age 20}} \\
36
+ \addlinespace[2pt]
37
+ Enrolled vs. Control
38
+ & @@earnings_heterogeneity_table.6.0@@ & @@earnings_heterogeneity_table.6.1@@ & @@earnings_heterogeneity_table.6.2@@ & @@earnings_heterogeneity_table.6.3@@ & @@earnings_heterogeneity_table.6.4@@ & @@earnings_heterogeneity_table.6.5@@ & @@earnings_heterogeneity_table.6.6@@ & @@earnings_heterogeneity_table.6.7@@ & @@earnings_heterogeneity_table.6.8@@ & @@earnings_heterogeneity_table.6.9@@ \\
39
+ & @@earnings_heterogeneity_table.7.0@@ & @@earnings_heterogeneity_table.7.1@@ & @@earnings_heterogeneity_table.7.2@@ & @@earnings_heterogeneity_table.7.3@@ & @@earnings_heterogeneity_table.7.4@@ & @@earnings_heterogeneity_table.7.5@@ & @@earnings_heterogeneity_table.7.6@@ & @@earnings_heterogeneity_table.7.7@@ & @@earnings_heterogeneity_table.7.8@@ & @@earnings_heterogeneity_table.7.9@@ \\
40
+
41
+
42
+ \addlinespace[2pt]
43
+ Control Complier Mean
44
+ & @@earnings_heterogeneity_table.8.0@@ & @@earnings_heterogeneity_table.8.1@@ & @@earnings_heterogeneity_table.8.2@@ & @@earnings_heterogeneity_table.8.3@@ & @@earnings_heterogeneity_table.8.4@@ & @@earnings_heterogeneity_table.8.5@@ & @@earnings_heterogeneity_table.8.6@@ & @@earnings_heterogeneity_table.8.7@@ & @@earnings_heterogeneity_table.8.8@@ & @@earnings_heterogeneity_table.8.9@@ \\
45
+
46
+ \addlinespace[8pt]
47
+ \multicolumn{11}{l}{\textit{Panel D. Four-Year Degree Completion by Age 24}} \\
48
+ \addlinespace[2pt]
49
+ Enrolled vs. Control & @@earnings_heterogeneity_table.9.0@@ & @@earnings_heterogeneity_table.9.1@@ & @@earnings_heterogeneity_table.9.2@@ & @@earnings_heterogeneity_table.9.3@@ & @@earnings_heterogeneity_table.9.4@@ & @@earnings_heterogeneity_table.9.5@@ & @@earnings_heterogeneity_table.9.6@@ & @@earnings_heterogeneity_table.9.7@@ & @@earnings_heterogeneity_table.9.8@@ & @@earnings_heterogeneity_table.9.9@@ \\
50
+ & @@earnings_heterogeneity_table.10.0@@ & @@earnings_heterogeneity_table.10.1@@ & @@earnings_heterogeneity_table.10.2@@ & @@earnings_heterogeneity_table.10.3@@ & @@earnings_heterogeneity_table.10.4@@ & @@earnings_heterogeneity_table.10.5@@ & @@earnings_heterogeneity_table.10.6@@ & @@earnings_heterogeneity_table.10.7@@ & @@earnings_heterogeneity_table.10.8@@ & @@earnings_heterogeneity_table.10.9@@ \\
51
+ Control Complier Mean & @@earnings_heterogeneity_table.11.0@@ & @@earnings_heterogeneity_table.11.1@@ & @@earnings_heterogeneity_table.11.2@@ & @@earnings_heterogeneity_table.11.3@@ & @@earnings_heterogeneity_table.11.4@@ & @@earnings_heterogeneity_table.11.5@@ & @@earnings_heterogeneity_table.11.6@@ & @@earnings_heterogeneity_table.11.7@@ & @@earnings_heterogeneity_table.11.8@@ & @@earnings_heterogeneity_table.11.9@@ \\
52
+
53
+ \bottomrule
54
+ \end{tabular}
@@ -0,0 +1,29 @@
1
+ \setlength{\tabcolsep}{3pt}
2
+ \begin{tabular}{L{3.3cm} *{7}{C{1.55cm}}}
3
+ \toprule
4
+ & \multicolumn{4}{C{6.83cm}}{Alternative Specifications for Earnings at 25}
5
+ & \multicolumn{3}{C{5.07cm}}{Baseline Specification for Other Outcomes at 25} \\
6
+ \cmidrule(lr){2-5}\cmidrule(lr){6-8}
7
+ & \shortstack{Initial Offer\\Only}
8
+ & Initial and Waitlist Offers
9
+ & Pre-Analysis Plan
10
+ & \shortstack{OLS with\\Tract FEs}
11
+ & AGI
12
+ & \shortstack{Spouse\\Earnings}
13
+ & Marriage \\
14
+ & (1) & (2) & (3) & (4) & (5) & (6) & (7) \\
15
+ \midrule
16
+ Enrollment effect
17
+ & @@earnings_robustness_table.0.0@@ & @@earnings_robustness_table.2.0@@ & @@earnings_robustness_table.4.0@@
18
+ & @@earnings_robustness_table.12.0@@
19
+ & @@earnings_robustness_table.6.0@@ & @@earnings_robustness_table.8.0@@ & @@earnings_robustness_table.10.0@@ \\
20
+ & @@earnings_robustness_table.1.0@@ & @@earnings_robustness_table.3.0@@ & @@earnings_robustness_table.5.0@@
21
+ & @@earnings_robustness_table.13.0@@
22
+ & @@earnings_robustness_table.7.0@@ & @@earnings_robustness_table.9.0@@ & @@earnings_robustness_table.11.0@@ \\
23
+ \addlinespace
24
+ Control Complier Mean
25
+ & @@earnings_robustness_table.0.1@@ & @@earnings_robustness_table.2.1@@ & @@earnings_robustness_table.4.1@@ & & @@earnings_robustness_table.6.1@@ & @@earnings_robustness_table.8.1@@ & @@earnings_robustness_table.10.1@@ \\
26
+ Control Mean
27
+ & & & & @@earnings_robustness_table.12.1@@ & & & \\
28
+ \bottomrule
29
+ \end{tabular}
@@ -0,0 +1,27 @@
1
+ % Synthetic review overlay; restore originals from data/codex_synthetic/review_source.
2
+ % Table layout backed by outputs/tables/input/earnings_threshold_table_input.csv.
3
+
4
+
5
+ \setlength{\tabcolsep}{3pt}
6
+ \begin{tabular}{L{3cm} *{7}{C{1.65cm}}}
7
+ \toprule
8
+ & Employed
9
+ & \multicolumn{2}{c}{Earning $>$\$20K}
10
+ & \multicolumn{2}{c}{Earning $>$\$50K}
11
+ & \multicolumn{2}{c}{Earning $>$\$100K} \\
12
+ \cmidrule(lr){2-2}\cmidrule(lr){3-4}\cmidrule(lr){5-6}\cmidrule(lr){7-8}
13
+ & Actual & Actual & Predicted
14
+ & Actual & Predicted & Actual & Predicted \\
15
+ & (1) & (2) & (3) & (4) & (5) & (6) & (7) \\
16
+ \midrule
17
+
18
+ Enrolled vs. Control
19
+ & @@earnings_threshold_table.0.0@@ & @@earnings_threshold_table.0.1@@ & @@earnings_threshold_table.0.2@@ & @@earnings_threshold_table.0.3@@ & @@earnings_threshold_table.0.4@@ & @@earnings_threshold_table.0.5@@ & @@earnings_threshold_table.0.6@@ \\
20
+ & @@earnings_threshold_table.1.0@@ & @@earnings_threshold_table.1.1@@ & & @@earnings_threshold_table.1.3@@ & & @@earnings_threshold_table.1.5@@ & \\
21
+
22
+ \addlinespace
23
+ Control Complier Mean
24
+ & @@earnings_threshold_table.2.0@@ & @@earnings_threshold_table.2.1@@ & & @@earnings_threshold_table.2.3@@ & & @@earnings_threshold_table.2.5@@ & \\
25
+
26
+ \bottomrule
27
+ \end{tabular}
@@ -0,0 +1,31 @@
1
+ \setlength{\tabcolsep}{3pt}
2
+ \begin{tabular}{L{3.5cm} *{5}{C{2.1cm}}}
3
+ \toprule
4
+ & \shortstack{Peer Parent\\Income\\Percentile}
5
+ & \shortstack{Teen Birth\\Rate for\\Girls}
6
+ & \shortstack{Selective\\College BA\\Rate at\\Age-19 Firm}
7
+ & \shortstack{Worker Wages\\Ages 30--40\\at Age-19 Firm}
8
+ & \shortstack{Retention Rate\\at Age-19 Firm} \\
9
+ & (1) & (2) & (3) & (4) & (5) \\
10
+ \midrule
11
+
12
+ Enrolled vs. Control
13
+ & @@other_mediators_table.0.0@@
14
+ & @@other_mediators_table.0.1@@
15
+ & @@other_mediators_table.0.3@@ & @@other_mediators_table.0.4@@ & @@other_mediators_table.0.5@@ \\
16
+ &
17
+ & @@other_mediators_table.1.1@@
18
+ & @@other_mediators_table.1.3@@ & @@other_mediators_table.1.4@@ & @@other_mediators_table.1.5@@ \\
19
+
20
+ \addlinespace
21
+ Comparison Mean
22
+ & @@other_mediators_table.2.0@@
23
+ & & & & \\
24
+
25
+ Control Complier Mean
26
+ &
27
+ & @@other_mediators_table.3.1@@
28
+ & @@other_mediators_table.3.3@@ & @@other_mediators_table.3.4@@ & @@other_mediators_table.3.5@@ \\
29
+
30
+ \bottomrule
31
+ \end{tabular}