@@ -45,6 +45,7 @@ class ExperimentalDesign:
45
45
"""Base class for experiment designs"""
46
46
47
47
model = None
48
+ expt_type = None
48
49
outcome_variable_name = None
49
50
50
51
def __init__ (self , model = None , ** kwargs ):
@@ -53,6 +54,17 @@ def __init__(self, model=None, **kwargs):
53
54
if self .model is None :
54
55
raise ValueError ("fitting_model not set or passed." )
55
56
57
+ def print_coefficients (self , round_to = None ) -> None :
58
+ """
59
+ Prints the model coefficients
60
+
61
+ :param round_to:
62
+ Number of decimals used to round results. Defaults to 2. Use "None" to return raw numbers.
63
+ """
64
+ print ("Model coefficients:" )
65
+ for name , val in zip (self .labels , self .model .coef_ [0 ]):
66
+ print (f"\t { name } \t \t { round_num (val , round_to )} " )
67
+
56
68
57
69
class PrePostFit (ExperimentalDesign , PrePostFitDataValidator ):
58
70
"""
@@ -95,6 +107,8 @@ def __init__(
95
107
super ().__init__ (model = model , ** kwargs )
96
108
self ._input_validation (data , treatment_time )
97
109
self .treatment_time = treatment_time
110
+ # set experiment type - usually done in subclasses
111
+ self .expt_type = "Pre-Post Fit"
98
112
# split data in to pre and post intervention
99
113
self .datapre = data [data .index < self .treatment_time ]
100
114
self .datapost = data [data .index >= self .treatment_time ]
@@ -103,10 +117,10 @@ def __init__(
103
117
104
118
# set things up with pre-intervention data
105
119
y , X = dmatrices (formula , self .datapre )
120
+ self .outcome_variable_name = y .design_info .column_names [0 ]
106
121
self ._y_design_info = y .design_info
107
122
self ._x_design_info = X .design_info
108
123
self .labels = X .design_info .column_names
109
- self .outcome_variable_name = y .design_info .column_names [0 ]
110
124
self .pre_y , self .pre_X = np .asarray (y ), np .asarray (X )
111
125
# process post-intervention data
112
126
(new_y , new_x ) = build_design_matrices (
@@ -222,6 +236,18 @@ def plot_coeffs(self):
222
236
palette = sns .color_palette ("husl" ),
223
237
)
224
238
239
+ def summary (self , round_to = None ) -> None :
240
+ """
241
+ Print text output summarising the results
242
+
243
+ :param round_to:
244
+ Number of decimals used to round results. Defaults to 2. Use "None" to return raw numbers.
245
+ """
246
+
247
+ print (f"{ self .expt_type :=^80} " )
248
+ print (f"Formula: { self .formula } " )
249
+ self .print_coefficients (round_to )
250
+
225
251
226
252
class InterruptedTimeSeries (PrePostFit ):
227
253
"""
@@ -351,6 +377,7 @@ def __init__(
351
377
):
352
378
super ().__init__ (model = model , ** kwargs )
353
379
self .data = data
380
+ self .expt_type = "Difference in Differences"
354
381
self .formula = formula
355
382
self .time_variable_name = time_variable_name
356
383
self .group_variable_name = group_variable_name
@@ -509,6 +536,24 @@ def plot(self, round_to=None):
509
536
ax .legend (fontsize = LEGEND_FONT_SIZE )
510
537
return (fig , ax )
511
538
539
+ def _causal_impact_summary_stat (self , round_to = None ) -> str :
540
+ causal_impact = f"{ round_num (self .causal_impact , round_to )} , "
541
+ return f"Causal impact = { causal_impact } "
542
+
543
+ def summary (self , round_to = None ) -> None :
544
+ """
545
+ Print text output summarising the results.
546
+
547
+ :param round_to:
548
+ Number of decimals used to round results. Defaults to 2. Use "None" to return raw numbers.
549
+ """
550
+
551
+ print (f"{ self .expt_type :=^80} " )
552
+ print (f"Formula: { self .formula } " )
553
+ print ("\n Results:" )
554
+ print (f"Causal impact = { round_num (self .causal_impact [0 ], round_to )} " )
555
+ self .print_coefficients (round_to )
556
+
512
557
513
558
class RegressionDiscontinuity (ExperimentalDesign , RDDataValidator ):
514
559
"""
@@ -687,16 +732,17 @@ def plot(self, round_to=None):
687
732
ax .legend (fontsize = LEGEND_FONT_SIZE )
688
733
return (fig , ax )
689
734
690
- def summary (self ):
735
+ def summary (self , round_to = None ):
691
736
"""
692
737
Print text output summarising the results
738
+
739
+ :param round_to:
740
+ Number of decimals used to round results. Defaults to 2. Use "None" to return raw numbers.
693
741
"""
694
742
print ("Difference in Differences experiment" )
695
743
print (f"Formula: { self .formula } " )
696
744
print (f"Running variable: { self .running_variable_name } " )
697
745
print (f"Threshold on running variable: { self .treatment_threshold } " )
698
746
print ("\n Results:" )
699
747
print (f"Discontinuity at threshold = { self .discontinuity_at_threshold :.2f} " )
700
- print ("Model coefficients:" )
701
- for name , val in zip (self .labels , self .model .coef_ [0 ]):
702
- print (f"\t { name } \t \t { val } " )
748
+ self .print_coefficients (round_to )
0 commit comments