|
106 | 106 | }, |
107 | 107 | { |
108 | 108 | "cell_type": "code", |
109 | | - "execution_count": 1, |
| 109 | + "execution_count": null, |
110 | 110 | "metadata": {}, |
111 | 111 | "outputs": [ |
112 | 112 | { |
|
163 | 163 | }, |
164 | 164 | { |
165 | 165 | "cell_type": "code", |
166 | | - "execution_count": 2, |
| 166 | + "execution_count": null, |
167 | 167 | "metadata": {}, |
168 | 168 | "outputs": [ |
169 | 169 | { |
|
190 | 190 | "\n", |
191 | 191 | "# Define intervention start (beginning of TV promo campaign)\n", |
192 | 192 | "intervention_start = date_range[n_weeks_pre]\n", |
| 193 | + "# Define intervention end (after 4-week promo campaign)\n", |
| 194 | + "promo_weeks = 4\n", |
| 195 | + "intervention_end = intervention_start + pd.Timedelta(weeks=promo_weeks)\n", |
193 | 196 | "print(f\"Pre-intervention period: {date_range[0]} to {date_range[n_weeks_pre - 1]}\")\n", |
194 | 197 | "print(f\"Intervention starts: {intervention_start}\")\n", |
195 | | - "print(f\"Post-intervention period: {intervention_start} to {date_range[-1]}\")\n", |
| 198 | + "print(f\"Intervention ends: {intervention_end}\")\n", |
| 199 | + "print(f\"Post-intervention period: {intervention_end} to {date_range[-1]}\")\n", |
196 | 200 | "print(f\"Total weeks: {n_total}\")" |
197 | 201 | ] |
198 | 202 | }, |
|
207 | 211 | }, |
208 | 212 | { |
209 | 213 | "cell_type": "code", |
210 | | - "execution_count": 3, |
| 214 | + "execution_count": null, |
211 | 215 | "metadata": {}, |
212 | 216 | "outputs": [ |
213 | 217 | { |
|
345 | 349 | "# 2. TV Promo: zero pre-intervention, high spend for 4 weeks during intervention\n", |
346 | 350 | "spend_data[\"tv_promo\"] = np.zeros(n_total)\n", |
347 | 351 | "# High spend during first 4 weeks of intervention (weeks 104-107)\n", |
348 | | - "promo_weeks = 4\n", |
349 | 352 | "for i in range(promo_weeks):\n", |
350 | 353 | " # Promo spend around £50,000/week (much higher than baseline)\n", |
351 | 354 | " spend_data[\"tv_promo\"][n_weeks_pre + i] = 50_000 + rng.normal(0, 3_000)\n", |
|
374 | 377 | }, |
375 | 378 | { |
376 | 379 | "cell_type": "code", |
377 | | - "execution_count": 4, |
| 380 | + "execution_count": null, |
378 | 381 | "metadata": {}, |
379 | 382 | "outputs": [ |
380 | 383 | { |
|
436 | 439 | }, |
437 | 440 | { |
438 | 441 | "cell_type": "code", |
439 | | - "execution_count": 5, |
| 442 | + "execution_count": null, |
440 | 443 | "metadata": {}, |
441 | 444 | "outputs": [], |
442 | 445 | "source": [ |
|
492 | 495 | }, |
493 | 496 | { |
494 | 497 | "cell_type": "code", |
495 | | - "execution_count": 6, |
| 498 | + "execution_count": null, |
496 | 499 | "metadata": {}, |
497 | 500 | "outputs": [ |
498 | 501 | { |
|
526 | 529 | }, |
527 | 530 | { |
528 | 531 | "cell_type": "code", |
529 | | - "execution_count": 7, |
| 532 | + "execution_count": null, |
530 | 533 | "metadata": {}, |
531 | 534 | "outputs": [ |
532 | 535 | { |
|
722 | 725 | }, |
723 | 726 | { |
724 | 727 | "cell_type": "code", |
725 | | - "execution_count": 8, |
| 728 | + "execution_count": null, |
726 | 729 | "metadata": { |
727 | 730 | "tags": [ |
728 | 731 | "hide-input" |
|
845 | 848 | }, |
846 | 849 | { |
847 | 850 | "cell_type": "code", |
848 | | - "execution_count": 9, |
| 851 | + "execution_count": null, |
849 | 852 | "metadata": { |
850 | 853 | "tags": [ |
851 | 854 | "hide-output" |
|
902 | 905 | "result = cp.InterruptedTimeSeries(\n", |
903 | 906 | " df,\n", |
904 | 907 | " treatment_time=intervention_start,\n", |
| 908 | + " treatment_end_time=intervention_end,\n", |
905 | 909 | " formula=\"sales ~ 1 + t + C(month) + C(week_of_month)\",\n", |
906 | 910 | " model=cp.pymc_models.LinearRegression(sample_kwargs={\"random_seed\": seed}),\n", |
907 | 911 | ")" |
|
911 | 915 | "cell_type": "markdown", |
912 | 916 | "metadata": {}, |
913 | 917 | "source": [ |
914 | | - "### Visualize the Results" |
| 918 | + "### Visualize the Results\n", |
| 919 | + "\n", |
| 920 | + "The plot now shows the three-period design with:\n", |
| 921 | + "- **Solid red line**: Intervention start (when the TV promo campaign began)\n", |
| 922 | + "- **Dashed orange line**: Intervention end (when the 4-week campaign ended)\n", |
| 923 | + "\n", |
| 924 | + "This allows us to visually distinguish between the intervention period (when the campaign was active) and the post-intervention period (after the campaign ended, showing any persistence effects from adstock)." |
915 | 925 | ] |
916 | 926 | }, |
917 | 927 | { |
918 | 928 | "cell_type": "code", |
919 | | - "execution_count": 10, |
| 929 | + "execution_count": null, |
920 | 930 | "metadata": {}, |
921 | 931 | "outputs": [ |
922 | 932 | { |
|
948 | 958 | }, |
949 | 959 | { |
950 | 960 | "cell_type": "code", |
951 | | - "execution_count": 11, |
| 961 | + "execution_count": null, |
952 | 962 | "metadata": {}, |
953 | 963 | "outputs": [ |
954 | 964 | { |
|
983 | 993 | "result.summary()" |
984 | 994 | ] |
985 | 995 | }, |
| 996 | + { |
| 997 | + "cell_type": "markdown", |
| 998 | + "metadata": {}, |
| 999 | + "source": [ |
| 1000 | + "### Period-Specific Effect Summaries\n", |
| 1001 | + "\n", |
| 1002 | + "With the three-period design, we can now analyze effects separately for the intervention period (when the campaign was active) and the post-intervention period (after the campaign ended). This helps us understand both the immediate impact and any persistence effects.\n" |
| 1003 | + ] |
| 1004 | + }, |
| 1005 | + { |
| 1006 | + "cell_type": "code", |
| 1007 | + "execution_count": null, |
| 1008 | + "metadata": {}, |
| 1009 | + "outputs": [], |
| 1010 | + "source": [ |
| 1011 | + "# Intervention period (during the 4-week campaign)\n", |
| 1012 | + "intervention_summary = result.effect_summary(period=\"intervention\")\n", |
| 1013 | + "print(\"Intervention Period Effect:\")\n", |
| 1014 | + "print(intervention_summary.text)\n", |
| 1015 | + "print(\"\\n\" + \"=\" * 60 + \"\\n\")\n", |
| 1016 | + "\n", |
| 1017 | + "# Post-intervention period (after campaign ended)\n", |
| 1018 | + "post_summary = result.effect_summary(period=\"post\")\n", |
| 1019 | + "print(\"Post-Intervention Period Effect:\")\n", |
| 1020 | + "print(post_summary.text)\n", |
| 1021 | + "print(\"\\n\" + \"=\" * 60 + \"\\n\")\n", |
| 1022 | + "\n", |
| 1023 | + "# Comparison summary (shows persistence metrics)\n", |
| 1024 | + "comparison_summary = result.effect_summary(period=\"comparison\")\n", |
| 1025 | + "print(\"Effect Persistence Analysis:\")\n", |
| 1026 | + "print(comparison_summary.text)" |
| 1027 | + ] |
| 1028 | + }, |
| 1029 | + { |
| 1030 | + "cell_type": "markdown", |
| 1031 | + "metadata": {}, |
| 1032 | + "source": [ |
| 1033 | + "### Detailed Persistence Analysis\n", |
| 1034 | + "\n", |
| 1035 | + "The `analyze_persistence()` method provides a comprehensive summary of how effects persist after the campaign ends:\n" |
| 1036 | + ] |
| 1037 | + }, |
| 1038 | + { |
| 1039 | + "cell_type": "code", |
| 1040 | + "execution_count": null, |
| 1041 | + "metadata": {}, |
| 1042 | + "outputs": [], |
| 1043 | + "source": [ |
| 1044 | + "persistence = result.analyze_persistence()\n", |
| 1045 | + "\n", |
| 1046 | + "# Access results programmatically if needed\n", |
| 1047 | + "print(\n", |
| 1048 | + " f\"\\nPersistence ratio: {persistence['persistence_ratio']:.3f} ({persistence['persistence_ratio'] * 100:.1f}%)\"\n", |
| 1049 | + ")\n", |
| 1050 | + "print(f\"Mean effect during campaign: {persistence['mean_effect_during']:.2f}\")\n", |
| 1051 | + "print(f\"Mean effect post-campaign: {persistence['mean_effect_post']:.2f}\")" |
| 1052 | + ] |
| 1053 | + }, |
986 | 1054 | { |
987 | 1055 | "cell_type": "markdown", |
988 | 1056 | "metadata": {}, |
|
1013 | 1081 | }, |
1014 | 1082 | { |
1015 | 1083 | "cell_type": "code", |
1016 | | - "execution_count": 12, |
| 1084 | + "execution_count": null, |
1017 | 1085 | "metadata": { |
1018 | 1086 | "tags": [ |
1019 | 1087 | "hide-input" |
|
1181 | 1249 | }, |
1182 | 1250 | { |
1183 | 1251 | "cell_type": "code", |
1184 | | - "execution_count": 13, |
| 1252 | + "execution_count": null, |
1185 | 1253 | "metadata": { |
1186 | 1254 | "tags": [ |
1187 | 1255 | "hide-input" |
|
1273 | 1341 | }, |
1274 | 1342 | { |
1275 | 1343 | "cell_type": "code", |
1276 | | - "execution_count": 14, |
| 1344 | + "execution_count": null, |
1277 | 1345 | "metadata": { |
1278 | 1346 | "tags": [ |
1279 | 1347 | "hide-input" |
|
0 commit comments