-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsummary.py
More file actions
129 lines (110 loc) · 4.83 KB
/
summary.py
File metadata and controls
129 lines (110 loc) · 4.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"""Summary and report formatting for CausalImpact results."""
from __future__ import annotations
from causal_impact.analysis import CausalImpactResults
class SummaryFormatter:
"""Format CausalImpact results as text summary or report."""
@staticmethod
def summary(results: CausalImpactResults, digits: int = 2) -> str:
fmt = f".{digits}f"
avg_actual = format(results.actual.mean(), fmt)
cum_actual = format(results.actual.sum(), fmt)
avg_pred = format(results.predictions_mean.mean(), fmt)
avg_pred_sd = format(results.average_prediction_sd, fmt)
cum_pred = format(results.predictions_mean.sum(), fmt)
cum_pred_sd = format(results.cumulative_prediction_sd, fmt)
avg_pred_ci = (
f"[{format(results.average_prediction_lower, fmt)}, "
f"{format(results.average_prediction_upper, fmt)}]"
)
cum_pred_ci = (
f"[{format(results.cumulative_prediction_lower, fmt)}, "
f"{format(results.cumulative_prediction_upper, fmt)}]"
)
avg_eff = format(results.point_effect_mean, fmt)
avg_eff_sd = format(results.average_effect_sd, fmt)
cum_eff = format(results.cumulative_effect_total, fmt)
cum_eff_sd = format(results.cumulative_effect_sd, fmt)
avg_eff_ci = (
f"[{format(results.ci_lower, fmt)}, {format(results.ci_upper, fmt)}]"
)
cum_eff_ci = (
f"[{format(results.cumulative_effect_lower[-1], fmt)}, "
f"{format(results.cumulative_effect_upper[-1], fmt)}]"
)
rel_m = format(results.relative_effect_mean * 100, fmt)
rel_sd = format(results.relative_effect_sd * 100, fmt)
rel_lo = format(results.relative_effect_lower * 100, fmt)
rel_hi = format(results.relative_effect_upper * 100, fmt)
p_val = format(results.p_value, f".{max(digits, 3)}f")
prob = format((1 - results.p_value) * 100, fmt)
pred_row = (
f"Prediction (s.d.) "
f"{avg_pred} ({avg_pred_sd}) "
f"{cum_pred} ({cum_pred_sd})"
)
eff_row = (
f"Absolute effect (s.d.) "
f"{avg_eff} ({avg_eff_sd}) "
f"{cum_eff} ({cum_eff_sd})"
)
rel_row = f"Relative effect (s.d.) {rel_m}% ({rel_sd}%) {rel_m}% ({rel_sd}%)"
rel_ci_row = (
f"95% CI [{rel_lo}%, {rel_hi}%] [{rel_lo}%, {rel_hi}%]"
)
lines = [
"Posterior inference {CausalImpact}",
"",
" Average Cumulative",
f"Actual {avg_actual} {cum_actual}",
pred_row,
f"95% CI {avg_pred_ci} {cum_pred_ci}",
"",
eff_row,
f"95% CI {avg_eff_ci} {cum_eff_ci}",
"",
rel_row,
rel_ci_row,
"",
f"Posterior tail-area probability p: {p_val}",
f"Posterior prob. of a causal effect: {prob}%",
]
return "\n".join(lines)
@staticmethod
def report(results: CausalImpactResults) -> str:
is_significant = results.p_value < 0.05
direction = "increase" if results.point_effect_mean >= 0 else "decrease"
lines = [
"Analysis report {CausalImpact}",
"",
f"During the post-intervention period, the response variable showed "
f"a {direction} compared to what would have been expected without "
f"the intervention.",
"",
f"The average causal effect was {results.point_effect_mean:.2f} "
f"(95% CI [{results.ci_lower:.2f}, {results.ci_upper:.2f}]).",
"",
f"The cumulative effect over the entire post-period was "
f"{results.cumulative_effect_total:.2f}.",
"",
f"The relative effect was {results.relative_effect_mean * 100:.1f}%.",
"",
]
p = results.p_value
if is_significant:
lines.append(
f"This effect is statistically significant "
f"(p = {p:.4f}). The probability of obtaining "
f"an effect of this magnitude by chance is very "
f"small. Hence, the causal effect can be "
f"considered statistically significant."
)
else:
lines.append(
f"This effect is not statistically significant "
f"(p = {p:.4f}). The apparent effect could be "
f"the result of random fluctuations that are "
f"not related to the intervention. This is "
f"often the case when the intervention effect "
f"is small relative to the noise level."
)
return "\n".join(lines)