@@ -28,19 +28,28 @@ def print_coefficients(self):
28
28
"""Prints the model coefficients"""
29
29
print ("Model coefficients:" )
30
30
coeffs = az .extract (self .prediction_model .idata .posterior , var_names = "beta" )
31
- # Note: f"{name: <30}" pads the name with spaces so that we have alignment of the stats despite variable names of different lengths
31
+ # Note: f"{name: <30}" pads the name with spaces so that we have alignment of
32
+ # the stats despite variable names of different lengths
32
33
for name in self .labels :
33
34
coeff_samples = coeffs .sel (coeffs = name )
34
35
print (
35
- f" { name : <30} { coeff_samples .mean ().data :.2f} , 94% HDI [{ coeff_samples .quantile (0.03 ).data :.2f} , { coeff_samples .quantile (1 - 0.03 ).data :.2f} ]"
36
+ f"""
37
+ { name : <30} { coeff_samples .mean ().data :.2f} ,
38
+ 94% HDI [{ coeff_samples .quantile (0.03 ).data :.2f} ,
39
+ { coeff_samples .quantile (1 - 0.03 ).data :.2f} ]
40
+ """
36
41
)
37
42
# add coeff for measurement std
38
43
coeff_samples = az .extract (
39
44
self .prediction_model .idata .posterior , var_names = "sigma"
40
45
)
41
46
name = "sigma"
42
47
print (
43
- f" { name : <30} { coeff_samples .mean ().data :.2f} , 94% HDI [{ coeff_samples .quantile (0.03 ).data :.2f} , { coeff_samples .quantile (1 - 0.03 ).data :.2f} ]"
48
+ f"""
49
+ { name : <30} { coeff_samples .mean ().data :.2f} ,
50
+ 94% HDI [{ coeff_samples .quantile (0.03 ).data :.2f} ,
51
+ { coeff_samples .quantile (1 - 0.03 ).data :.2f} ]
52
+ """
44
53
)
45
54
46
55
@@ -120,8 +129,12 @@ def plot(self):
120
129
include_label = False ,
121
130
)
122
131
ax [0 ].plot (self .datapost .index , self .post_y , "k." )
132
+
123
133
ax [0 ].set (
124
- title = f"Pre-intervention Bayesian $R^2$: { self .score .r2 :.3f} (std = { self .score .r2_std :.3f} )"
134
+ title = f"""
135
+ Pre-intervention Bayesian $R^2$: { self .score .r2 :.3f}
136
+ (std = { self .score .r2_std :.3f} )
137
+ """
125
138
)
126
139
127
140
plot_xY (self .datapre .index , self .pre_impact , ax = ax [1 ])
@@ -200,7 +213,8 @@ class DifferenceInDifferences(ExperimentalDesign):
200
213
201
214
.. note::
202
215
203
- There is no pre/post intervention data distinction for DiD, we fit all the data available.
216
+ There is no pre/post intervention data distinction for DiD, we fit all the
217
+ data available.
204
218
205
219
"""
206
220
@@ -224,7 +238,8 @@ def __init__(
224
238
self .y , self .X = np .asarray (y ), np .asarray (X )
225
239
self .outcome_variable_name = y .design_info .column_names [0 ]
226
240
227
- # TODO: `treated` is a deterministic function of group and time, so this should be a function rather than supplied data
241
+ # TODO: `treated` is a deterministic function of group and time, so this should
242
+ # be a function rather than supplied data
228
243
229
244
# DEVIATION FROM SKL EXPERIMENT CODE =============================
230
245
# fit the model to the observed (pre-intervention) data
@@ -309,7 +324,8 @@ def plot(self):
309
324
showmedians = False ,
310
325
widths = 0.2 ,
311
326
)
312
- # Plot counterfactual - post-test for treatment group IF no treatment had occurred.
327
+ # Plot counterfactual - post-test for treatment group IF no treatment
328
+ # had occurred.
313
329
parts = ax .violinplot (
314
330
az .extract (
315
331
self .y_pred_counterfactual ,
@@ -381,13 +397,16 @@ class RegressionDiscontinuity(ExperimentalDesign):
381
397
382
398
:param data: A pandas dataframe
383
399
:param formula: A statistical model formula
384
- :param treatment_threshold: A scalar threshold value at which the treatment is applied
400
+ :param treatment_threshold: A scalar threshold value at which the treatment
401
+ is applied
385
402
:param prediction_model: A PyMC model
386
- :param running_variable_name: The name of the predictor variable that the treatment threshold is based upon
403
+ :param running_variable_name: The name of the predictor variable that the treatment
404
+ threshold is based upon
387
405
388
406
.. note::
389
407
390
- There is no pre/post intervention data distinction for the regression discontinuity design, we fit all the data available.
408
+ There is no pre/post intervention data distinction for the regression
409
+ discontinuity design, we fit all the data available.
391
410
"""
392
411
393
412
def __init__ (
@@ -412,7 +431,8 @@ def __init__(
412
431
self .y , self .X = np .asarray (y ), np .asarray (X )
413
432
self .outcome_variable_name = y .design_info .column_names [0 ]
414
433
415
- # TODO: `treated` is a deterministic function of x and treatment_threshold, so this could be a function rather than supplied data
434
+ # TODO: `treated` is a deterministic function of x and treatment_threshold, so
435
+ # this could be a function rather than supplied data
416
436
417
437
# DEVIATION FROM SKL EXPERIMENT CODE =============================
418
438
# fit the model to the observed (pre-intervention) data
@@ -435,8 +455,10 @@ def __init__(
435
455
(new_x ,) = build_design_matrices ([self ._x_design_info ], self .x_pred )
436
456
self .pred = self .prediction_model .predict (X = np .asarray (new_x ))
437
457
438
- # calculate discontinuity by evaluating the difference in model expectation on either side of the discontinuity
439
- # NOTE: `"treated": np.array([0, 1])`` assumes treatment is applied above (not below) the threshold
458
+ # calculate discontinuity by evaluating the difference in model expectation on
459
+ # either side of the discontinuity
460
+ # NOTE: `"treated": np.array([0, 1])`` assumes treatment is applied above
461
+ # (not below) the threshold
440
462
self .x_discon = pd .DataFrame (
441
463
{
442
464
self .running_variable_name : np .array (
@@ -457,7 +479,7 @@ def _is_treated(self, x):
457
479
458
480
.. warning::
459
481
460
- Assumes treatment is given to those ABOVE the treatment threshold.
482
+ Assumes treatment is given to those ABOVE the treatment threshold.
461
483
"""
462
484
return np .greater_equal (x , self .treatment_threshold )
463
485
@@ -479,10 +501,13 @@ def plot(self):
479
501
ax = ax ,
480
502
)
481
503
# create strings to compose title
482
- r2 = f"Bayesian $R^2$ on all data = { self .score .r2 :.3f} (std = { self .score .r2_std :.3f} )"
504
+ title_info = f"{ self .score .r2 :.3f} (std = { self .score .r2_std :.3f} )"
505
+ r2 = f"Bayesian $R^2$ on all data = { title_info } "
483
506
percentiles = self .discontinuity_at_threshold .quantile ([0.03 , 1 - 0.03 ]).values
484
507
ci = r"$CI_{94\%}$" + f"[{ percentiles [0 ]:.2f} , { percentiles [1 ]:.2f} ]"
485
- discon = f"Discontinuity at threshold = { self .discontinuity_at_threshold .mean ():.2f} , "
508
+ discon = f"""
509
+ Discontinuity at threshold = { self .discontinuity_at_threshold .mean ():.2f} ,
510
+ """
486
511
ax .set (title = r2 + "\n " + discon + ci )
487
512
# Intervention line
488
513
ax .axvline (
@@ -502,7 +527,7 @@ def summary(self):
502
527
print (f"Formula: { self .formula } " )
503
528
print (f"Running variable: { self .running_variable_name } " )
504
529
print (f"Threshold on running variable: { self .treatment_threshold } " )
505
- print (f "\n Results:" )
530
+ print ("\n Results:" )
506
531
print (
507
532
f"Discontinuity at threshold = { self .discontinuity_at_threshold .mean ():.2f} "
508
533
)
0 commit comments