├── Class Exercises
├── L2 - Exercises
│ ├── Multiple_Testing.ipynb
│ ├── exp_data.csv
│ ├── potential_outcomes.xlsx
│ ├── t_z_tests.ipynb
│ └── ttest.xlsx
├── L3
│ ├── CI-Bootstrap.ipynb
│ ├── CIMean0.png
│ ├── CIMeanSmall.png
│ ├── Power_SampleSize.png
│ ├── power_analysis.ipynb
│ └── skewness
│ │ ├── exp_data_2.csv
│ │ └── skew.ipynb
├── L4
│ └── s4
│ │ ├── AA.ipynb
│ │ ├── SRM Tests.xlsx
│ │ └── sample_data_aatest.csv
├── L5
│ ├── AA.ipynb
│ ├── Heterogenous.ipynb
│ ├── Interleaving.xlsx
│ ├── cluster.ipynb
│ ├── exp_data_cluster.csv
│ ├── sample_data_aatest.csv
│ ├── sample_data_segments.csv
│ └── variance_lift.ipynb
├── L6
│ ├── Interleaving.xlsx
│ ├── Split Traffic.ipynb
│ ├── cluster.ipynb
│ ├── exp_data_cluster.csv
│ ├── variance_lift.ipynb
│ └── ~$Interleaving.xlsx
├── L7
│ ├── Control_Variables.ipynb
│ └── exp_data_3.csv
└── Readme
├── README.md
└── Slides
├── Guest_Lecture_KennyXie.pdf
├── Guest_Lecture_Tencent.pdf
├── JasonMa_Tencent_PresentationHK.pdf
├── L1 - AB -Testing Overview_SH.pdf
├── L2-Statistics1_SH.pdf
├── L3-Statistics2_SH.pdf
├── L4-InternalExternalValidity_SH.pdf
├── L5-Improve_SensitivityI_SH.pdf
├── L6 - ImproveSensitivity II-SH.pdf
├── L7- ObservationalCausal-SH.pdf
└── Readme.md
/Class Exercises/L2 - Exercises/Multiple_Testing.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "### Import Data"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {},
14 | "outputs": [
15 | {
16 | "name": "stdout",
17 | "output_type": "stream",
18 | "text": [
19 | "Requirement already satisfied: termcolor in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (1.1.0)\n",
20 | "Note: you may need to restart the kernel to use updated packages.\n"
21 | ]
22 | }
23 | ],
24 | "source": [
25 | "pip install termcolor"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": 2,
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "from termcolor import colored, cprint\n",
35 | "import itertools\n",
36 | "import numpy as np, statsmodels.stats.api as sms\n",
37 | "import matplotlib.pyplot as plt\n",
38 | "from matplotlib.ticker import NullFormatter\n",
39 | "import pandas as pd\n",
40 | "import matplotlib.ticker as ticker\n",
41 | "from sklearn import preprocessing\n",
42 | "from numpy import random"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": 3,
48 | "metadata": {},
49 | "outputs": [],
50 | "source": [
51 | "df = pd.read_csv('exp_data.csv')"
52 | ]
53 | },
54 | {
55 | "cell_type": "code",
56 | "execution_count": 4,
57 | "metadata": {},
58 | "outputs": [
59 | {
60 | "data": {
61 | "text/html": [
62 | "
\n",
63 | "\n",
76 | "
\n",
77 | " \n",
78 | " \n",
79 | " | \n",
80 | " Uin | \n",
81 | " gender | \n",
82 | " age | \n",
83 | " device | \n",
84 | " has_interest_online | \n",
85 | " interestss_TVShows | \n",
86 | " interests_Travel | \n",
87 | " interests_Society | \n",
88 | " interests_Pets | \n",
89 | " interests_Natural | \n",
90 | " ... | \n",
91 | " interests_Fashion | \n",
92 | " interests_Tech | \n",
93 | " interests_Entertainment | \n",
94 | " interests_Health | \n",
95 | " interests_Cartoon | \n",
96 | " interests_Finance | \n",
97 | " interests_Realestate | \n",
98 | " interests_Videogames | \n",
99 | " interests_Art | \n",
100 | " Group | \n",
101 | "
\n",
102 | " \n",
103 | " \n",
104 | " \n",
105 | " 0 | \n",
106 | " 137f94de7d47cb5bbb2bf3265558f5b8 | \n",
107 | " 2 | \n",
108 | " 41 | \n",
109 | " 2 | \n",
110 | " 1 | \n",
111 | " 0.796494 | \n",
112 | " 0.0 | \n",
113 | " 4.110483 | \n",
114 | " 0.000000 | \n",
115 | " 0.0 | \n",
116 | " ... | \n",
117 | " 0.000000 | \n",
118 | " 0.000000 | \n",
119 | " 0.000000 | \n",
120 | " 2.261562 | \n",
121 | " 0.0 | \n",
122 | " 0.000000 | \n",
123 | " 0.000000 | \n",
124 | " 0.0 | \n",
125 | " 0.000000 | \n",
126 | " 0 | \n",
127 | "
\n",
128 | " \n",
129 | " 1 | \n",
130 | " 337d0ac1a7b86b8acfb107490cfcc37b | \n",
131 | " 2 | \n",
132 | " 27 | \n",
133 | " 14 | \n",
134 | " 1 | \n",
135 | " 38.714942 | \n",
136 | " 0.0 | \n",
137 | " 369.548390 | \n",
138 | " 0.000000 | \n",
139 | " 0.0 | \n",
140 | " ... | \n",
141 | " 62.609615 | \n",
142 | " 120.487872 | \n",
143 | " 189.237181 | \n",
144 | " 291.606592 | \n",
145 | " 0.0 | \n",
146 | " 1125.921014 | \n",
147 | " 0.000000 | \n",
148 | " 0.0 | \n",
149 | " 0.000000 | \n",
150 | " 0 | \n",
151 | "
\n",
152 | " \n",
153 | " 2 | \n",
154 | " e7065ba7a831950c4711dd3fd3904ffe | \n",
155 | " 2 | \n",
156 | " 37 | \n",
157 | " 2 | \n",
158 | " 1 | \n",
159 | " 0.000000 | \n",
160 | " 0.0 | \n",
161 | " 6.930192 | \n",
162 | " 0.000000 | \n",
163 | " 0.0 | \n",
164 | " ... | \n",
165 | " 0.000000 | \n",
166 | " 0.000000 | \n",
167 | " 1.448855 | \n",
168 | " 5.620250 | \n",
169 | " 0.0 | \n",
170 | " 1.617699 | \n",
171 | " 0.000000 | \n",
172 | " 0.0 | \n",
173 | " 1.293002 | \n",
174 | " 1 | \n",
175 | "
\n",
176 | " \n",
177 | " 3 | \n",
178 | " 36498084c61db712ad18e0c6def8579e | \n",
179 | " 1 | \n",
180 | " 33 | \n",
181 | " 1 | \n",
182 | " 1 | \n",
183 | " 3.179579 | \n",
184 | " 0.0 | \n",
185 | " 455.546589 | \n",
186 | " 3.614626 | \n",
187 | " 0.0 | \n",
188 | " ... | \n",
189 | " 0.000000 | \n",
190 | " 0.000000 | \n",
191 | " 0.000000 | \n",
192 | " 158.125969 | \n",
193 | " 0.0 | \n",
194 | " 0.000000 | \n",
195 | " 0.000000 | \n",
196 | " 0.0 | \n",
197 | " 0.000000 | \n",
198 | " 2 | \n",
199 | "
\n",
200 | " \n",
201 | " 4 | \n",
202 | " 400dac9d50c6ca15e26d67590a758426 | \n",
203 | " 2 | \n",
204 | " 62 | \n",
205 | " 0 | \n",
206 | " 0 | \n",
207 | " 0.000000 | \n",
208 | " 0.0 | \n",
209 | " 5.914961 | \n",
210 | " 0.000000 | \n",
211 | " 0.0 | \n",
212 | " ... | \n",
213 | " 0.000000 | \n",
214 | " 0.000000 | \n",
215 | " 0.000000 | \n",
216 | " 1.678389 | \n",
217 | " 0.0 | \n",
218 | " 0.000000 | \n",
219 | " 1.146208 | \n",
220 | " 0.0 | \n",
221 | " 0.492551 | \n",
222 | " 0 | \n",
223 | "
\n",
224 | " \n",
225 | "
\n",
226 | "
5 rows × 28 columns
\n",
227 | "
"
228 | ],
229 | "text/plain": [
230 | " Uin gender age device has_interest_online \\\n",
231 | "0 137f94de7d47cb5bbb2bf3265558f5b8 2 41 2 1 \n",
232 | "1 337d0ac1a7b86b8acfb107490cfcc37b 2 27 14 1 \n",
233 | "2 e7065ba7a831950c4711dd3fd3904ffe 2 37 2 1 \n",
234 | "3 36498084c61db712ad18e0c6def8579e 1 33 1 1 \n",
235 | "4 400dac9d50c6ca15e26d67590a758426 2 62 0 0 \n",
236 | "\n",
237 | " interestss_TVShows interests_Travel interests_Society interests_Pets \\\n",
238 | "0 0.796494 0.0 4.110483 0.000000 \n",
239 | "1 38.714942 0.0 369.548390 0.000000 \n",
240 | "2 0.000000 0.0 6.930192 0.000000 \n",
241 | "3 3.179579 0.0 455.546589 3.614626 \n",
242 | "4 0.000000 0.0 5.914961 0.000000 \n",
243 | "\n",
244 | " interests_Natural ... interests_Fashion interests_Tech \\\n",
245 | "0 0.0 ... 0.000000 0.000000 \n",
246 | "1 0.0 ... 62.609615 120.487872 \n",
247 | "2 0.0 ... 0.000000 0.000000 \n",
248 | "3 0.0 ... 0.000000 0.000000 \n",
249 | "4 0.0 ... 0.000000 0.000000 \n",
250 | "\n",
251 | " interests_Entertainment interests_Health interests_Cartoon \\\n",
252 | "0 0.000000 2.261562 0.0 \n",
253 | "1 189.237181 291.606592 0.0 \n",
254 | "2 1.448855 5.620250 0.0 \n",
255 | "3 0.000000 158.125969 0.0 \n",
256 | "4 0.000000 1.678389 0.0 \n",
257 | "\n",
258 | " interests_Finance interests_Realestate interests_Videogames \\\n",
259 | "0 0.000000 0.000000 0.0 \n",
260 | "1 1125.921014 0.000000 0.0 \n",
261 | "2 1.617699 0.000000 0.0 \n",
262 | "3 0.000000 0.000000 0.0 \n",
263 | "4 0.000000 1.146208 0.0 \n",
264 | "\n",
265 | " interests_Art Group \n",
266 | "0 0.000000 0 \n",
267 | "1 0.000000 0 \n",
268 | "2 1.293002 1 \n",
269 | "3 0.000000 2 \n",
270 | "4 0.492551 0 \n",
271 | "\n",
272 | "[5 rows x 28 columns]"
273 | ]
274 | },
275 | "execution_count": 4,
276 | "metadata": {},
277 | "output_type": "execute_result"
278 | }
279 | ],
280 | "source": [
281 | "df.head()"
282 | ]
283 | },
284 | {
285 | "cell_type": "code",
286 | "execution_count": 5,
287 | "metadata": {},
288 | "outputs": [
289 | {
290 | "data": {
291 | "text/plain": [
292 | "Index(['Uin', 'gender', 'age', 'device', 'has_interest_online',\n",
293 | " 'interestss_TVShows', 'interests_Travel', 'interests_Society',\n",
294 | " 'interests_Pets', 'interests_Natural', 'interests_Cars',\n",
295 | " 'interests_Foods', 'interests_Music', 'interests_Digital',\n",
296 | " 'interests_Life', 'interests_Sports', 'interests_Reading',\n",
297 | " 'interests_Childproducts', 'interests_Fashion', 'interests_Tech',\n",
298 | " 'interests_Entertainment', 'interests_Health', 'interests_Cartoon',\n",
299 | " 'interests_Finance', 'interests_Realestate', 'interests_Videogames',\n",
300 | " 'interests_Art', 'Group'],\n",
301 | " dtype='object')"
302 | ]
303 | },
304 | "execution_count": 5,
305 | "metadata": {},
306 | "output_type": "execute_result"
307 | }
308 | ],
309 | "source": [
310 | "df.columns"
311 | ]
312 | },
313 | {
314 | "cell_type": "code",
315 | "execution_count": 6,
316 | "metadata": {},
317 | "outputs": [
318 | {
319 | "data": {
320 | "text/plain": [
321 | "(10000, 28)"
322 | ]
323 | },
324 | "execution_count": 6,
325 | "metadata": {},
326 | "output_type": "execute_result"
327 | }
328 | ],
329 | "source": [
330 | "df.shape"
331 | ]
332 | },
333 | {
334 | "cell_type": "markdown",
335 | "metadata": {},
336 | "source": [
337 | "### Compare Age between Group 0 vs. 1"
338 | ]
339 | },
340 | {
341 | "cell_type": "code",
342 | "execution_count": 6,
343 | "metadata": {},
344 | "outputs": [],
345 | "source": [
346 | "age_0 = df[df['Group'] == 0]['age']\n",
347 | "age_1 = df[df['Group'] == 1]['age']"
348 | ]
349 | },
350 | {
351 | "cell_type": "code",
352 | "execution_count": 7,
353 | "metadata": {},
354 | "outputs": [
355 | {
356 | "name": "stdout",
357 | "output_type": "stream",
358 | "text": [
359 | "(-0.2258780702654209, 0.8213030931691397, 6750.0)\n"
360 | ]
361 | }
362 | ],
363 | "source": [
364 | "cm_age = sms.CompareMeans(sms.DescrStatsW(age_0), sms.DescrStatsW(age_1))\n",
365 | "print(cm_age.ttest_ind(alternative='two-sided', usevar='pooled'))"
366 | ]
367 | },
368 | {
369 | "cell_type": "markdown",
370 | "metadata": {},
371 | "source": [
372 | "### Multiple Testing with t tests"
373 | ]
374 | },
375 | {
376 | "cell_type": "code",
377 | "execution_count": 8,
378 | "metadata": {},
379 | "outputs": [],
380 | "source": [
381 | "def multi_cm(x):\n",
382 | " x0 = df[df['Group'] == 0][x]\n",
383 | " x1 = df[df['Group'] == 1][x]\n",
384 | " x2 = df[df['Group'] == 2][x]\n",
385 | " cm01 = sms.CompareMeans(sms.DescrStatsW(x0), sms.DescrStatsW(x1))\n",
386 | " cm02 = sms.CompareMeans(sms.DescrStatsW(x0), sms.DescrStatsW(x2))\n",
387 | " cm12 = sms.CompareMeans(sms.DescrStatsW(x1), sms.DescrStatsW(x2))\n",
388 | " cprint(x,'red', 'on_yellow')\n",
389 | " print(cm01.ttest_ind(alternative='two-sided', usevar='pooled')) \n",
390 | " print(cm02.ttest_ind(alternative='two-sided', usevar='pooled')) \n",
391 | " print(cm12.ttest_ind(alternative='two-sided', usevar='pooled')) "
392 | ]
393 | },
394 | {
395 | "cell_type": "code",
396 | "execution_count": 9,
397 | "metadata": {},
398 | "outputs": [
399 | {
400 | "name": "stdout",
401 | "output_type": "stream",
402 | "text": [
403 | "\u001b[43m\u001b[31mgender\u001b[0m\n",
404 | "(1.338773515763321, 0.18068950041259244, 6750.0)\n",
405 | "(0.9053695111401618, 0.36530258109856395, 6626.0)\n",
406 | "(-0.41833581824238186, 0.6757151790218867, 6618.0)\n",
407 | "\u001b[43m\u001b[31mage\u001b[0m\n",
408 | "(-0.2258780702654209, 0.8213030931691397, 6750.0)\n",
409 | "(0.9497330944934246, 0.3422825277496915, 6626.0)\n",
410 | "(1.1687121493699624, 0.24256172111339383, 6618.0)\n",
411 | "\u001b[43m\u001b[31mdevice\u001b[0m\n",
412 | "(0.10889071847020237, 0.9132924051645153, 6750.0)\n",
413 | "(0.5134641434648958, 0.6076438065780314, 6626.0)\n",
414 | "(0.41388040743233595, 0.6789751051271262, 6618.0)\n",
415 | "\u001b[43m\u001b[31mhas_interest_online\u001b[0m\n",
416 | "(-1.2845094396946113, 0.19900784380497932, 6750.0)\n",
417 | "(-1.6808531965006905, 0.0928385650413649, 6626.0)\n",
418 | "(-0.40792621277474284, 0.6833410435536809, 6618.0)\n",
419 | "\u001b[43m\u001b[31minterestss_TVShows\u001b[0m\n",
420 | "(-0.5234272052816967, 0.6006941789213049, 6750.0)\n",
421 | "(0.23350129033532566, 0.8153793808681323, 6626.0)\n",
422 | "(0.6736860794427328, 0.5005344408716177, 6618.0)\n",
423 | "\u001b[43m\u001b[31minterests_Travel\u001b[0m\n",
424 | "(0.06482087845276627, 0.9483185373224183, 6750.0)\n",
425 | "(-0.5013152001110853, 0.6161659636359065, 6626.0)\n",
426 | "(-0.5394472710402294, 0.5895964190860086, 6618.0)\n",
427 | "\u001b[43m\u001b[31minterests_Society\u001b[0m\n",
428 | "(-0.6847791455098242, 0.4935068089879331, 6750.0)\n",
429 | "(1.2351380997665236, 0.2168229057175556, 6626.0)\n",
430 | "(1.9446141119994387, 0.0518637481483557, 6618.0)\n",
431 | "\u001b[43m\u001b[31minterests_Pets\u001b[0m\n",
432 | "(0.9707276306009271, 0.3317187109438976, 6750.0)\n",
433 | "(0.31475064308464806, 0.7529608999543934, 6626.0)\n",
434 | "(-0.6519002384228214, 0.5144881696069725, 6618.0)\n",
435 | "\u001b[43m\u001b[31minterests_Natural\u001b[0m\n",
436 | "(-1.0612678410854939, 0.2886061658249812, 6750.0)\n",
437 | "(-1.8427709795172764, 0.06540709922408983, 6626.0)\n",
438 | "(-1.3663540716083276, 0.17187427850386666, 6618.0)\n",
439 | "\u001b[43m\u001b[31minterests_Cars\u001b[0m\n",
440 | "(0.6187802423559168, 0.5360820204981972, 6750.0)\n",
441 | "(-1.3893444622272728, 0.1647747146564894, 6626.0)\n",
442 | "(-1.7725664974397572, 0.07634656053156527, 6618.0)\n",
443 | "\u001b[43m\u001b[31minterests_Foods\u001b[0m\n",
444 | "(1.0184637185219496, 0.30849413623581146, 6750.0)\n",
445 | "(2.0767837483140696, 0.0378599681773576, 6626.0)\n",
446 | "(1.016626487214549, 0.3093683127187254, 6618.0)\n",
447 | "\u001b[43m\u001b[31minterests_Music\u001b[0m\n",
448 | "(-0.3262239225314997, 0.7442650563623125, 6750.0)\n",
449 | "(0.715621661229616, 0.4742502108804256, 6626.0)\n",
450 | "(0.9673603471637798, 0.33339927465462404, 6618.0)\n",
451 | "\u001b[43m\u001b[31minterests_Digital\u001b[0m\n",
452 | "(-1.7427156587400412, 0.08142883367459604, 6750.0)\n",
453 | "(-2.227313101078629, 0.025959817302320727, 6626.0)\n",
454 | "(-0.45167712090086354, 0.6515164041179344, 6618.0)\n",
455 | "\u001b[43m\u001b[31minterests_Life\u001b[0m\n",
456 | "(0.27387057610143695, 0.7841924640867347, 6750.0)\n",
457 | "(1.7190916772349614, 0.08564438610483052, 6626.0)\n",
458 | "(1.4489976215244424, 0.14738562626501506, 6618.0)\n"
459 | ]
460 | }
461 | ],
462 | "source": [
463 | "var = df.columns\n",
464 | "for i in range(14):\n",
465 | " multi_cm(var[i+1])"
466 | ]
467 | },
468 | {
469 | "cell_type": "markdown",
470 | "metadata": {},
471 | "source": [
472 | "### Multiple Testing with CIs"
473 | ]
474 | },
475 | {
476 | "cell_type": "code",
477 | "execution_count": 10,
478 | "metadata": {},
479 | "outputs": [],
480 | "source": [
481 | "def multi_cm(x):\n",
482 | " x0 = df[df['Group'] == 0][x]\n",
483 | " x1 = df[df['Group'] == 1][x]\n",
484 | " x2 = df[df['Group'] == 2][x]\n",
485 | " cm01 = sms.CompareMeans(sms.DescrStatsW(x0), sms.DescrStatsW(x1))\n",
486 | " cm02 = sms.CompareMeans(sms.DescrStatsW(x0), sms.DescrStatsW(x2))\n",
487 | " cm12 = sms.CompareMeans(sms.DescrStatsW(x1), sms.DescrStatsW(x2))\n",
488 | " cprint(x,'red', 'on_yellow')\n",
489 | " print(cm01.zconfint_diff(alpha=0.05, alternative='two-sided', usevar='pooled'))\n",
490 | " print(cm02.zconfint_diff(alpha=0.05, alternative='two-sided', usevar='pooled'))\n",
491 | " print(cm12.zconfint_diff(alpha=0.05, alternative='two-sided', usevar='pooled'))"
492 | ]
493 | },
494 | {
495 | "cell_type": "code",
496 | "execution_count": 11,
497 | "metadata": {},
498 | "outputs": [
499 | {
500 | "name": "stdout",
501 | "output_type": "stream",
502 | "text": [
503 | "\u001b[43m\u001b[31mgender\u001b[0m\n",
504 | "(-0.00755761848672714, 0.04013358344703349)\n",
505 | "(-0.012993350685755072, 0.03530293765051445)\n",
506 | "(-0.029182923978018634, 0.018916545982471663)\n",
507 | "\u001b[43m\u001b[31mage\u001b[0m\n",
508 | "(-0.7642663066007759, 0.6063125348501205)\n",
509 | "(-0.3598776790635133, 1.0365304029973976)\n",
510 | "(-0.28252633538176, 1.1171328310662996)\n",
511 | "\u001b[43m\u001b[31mdevice\u001b[0m\n",
512 | "(-0.0779825235473426, 0.08715727980668687)\n",
513 | "(-0.06048222514523573, 0.1034209839991136)\n",
514 | "(-0.06306407475614212, 0.09682807735067572)\n",
515 | "\u001b[43m\u001b[31mhas_interest_online\u001b[0m\n",
516 | "(-0.03812695208476372, 0.007937504703966848)\n",
517 | "(-0.04324119211221372, 0.0033149379949782252)\n",
518 | "(-0.028259631892169006, 0.018522825155730387)\n",
519 | "\u001b[43m\u001b[31minterestss_TVShows\u001b[0m\n",
520 | "(-2.2203402873774665, 1.2843729567695452)\n",
521 | "(-1.4700744002895791, 1.867724775833508)\n",
522 | "(-1.2731471241684726, 2.606764830320323)\n",
523 | "\u001b[43m\u001b[31minterests_Travel\u001b[0m\n",
524 | "(-0.9902440329339546, 1.0579840235354163)\n",
525 | "(-1.4302725552067663, 0.8476345702936463)\n",
526 | "(-1.5066922381941543, 0.8563142626795726)\n",
527 | "\u001b[43m\u001b[31minterests_Society\u001b[0m\n",
528 | "(-18.002333285345074, 8.679974327869173)\n",
529 | "(-4.839505220035202, 21.333003608691918)\n",
530 | "(-0.10188914020129225, 25.91774648633391)\n",
531 | "\u001b[43m\u001b[31minterests_Pets\u001b[0m\n",
532 | "(-0.5937913501693202, 1.7591542447413473)\n",
533 | "(-1.1483538385538703, 1.5877437949394773)\n",
534 | "(-1.4543197197440776, 0.7283467815576574)\n",
535 | "\u001b[43m\u001b[31minterests_Natural\u001b[0m\n",
536 | "(-0.01627155560873128, 0.00484013975675153)\n",
537 | "(-0.04742375429868649, 0.0014615092369716746)\n",
538 | "(-0.042031755560590536, 0.007500926350855475)\n",
539 | "\u001b[43m\u001b[31minterests_Cars\u001b[0m\n",
540 | "(-1.2575971667146193, 2.418029186772535)\n",
541 | "(-4.837229964177681, 0.824115752653428)\n",
542 | "(-5.447022449426756, 0.2734762178445882)\n",
543 | "\u001b[43m\u001b[31minterests_Foods\u001b[0m\n",
544 | "(-1.0414254980968631, 3.2945402844391736)\n",
545 | "(0.11601246330335302, 4.008851183165975)\n",
546 | "(-0.8684068866688182, 2.740155746795835)\n",
547 | "\u001b[43m\u001b[31minterests_Music\u001b[0m\n",
548 | "(-2.809851661049954, 2.007957094322481)\n",
549 | "(-1.4951288755817855, 3.2148270481067356)\n",
550 | "(-1.2936968795040942, 3.815289618756517)\n",
551 | "\u001b[43m\u001b[31minterests_Digital\u001b[0m\n",
552 | "(-2.8099268125223746, 0.1648675971060436)\n",
553 | "(-3.342235657330044, -0.21339494186324837)\n",
554 | "(-2.430908360130023, 1.520336976353062)\n",
555 | "\u001b[43m\u001b[31minterests_Life\u001b[0m\n",
556 | "(-3.7439323420447472, 4.9601792027096145)\n",
557 | "(-0.5141038063684737, 7.852361862272196)\n",
558 | "(-1.0794157796756902, 7.201426974914545)\n"
559 | ]
560 | }
561 | ],
562 | "source": [
563 | "for i in range(14):\n",
564 | " multi_cm(var[i+1])"
565 | ]
566 | },
567 | {
568 | "cell_type": "code",
569 | "execution_count": null,
570 | "metadata": {},
571 | "outputs": [],
572 | "source": []
573 | },
574 | {
575 | "cell_type": "code",
576 | "execution_count": null,
577 | "metadata": {},
578 | "outputs": [],
579 | "source": []
580 | }
581 | ],
582 | "metadata": {
583 | "kernelspec": {
584 | "display_name": "Python 3",
585 | "language": "python",
586 | "name": "python3"
587 | },
588 | "language_info": {
589 | "codemirror_mode": {
590 | "name": "ipython",
591 | "version": 3
592 | },
593 | "file_extension": ".py",
594 | "mimetype": "text/x-python",
595 | "name": "python",
596 | "nbconvert_exporter": "python",
597 | "pygments_lexer": "ipython3",
598 | "version": "3.8.5"
599 | }
600 | },
601 | "nbformat": 4,
602 | "nbformat_minor": 4
603 | }
604 |
--------------------------------------------------------------------------------
/Class Exercises/L2 - Exercises/potential_outcomes.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Class Exercises/L2 - Exercises/potential_outcomes.xlsx
--------------------------------------------------------------------------------
/Class Exercises/L2 - Exercises/t_z_tests.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Compare Means\n",
8 | "\n",
9 | "#### A/B Test Example \n",
10 | "\n",
11 | "Considering WeChat wants to use algorithms to rank the feeds on WeChat Moments instead of showing the organic feeds chronologically.\n",
12 | "\n",
13 | "**We are testing the two approaches to rank the feeds:** \n",
14 | "\n",
15 | "Control Group: show feeds chronologically\n",
16 | "\n",
17 | "Treatment Group: Rank feeds with algorithms\n",
18 | "\n",
19 | "Metric (#days): the number of days that a user clicks any feeds on WeChat Moments during the recent 30 days. \n",
20 | "\n",
21 | "**Objective**: Find whether $\\mu_1$ is signfiicantly different from $\\mu_0$, \n",
22 | "\n",
23 | "Ho: $\\delta$ = $\\mu_1$ - $\\mu_0$ = 0 "
24 | ]
25 | },
26 | {
27 | "cell_type": "code",
28 | "execution_count": 2,
29 | "metadata": {},
30 | "outputs": [],
31 | "source": [
32 | "import numpy as np, statsmodels.stats.api as sms\n",
33 | "import itertools\n",
34 | "import matplotlib.pyplot as plt\n",
35 | "from matplotlib.ticker import NullFormatter\n",
36 | "import pandas as pd\n",
37 | "import matplotlib.ticker as ticker\n",
38 | "from sklearn import preprocessing\n",
39 | "import scipy.stats as st\n",
40 | "import random\n",
41 | "import pandas as pd"
42 | ]
43 | },
44 | {
45 | "cell_type": "markdown",
46 | "metadata": {},
47 | "source": [
48 | "## t tests"
49 | ]
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": 3,
54 | "metadata": {},
55 | "outputs": [],
56 | "source": [
57 | "test0_s = [1,2,1,2,1,4,3,2,4,3,2,3]\n",
58 | "ctrl0_s = [2,3,2,4,3,5,4,3,5,5,4,3]"
59 | ]
60 | },
61 | {
62 | "cell_type": "code",
63 | "execution_count": 4,
64 | "metadata": {},
65 | "outputs": [
66 | {
67 | "name": "stdout",
68 | "output_type": "stream",
69 | "text": [
70 | "-1.25\n"
71 | ]
72 | }
73 | ],
74 | "source": [
75 | "mean_d=np.mean(test0_s) - np.mean(ctrl0_s)\n",
76 | "print(mean_d)"
77 | ]
78 | },
79 | {
80 | "cell_type": "code",
81 | "execution_count": 5,
82 | "metadata": {},
83 | "outputs": [
84 | {
85 | "name": "stdout",
86 | "output_type": "stream",
87 | "text": [
88 | "(-2.8393466239285283, 0.009542324891921597, 21.997899382545775)\n"
89 | ]
90 | }
91 | ],
92 | "source": [
93 | "#//usevar='unequal' or 'pooled'\n",
94 | "\n",
95 | "cm0 = sms.CompareMeans(sms.DescrStatsW(test0_s), sms.DescrStatsW(ctrl0_s))\n",
96 | "print(cm0.ttest_ind(alternative='two-sided', usevar='unequal'))"
97 | ]
98 | },
99 | {
100 | "cell_type": "markdown",
101 | "metadata": {},
102 | "source": [
103 | "**The WeChat Experiment Example**"
104 | ]
105 | },
106 | {
107 | "cell_type": "code",
108 | "execution_count": 3,
109 | "metadata": {},
110 | "outputs": [],
111 | "source": [
112 | "#Population Characeristics\n",
113 | "lift = 1.001\n",
114 | "ctr0=0.5\n",
115 | "ctr1=ctr0*lift\n",
116 | "m0=30*ctr0\n",
117 | "m1=30*ctr1\n",
118 | "delta_p = m1-m0\n",
119 | "se_p_0 = np.sqrt(30*ctr0*(1-ctr0))\n",
120 | "se_p_1 = np.sqrt(30*ctr0*lift*(1-ctr0*lift))"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": 59,
126 | "metadata": {},
127 | "outputs": [
128 | {
129 | "name": "stdout",
130 | "output_type": "stream",
131 | "text": [
132 | "0.014999999999998792 2.7386127875258306 2.7386114182190946\n"
133 | ]
134 | }
135 | ],
136 | "source": [
137 | "print(delta_p,se_p_0,se_p_1)"
138 | ]
139 | },
140 | {
141 | "cell_type": "code",
142 | "execution_count": 9,
143 | "metadata": {},
144 | "outputs": [],
145 | "source": [
146 | "#DRAW SAMPLES from Treatment and Control Populations, k=1000\n",
147 | "ctrl = np.random.binomial(30, p=ctr0, size=50) * 1.0\n",
148 | "test = np.random.binomial(30, p=ctr1, size=50) * 1.0"
149 | ]
150 | },
151 | {
152 | "cell_type": "code",
153 | "execution_count": 10,
154 | "metadata": {},
155 | "outputs": [
156 | {
157 | "name": "stdout",
158 | "output_type": "stream",
159 | "text": [
160 | "-0.620000000000001\n"
161 | ]
162 | }
163 | ],
164 | "source": [
165 | "#Sample characteristics\n",
166 | "delta_s = np.mean(test)-np.mean(ctrl)\n",
167 | "se0 = np.std(ctrl)\n",
168 | "se1 = np.std(test)\n",
169 | "print(delta_s)"
170 | ]
171 | },
172 | {
173 | "cell_type": "code",
174 | "execution_count": 11,
175 | "metadata": {},
176 | "outputs": [
177 | {
178 | "data": {
179 | "text/plain": [
180 | ""
181 | ]
182 | },
183 | "execution_count": 11,
184 | "metadata": {},
185 | "output_type": "execute_result"
186 | },
187 | {
188 | "data": {
189 | "image/png": "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\n",
190 | "text/plain": [
191 | ""
192 | ]
193 | },
194 | "metadata": {
195 | "needs_background": "light"
196 | },
197 | "output_type": "display_data"
198 | }
199 | ],
200 | "source": [
201 | "bins = np.linspace(0, 30, 30)\n",
202 | "plt.hist(test, bins=bins, label='Test')\n",
203 | "plt.hist(ctrl, bins=bins, label='Control', color='orange')\n",
204 | "plt.title('Test/Ctrl Data')\n",
205 | "plt.legend()"
206 | ]
207 | },
208 | {
209 | "cell_type": "code",
210 | "execution_count": 12,
211 | "metadata": {},
212 | "outputs": [],
213 | "source": [
214 | "cm = sms.CompareMeans(sms.DescrStatsW(test), sms.DescrStatsW(ctrl))\n",
215 | "se_s = cm.std_meandiff_separatevar"
216 | ]
217 | },
218 | {
219 | "cell_type": "code",
220 | "execution_count": 13,
221 | "metadata": {},
222 | "outputs": [
223 | {
224 | "name": "stdout",
225 | "output_type": "stream",
226 | "text": [
227 | "(-1.2026452604350089, 0.23201576184314465, 97.84757101932192)\n"
228 | ]
229 | }
230 | ],
231 | "source": [
232 | "print(cm.ttest_ind(alternative='two-sided', usevar='unequal'))"
233 | ]
234 | },
235 | {
236 | "cell_type": "markdown",
237 | "metadata": {},
238 | "source": [
239 | "# z tests"
240 | ]
241 | },
242 | {
243 | "cell_type": "code",
244 | "execution_count": 15,
245 | "metadata": {},
246 | "outputs": [
247 | {
248 | "name": "stdout",
249 | "output_type": "stream",
250 | "text": [
251 | "(-1.2026452604350089, 0.22911362509585143)\n"
252 | ]
253 | }
254 | ],
255 | "source": [
256 | "print(cm.ztest_ind(alternative='two-sided', usevar='unequal'))"
257 | ]
258 | },
259 | {
260 | "cell_type": "code",
261 | "execution_count": null,
262 | "metadata": {},
263 | "outputs": [],
264 | "source": []
265 | },
266 | {
267 | "cell_type": "code",
268 | "execution_count": null,
269 | "metadata": {},
270 | "outputs": [],
271 | "source": []
272 | }
273 | ],
274 | "metadata": {
275 | "kernelspec": {
276 | "display_name": "Python 3",
277 | "language": "python",
278 | "name": "python3"
279 | },
280 | "language_info": {
281 | "codemirror_mode": {
282 | "name": "ipython",
283 | "version": 3
284 | },
285 | "file_extension": ".py",
286 | "mimetype": "text/x-python",
287 | "name": "python",
288 | "nbconvert_exporter": "python",
289 | "pygments_lexer": "ipython3",
290 | "version": "3.8.5"
291 | }
292 | },
293 | "nbformat": 4,
294 | "nbformat_minor": 4
295 | }
296 |
--------------------------------------------------------------------------------
/Class Exercises/L2 - Exercises/ttest.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Class Exercises/L2 - Exercises/ttest.xlsx
--------------------------------------------------------------------------------
/Class Exercises/L3/CI-Bootstrap.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "## Confidence Interval"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "#### A/B Test Example \n",
15 | "\n",
16 | "Considering WeChat wants to use algorithms to rank the feeds on WeChat Moments instead of showing the organic feeds chronologically.\n",
17 | "\n",
18 | "**We are testing the two approaches to rank the feeds:** \n",
19 | "\n",
20 | "Control Group: show feeds chronologically\n",
21 | "\n",
22 | "Treatment Group: Rank feeds with algorithms\n",
23 | "\n",
24 | "Metric (#days): the number of days that a user clicks any feeds on WeChat Moments during the recent 30 days. \n",
25 | "\n",
26 | "**Objective**: Find the confidence interval of $\\delta$ = $\\mu_1$ - $\\mu_0$ and decide whether it is significantly larger than 0.\n",
27 | "\n",
28 | "**CI**: CI represents how often (e.g., 95%) the CI should contain the true Treatment Effects (difference between treatment and control)."
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": 10,
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "import numpy as np, statsmodels.stats.api as sms\n",
38 | "import itertools\n",
39 | "import matplotlib.pyplot as plt\n",
40 | "from matplotlib.ticker import NullFormatter\n",
41 | "import pandas as pd\n",
42 | "import numpy as np\n",
43 | "import matplotlib.ticker as ticker\n",
44 | "import random\n",
45 | "from sklearn import preprocessing"
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": 11,
51 | "metadata": {},
52 | "outputs": [
53 | {
54 | "name": "stdout",
55 | "output_type": "stream",
56 | "text": [
57 | "1.5\n"
58 | ]
59 | }
60 | ],
61 | "source": [
62 | "#population characteristics\n",
63 | "lift = 1.1\n",
64 | "ctr0=0.5\n",
65 | "ctr1=lift*ctr0\n",
66 | "# mean = n*p (n=30)\n",
67 | "mu0=30*ctr0\n",
68 | "mu1=30*ctr1\n",
69 | "delta_p = mu1-mu0\n",
70 | "print(delta_p)"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "execution_count": 12,
76 | "metadata": {},
77 | "outputs": [
78 | {
79 | "name": "stdout",
80 | "output_type": "stream",
81 | "text": [
82 | "1.3790000000000013\n"
83 | ]
84 | }
85 | ],
86 | "source": [
87 | "#sample characteristics\n",
88 | "# we draw the sample\n",
89 | "ctrl = np.random.binomial(30, p=ctr0, size=1000) * 1.0\n",
90 | "test = np.random.binomial(30, p=ctr1, size=1000) * 1.0\n",
91 | "delta_s = np.mean(test)-np.mean(ctrl)\n",
92 | "print(delta_s)"
93 | ]
94 | },
95 | {
96 | "cell_type": "code",
97 | "execution_count": 13,
98 | "metadata": {},
99 | "outputs": [
100 | {
101 | "name": "stdout",
102 | "output_type": "stream",
103 | "text": [
104 | "2.720374790355182 2.675518641310503\n"
105 | ]
106 | }
107 | ],
108 | "source": [
109 | "se0 = np.std(ctrl)\n",
110 | "se1 = np.std(test)\n",
111 | "print(se0,se1)"
112 | ]
113 | },
114 | {
115 | "cell_type": "code",
116 | "execution_count": 14,
117 | "metadata": {},
118 | "outputs": [],
119 | "source": [
120 | "cm = sms.CompareMeans(sms.DescrStatsW(test), sms.DescrStatsW(ctrl))"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": 15,
126 | "metadata": {},
127 | "outputs": [
128 | {
129 | "name": "stdout",
130 | "output_type": "stream",
131 | "text": [
132 | "(1.1422489254698085, 1.6157510745301942)\n",
133 | "(1.1423923846126793, 1.6156076153873233)\n"
134 | ]
135 | }
136 | ],
137 | "source": [
138 | "print(cm.tconfint_diff(alpha=0.05, alternative='two-sided', usevar='unequal'))\n",
139 | "print(cm.zconfint_diff(alpha=0.05, alternative='two-sided', usevar='unequal'))"
140 | ]
141 | },
142 | {
143 | "cell_type": "markdown",
144 | "metadata": {},
145 | "source": [
146 | "### Compare CIs, k=100, 1000, 2000, 5000"
147 | ]
148 | },
149 | {
150 | "cell_type": "code",
151 | "execution_count": 7,
152 | "metadata": {},
153 | "outputs": [],
154 | "source": [
155 | "def ci_sample_size(n):\n",
156 | " ctrl = np.random.binomial(30, p=ctr0, size=n) * 1.0\n",
157 | " test = np.random.binomial(30, p=ctr0*lift, size=n) * 1.0\n",
158 | " cm = sms.CompareMeans(sms.DescrStatsW(test), sms.DescrStatsW(ctrl))\n",
159 | " x,y = cm.tconfint_diff(alpha=0.05, alternative='two-sided', usevar='unequal')\n",
160 | " return (x,y)"
161 | ]
162 | },
163 | {
164 | "cell_type": "code",
165 | "execution_count": 8,
166 | "metadata": {},
167 | "outputs": [],
168 | "source": [
169 | "size = [50,1000,2000,100000]\n",
170 | "ci_lower=[]\n",
171 | "ci_upper=[]"
172 | ]
173 | },
174 | {
175 | "cell_type": "code",
176 | "execution_count": 9,
177 | "metadata": {},
178 | "outputs": [
179 | {
180 | "name": "stdout",
181 | "output_type": "stream",
182 | "text": [
183 | "(0.0447351492565613, 2.155264850743438)\n",
184 | "(1.0227458222717214, 1.5092541777282786)\n",
185 | "(1.0939559051256076, 1.4320440948743887)\n",
186 | "(1.4748116305281684, 1.5226283694718326)\n"
187 | ]
188 | }
189 | ],
190 | "source": [
191 | "for i in size:\n",
192 | " print(ci_sample_size(i))\n",
193 | " ci_lower.append(ci_sample_size(i)[0])\n",
194 | " ci_upper.append(ci_sample_size(i)[1])"
195 | ]
196 | },
197 | {
198 | "cell_type": "code",
199 | "execution_count": 10,
200 | "metadata": {},
201 | "outputs": [],
202 | "source": [
203 | "data_dict = {}\n",
204 | "data_dict['lower'] = [x for x in ci_lower]\n",
205 | "data_dict['upper'] = [x for x in ci_upper]\n",
206 | "data_dict['size']=[x for x in size]\n",
207 | "dataset = pd.DataFrame(data_dict)"
208 | ]
209 | },
210 | {
211 | "cell_type": "code",
212 | "execution_count": 11,
213 | "metadata": {},
214 | "outputs": [
215 | {
216 | "data": {
217 | "text/plain": [
218 | "Text(0, 0.5, 'Sample Size')"
219 | ]
220 | },
221 | "execution_count": 11,
222 | "metadata": {},
223 | "output_type": "execute_result"
224 | },
225 | {
226 | "data": {
227 | "image/png": "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\n",
228 | "text/plain": [
229 | ""
230 | ]
231 | },
232 | "metadata": {
233 | "needs_background": "light"
234 | },
235 | "output_type": "display_data"
236 | }
237 | ],
238 | "source": [
239 | "for lower,upper,y in zip(dataset['lower'],dataset['upper'],range(len(dataset))):\n",
240 | " plt.plot((lower,upper),(y,y),'ro-',color='orange')\n",
241 | "plt.axvline(x=delta_p)\n",
242 | "plt.yticks(range(len(dataset)),list(dataset['size']))\n",
243 | "plt.title('SampleSize & CIs')\n",
244 | "plt.xlabel('Confidence Intervals')\n",
245 | "plt.ylabel('Sample Size')"
246 | ]
247 | },
248 | {
249 | "cell_type": "markdown",
250 | "metadata": {},
251 | "source": [
252 | "### CI and Type I Error"
253 | ]
254 | },
255 | {
256 | "cell_type": "markdown",
257 | "metadata": {},
258 | "source": [
259 | "CIs for testing the same variable ($\\delta$) based on different samples. Draw 25 samples from the population. Show the CIs and interpret Type I error by the results."
260 | ]
261 | },
262 | {
263 | "cell_type": "code",
264 | "execution_count": 12,
265 | "metadata": {},
266 | "outputs": [
267 | {
268 | "name": "stdout",
269 | "output_type": "stream",
270 | "text": [
271 | "0.5000000000000004\n"
272 | ]
273 | }
274 | ],
275 | "source": [
276 | "#population \n",
277 | "lift2 = 1.1\n",
278 | "std = 0.2\n",
279 | "mean = 5\n",
280 | "delta_p2=5*(lift2-1)\n",
281 | "print(delta_p2)"
282 | ]
283 | },
284 | {
285 | "cell_type": "code",
286 | "execution_count": 20,
287 | "metadata": {},
288 | "outputs": [],
289 | "source": [
290 | "ci=[]\n",
291 | "for i in range(20):\n",
292 | " ctrl = np.random.normal(5,std,1000)\n",
293 | " test = np.random.normal(5*lift2,std, 1000)\n",
294 | " cm = sms.CompareMeans(sms.DescrStatsW(test), sms.DescrStatsW(ctrl))\n",
295 | " x,y = cm.tconfint_diff(alpha=0.05, alternative='two-sided', usevar='unequal')\n",
296 | " ci.append((x,y))"
297 | ]
298 | },
299 | {
300 | "cell_type": "code",
301 | "execution_count": 21,
302 | "metadata": {},
303 | "outputs": [
304 | {
305 | "name": "stdout",
306 | "output_type": "stream",
307 | "text": [
308 | " Number lower upper\n",
309 | "0 0 0.480556 0.515585\n",
310 | "1 1 0.492531 0.527923\n",
311 | "2 2 0.487024 0.521639\n",
312 | "3 3 0.490352 0.525666\n",
313 | "4 4 0.496746 0.532386\n",
314 | "5 5 0.457623 0.492577\n",
315 | "6 6 0.482577 0.517819\n",
316 | "7 7 0.501737 0.536818\n",
317 | "8 8 0.480479 0.515723\n",
318 | "9 9 0.482137 0.517534\n",
319 | "10 10 0.483448 0.518725\n",
320 | "11 11 0.493172 0.527980\n",
321 | "12 12 0.471214 0.507093\n",
322 | "13 13 0.475970 0.512398\n",
323 | "14 14 0.465279 0.501072\n",
324 | "15 15 0.480083 0.515361\n",
325 | "16 16 0.487442 0.522472\n",
326 | "17 17 0.478996 0.514368\n",
327 | "18 18 0.491380 0.526660\n",
328 | "19 19 0.469840 0.504135\n"
329 | ]
330 | }
331 | ],
332 | "source": [
333 | "data_dict = {}\n",
334 | "data_dict['Number'] = [x for x in range(20)]\n",
335 | "data_dict['lower'] = [x[0] for x in ci]\n",
336 | "data_dict['upper'] = [x[1] for x in ci]\n",
337 | "dataset = pd.DataFrame(data_dict) \n",
338 | "print(dataset)"
339 | ]
340 | },
341 | {
342 | "cell_type": "code",
343 | "execution_count": 22,
344 | "metadata": {},
345 | "outputs": [
346 | {
347 | "data": {
348 | "image/png": "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\n",
349 | "text/plain": [
350 | ""
351 | ]
352 | },
353 | "metadata": {
354 | "needs_background": "light"
355 | },
356 | "output_type": "display_data"
357 | }
358 | ],
359 | "source": [
360 | "for lower,upper,y in zip(dataset['lower'],dataset['upper'],range(len(dataset))):\n",
361 | " plt.plot((lower,upper),(y,y),'ro-',color='orange')\n",
362 | " plt.yticks(range(len(dataset)),list(dataset['Number']))\n",
363 | " plt.axvline(delta_p2)\n",
364 | "plt.title('Confidence Intervals')\n",
365 | "plt.savefig(\"CIMean0.png\")"
366 | ]
367 | },
368 | {
369 | "cell_type": "markdown",
370 | "metadata": {},
371 | "source": [
372 | "### Bootstrap CIs"
373 | ]
374 | },
375 | {
376 | "cell_type": "markdown",
377 | "metadata": {},
378 | "source": [
379 | "https://github.com/facebookarchive/bootstrapped"
380 | ]
381 | },
382 | {
383 | "cell_type": "code",
384 | "execution_count": 16,
385 | "metadata": {},
386 | "outputs": [
387 | {
388 | "name": "stdout",
389 | "output_type": "stream",
390 | "text": [
391 | "Requirement already satisfied: bootstrapped in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (0.0.2)\n",
392 | "Requirement already satisfied: matplotlib>=1.5.3 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from bootstrapped) (3.3.2)\n",
393 | "Requirement already satisfied: pandas>=0.18.1 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from bootstrapped) (1.1.3)\n",
394 | "Requirement already satisfied: numpy>=1.11.1 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from bootstrapped) (1.19.2)\n",
395 | "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.3 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (2.4.7)\n",
396 | "Requirement already satisfied: pillow>=6.2.0 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (8.0.1)\n",
397 | "Requirement already satisfied: cycler>=0.10 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (0.10.0)\n",
398 | "Requirement already satisfied: kiwisolver>=1.0.1 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (1.3.0)\n",
399 | "Requirement already satisfied: certifi>=2020.06.20 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (2020.6.20)\n",
400 | "Requirement already satisfied: python-dateutil>=2.1 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (2.8.1)\n",
401 | "Requirement already satisfied: pytz>=2017.2 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from pandas>=0.18.1->bootstrapped) (2020.1)\n",
402 | "Requirement already satisfied: six in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from cycler>=0.10->matplotlib>=1.5.3->bootstrapped) (1.15.0)\n",
403 | "Note: you may need to restart the kernel to use updated packages.\n"
404 | ]
405 | }
406 | ],
407 | "source": [
408 | "pip install bootstrapped"
409 | ]
410 | },
411 | {
412 | "cell_type": "code",
413 | "execution_count": 2,
414 | "metadata": {},
415 | "outputs": [],
416 | "source": [
417 | "import bootstrapped.bootstrap as bs\n",
418 | "import bootstrapped.compare_functions as bs_compare\n",
419 | "import bootstrapped.stats_functions as bs_stats"
420 | ]
421 | },
422 | {
423 | "cell_type": "code",
424 | "execution_count": 17,
425 | "metadata": {},
426 | "outputs": [],
427 | "source": [
428 | "ctrl = np.array(ctrl)\n",
429 | "test = np.array(test)"
430 | ]
431 | },
432 | {
433 | "cell_type": "markdown",
434 | "metadata": {},
435 | "source": [
436 | "**Compare Mean Difference: value change & percent change**"
437 | ]
438 | },
439 | {
440 | "cell_type": "code",
441 | "execution_count": 18,
442 | "metadata": {},
443 | "outputs": [
444 | {
445 | "name": "stdout",
446 | "output_type": "stream",
447 | "text": [
448 | "1.3790000000000013 (1.1380000000000035, 1.6240000000000006)\n"
449 | ]
450 | }
451 | ],
452 | "source": [
453 | "print(bs.bootstrap_ab(\n",
454 | " test, \n",
455 | " ctrl, \n",
456 | " stat_func=bs_stats.mean,\n",
457 | " compare_func=bs_compare.difference,\n",
458 | " alpha=0.05))"
459 | ]
460 | },
461 | {
462 | "cell_type": "code",
463 | "execution_count": 19,
464 | "metadata": {},
465 | "outputs": [
466 | {
467 | "name": "stdout",
468 | "output_type": "stream",
469 | "text": [
470 | "9.14395597108946 (7.492608721343869, 10.771821298348328)\n"
471 | ]
472 | }
473 | ],
474 | "source": [
475 | "print(bs.bootstrap_ab(\n",
476 | " test, \n",
477 | " ctrl, \n",
478 | " stat_func=bs_stats.mean,\n",
479 | " compare_func=bs_compare.percent_change,\n",
480 | " alpha=0.05))"
481 | ]
482 | },
483 | {
484 | "cell_type": "markdown",
485 | "metadata": {},
486 | "source": [
487 | "**Compare Median Difference: value change & percent change**"
488 | ]
489 | },
490 | {
491 | "cell_type": "code",
492 | "execution_count": 20,
493 | "metadata": {},
494 | "outputs": [
495 | {
496 | "name": "stdout",
497 | "output_type": "stream",
498 | "text": [
499 | "2.0 (2.0, 3.0)\n"
500 | ]
501 | }
502 | ],
503 | "source": [
504 | "print(bs.bootstrap_ab(\n",
505 | " test, \n",
506 | " ctrl, \n",
507 | " stat_func=bs_stats.median,\n",
508 | " compare_func=bs_compare.difference,\n",
509 | " alpha=0.05))"
510 | ]
511 | },
512 | {
513 | "cell_type": "code",
514 | "execution_count": 21,
515 | "metadata": {},
516 | "outputs": [
517 | {
518 | "name": "stdout",
519 | "output_type": "stream",
520 | "text": [
521 | "13.333333333333334 (13.333333333333334, 20.0)\n"
522 | ]
523 | }
524 | ],
525 | "source": [
526 | "print(bs.bootstrap_ab(\n",
527 | " test, \n",
528 | " ctrl, \n",
529 | " stat_func=bs_stats.median,\n",
530 | " compare_func=bs_compare.percent_change,\n",
531 | " alpha=0.05))"
532 | ]
533 | },
534 | {
535 | "cell_type": "markdown",
536 | "metadata": {},
537 | "source": [
538 | "**Compare Standard Errors Difference: value change & percent change**"
539 | ]
540 | },
541 | {
542 | "cell_type": "code",
543 | "execution_count": 22,
544 | "metadata": {},
545 | "outputs": [
546 | {
547 | "name": "stdout",
548 | "output_type": "stream",
549 | "text": [
550 | "-0.044856149044678606 (-0.21680099414147444, 0.12374627150013212)\n"
551 | ]
552 | }
553 | ],
554 | "source": [
555 | "print(bs.bootstrap_ab(\n",
556 | " test, \n",
557 | " ctrl, \n",
558 | " stat_func=bs_stats.std,\n",
559 | " compare_func=bs_compare.difference,\n",
560 | " alpha=0.05))"
561 | ]
562 | },
563 | {
564 | "cell_type": "code",
565 | "execution_count": 23,
566 | "metadata": {},
567 | "outputs": [
568 | {
569 | "name": "stdout",
570 | "output_type": "stream",
571 | "text": [
572 | "-1.6488959243304129 (-8.015358620926206, 4.234015978126974)\n"
573 | ]
574 | }
575 | ],
576 | "source": [
577 | "print(bs.bootstrap_ab(\n",
578 | " test, \n",
579 | " ctrl, \n",
580 | " stat_func=bs_stats.std,\n",
581 | " compare_func=bs_compare.percent_change,\n",
582 | " alpha=0.05))"
583 | ]
584 | },
585 | {
586 | "cell_type": "markdown",
587 | "metadata": {},
588 | "source": [
589 | "**Compare SUM Difference: value change & percent change**"
590 | ]
591 | },
592 | {
593 | "cell_type": "code",
594 | "execution_count": 24,
595 | "metadata": {},
596 | "outputs": [
597 | {
598 | "name": "stdout",
599 | "output_type": "stream",
600 | "text": [
601 | "1379.0 (1142.9750000000004, 1614.0)\n"
602 | ]
603 | }
604 | ],
605 | "source": [
606 | "print(bs.bootstrap_ab(\n",
607 | " test, \n",
608 | " ctrl, \n",
609 | " stat_func=bs_stats.sum,\n",
610 | " compare_func=bs_compare.difference,\n",
611 | " alpha=0.05))"
612 | ]
613 | },
614 | {
615 | "cell_type": "code",
616 | "execution_count": 25,
617 | "metadata": {},
618 | "outputs": [
619 | {
620 | "name": "stdout",
621 | "output_type": "stream",
622 | "text": [
623 | "9.14395597108945 (7.531300354398173, 10.795311231116987)\n"
624 | ]
625 | }
626 | ],
627 | "source": [
628 | "print(bs.bootstrap_ab(\n",
629 | " test, \n",
630 | " ctrl, \n",
631 | " stat_func=bs_stats.sum,\n",
632 | " compare_func=bs_compare.percent_change,\n",
633 | " alpha=0.05))"
634 | ]
635 | },
636 | {
637 | "cell_type": "code",
638 | "execution_count": null,
639 | "metadata": {},
640 | "outputs": [],
641 | "source": []
642 | }
643 | ],
644 | "metadata": {
645 | "kernelspec": {
646 | "display_name": "Python 3",
647 | "language": "python",
648 | "name": "python3"
649 | },
650 | "language_info": {
651 | "codemirror_mode": {
652 | "name": "ipython",
653 | "version": 3
654 | },
655 | "file_extension": ".py",
656 | "mimetype": "text/x-python",
657 | "name": "python",
658 | "nbconvert_exporter": "python",
659 | "pygments_lexer": "ipython3",
660 | "version": "3.8.5"
661 | }
662 | },
663 | "nbformat": 4,
664 | "nbformat_minor": 4
665 | }
666 |
--------------------------------------------------------------------------------
/Class Exercises/L3/CIMean0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Class Exercises/L3/CIMean0.png
--------------------------------------------------------------------------------
/Class Exercises/L3/CIMeanSmall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Class Exercises/L3/CIMeanSmall.png
--------------------------------------------------------------------------------
/Class Exercises/L3/Power_SampleSize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Class Exercises/L3/Power_SampleSize.png
--------------------------------------------------------------------------------
/Class Exercises/L4/s4/SRM Tests.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Class Exercises/L4/s4/SRM Tests.xlsx
--------------------------------------------------------------------------------
/Class Exercises/L5/Interleaving.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Class Exercises/L5/Interleaving.xlsx
--------------------------------------------------------------------------------
/Class Exercises/L5/cluster.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "## Regression with Clustered Standard Errors"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {},
14 | "outputs": [],
15 | "source": [
16 | "import numpy as np, statsmodels.stats.api as sms\n",
17 | "import itertools\n",
18 | "import matplotlib.pyplot as plt\n",
19 | "from matplotlib.ticker import NullFormatter\n",
20 | "import pandas as pd\n",
21 | "import numpy as np\n",
22 | "import matplotlib.ticker as ticker\n",
23 | "import random\n",
24 | "from sklearn import preprocessing"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": 2,
30 | "metadata": {},
31 | "outputs": [],
32 | "source": [
33 | "infile = 'exp_data_cluster.csv' \n",
34 | "data = pd.read_csv(infile)"
35 | ]
36 | },
37 | {
38 | "cell_type": "code",
39 | "execution_count": 3,
40 | "metadata": {},
41 | "outputs": [
42 | {
43 | "data": {
44 | "text/plain": [
45 | "(16000, 4)"
46 | ]
47 | },
48 | "execution_count": 3,
49 | "metadata": {},
50 | "output_type": "execute_result"
51 | }
52 | ],
53 | "source": [
54 | "data.shape"
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": 4,
60 | "metadata": {},
61 | "outputs": [
62 | {
63 | "data": {
64 | "text/html": [
65 | "\n",
66 | "\n",
79 | "
\n",
80 | " \n",
81 | " \n",
82 | " | \n",
83 | " user | \n",
84 | " adid | \n",
85 | " expid | \n",
86 | " if_click | \n",
87 | "
\n",
88 | " \n",
89 | " \n",
90 | " \n",
91 | " 0 | \n",
92 | " 92092 | \n",
93 | " 1e4fb0d22340fdf9ee02b6ae4a7d9a83 | \n",
94 | " 1 | \n",
95 | " 0 | \n",
96 | "
\n",
97 | " \n",
98 | " 1 | \n",
99 | " 878501 | \n",
100 | " 97fc187415fe1785d5ee02bfd348968e | \n",
101 | " 0 | \n",
102 | " 0 | \n",
103 | "
\n",
104 | " \n",
105 | " 2 | \n",
106 | " 266367 | \n",
107 | " 0b0fa14b56d3741178196daaa92e6a1e | \n",
108 | " 1 | \n",
109 | " 0 | \n",
110 | "
\n",
111 | " \n",
112 | " 3 | \n",
113 | " 329319 | \n",
114 | " 1f1fe825014d9e9a0881233d9950bd43 | \n",
115 | " 1 | \n",
116 | " 0 | \n",
117 | "
\n",
118 | " \n",
119 | " 4 | \n",
120 | " 64672 | \n",
121 | " 5b2ae85128137e449eb015f6de78add5 | \n",
122 | " 0 | \n",
123 | " 0 | \n",
124 | "
\n",
125 | " \n",
126 | "
\n",
127 | "
"
128 | ],
129 | "text/plain": [
130 | " user adid expid if_click\n",
131 | "0 92092 1e4fb0d22340fdf9ee02b6ae4a7d9a83 1 0\n",
132 | "1 878501 97fc187415fe1785d5ee02bfd348968e 0 0\n",
133 | "2 266367 0b0fa14b56d3741178196daaa92e6a1e 1 0\n",
134 | "3 329319 1f1fe825014d9e9a0881233d9950bd43 1 0\n",
135 | "4 64672 5b2ae85128137e449eb015f6de78add5 0 0"
136 | ]
137 | },
138 | "execution_count": 4,
139 | "metadata": {},
140 | "output_type": "execute_result"
141 | }
142 | ],
143 | "source": [
144 | "data.head()"
145 | ]
146 | },
147 | {
148 | "cell_type": "code",
149 | "execution_count": 6,
150 | "metadata": {},
151 | "outputs": [],
152 | "source": [
153 | "import statsmodels.formula.api as smf\n",
154 | "model = smf.ols(formula='if_click ~ expid', data=data)"
155 | ]
156 | },
157 | {
158 | "cell_type": "markdown",
159 | "metadata": {},
160 | "source": [
161 | "#### OLS with Clustered SE"
162 | ]
163 | },
164 | {
165 | "cell_type": "code",
166 | "execution_count": 15,
167 | "metadata": {},
168 | "outputs": [
169 | {
170 | "name": "stdout",
171 | "output_type": "stream",
172 | "text": [
173 | "Result with cluster\n",
174 | " Results: Ordinary least squares\n",
175 | "==================================================================\n",
176 | "Model: OLS Adj. R-squared: 0.000 \n",
177 | "Dependent Variable: if_click AIC: 1467.5819\n",
178 | "Date: 2023-04-04 15:53 BIC: 1482.9425\n",
179 | "No. Observations: 16000 Log-Likelihood: -731.79 \n",
180 | "Df Model: 1 F-statistic: 6.710 \n",
181 | "Df Residuals: 15998 Prob (F-statistic): 0.00960 \n",
182 | "R-squared: 0.000 Scale: 0.064166 \n",
183 | "--------------------------------------------------------------------\n",
184 | " Coef. Std.Err. z P>|z| [0.025 0.975]\n",
185 | "--------------------------------------------------------------------\n",
186 | "Intercept 0.0638 0.0027 23.3379 0.0000 0.0584 0.0691\n",
187 | "expid 0.0104 0.0040 2.5904 0.0096 0.0025 0.0182\n",
188 | "------------------------------------------------------------------\n",
189 | "Omnibus: 10828.253 Durbin-Watson: 2.012 \n",
190 | "Prob(Omnibus): 0.000 Jarque-Bera (JB): 91921.719\n",
191 | "Skew: 3.401 Prob(JB): 0.000 \n",
192 | "Kurtosis: 12.572 Condition No.: 3 \n",
193 | "==================================================================\n",
194 | "\n"
195 | ]
196 | }
197 | ],
198 | "source": [
199 | "result_cluster = model.fit(cov_type='cluster', cov_kwds = {'groups': data.user})\n",
200 | "print('Result with cluster')\n",
201 | "print(result_cluster.summary2())"
202 | ]
203 | },
204 | {
205 | "cell_type": "markdown",
206 | "metadata": {},
207 | "source": [
208 | "#### OLS without Clustered SE"
209 | ]
210 | },
211 | {
212 | "cell_type": "code",
213 | "execution_count": 16,
214 | "metadata": {},
215 | "outputs": [
216 | {
217 | "name": "stdout",
218 | "output_type": "stream",
219 | "text": [
220 | "Result without cluster\n",
221 | " Results: Ordinary least squares\n",
222 | "==================================================================\n",
223 | "Model: OLS Adj. R-squared: 0.000 \n",
224 | "Dependent Variable: if_click AIC: 1467.5819\n",
225 | "Date: 2023-04-04 15:54 BIC: 1482.9425\n",
226 | "No. Observations: 16000 Log-Likelihood: -731.79 \n",
227 | "Df Model: 1 F-statistic: 6.710 \n",
228 | "Df Residuals: 15998 Prob (F-statistic): 0.00960 \n",
229 | "R-squared: 0.000 Scale: 0.064166 \n",
230 | "--------------------------------------------------------------------\n",
231 | " Coef. Std.Err. t P>|t| [0.025 0.975]\n",
232 | "--------------------------------------------------------------------\n",
233 | "Intercept 0.0638 0.0028 22.5098 0.0000 0.0582 0.0693\n",
234 | "expid 0.0104 0.0040 2.5904 0.0096 0.0025 0.0182\n",
235 | "------------------------------------------------------------------\n",
236 | "Omnibus: 10828.253 Durbin-Watson: 2.012 \n",
237 | "Prob(Omnibus): 0.000 Jarque-Bera (JB): 91921.719\n",
238 | "Skew: 3.401 Prob(JB): 0.000 \n",
239 | "Kurtosis: 12.572 Condition No.: 3 \n",
240 | "==================================================================\n",
241 | "\n"
242 | ]
243 | }
244 | ],
245 | "source": [
246 | "result_ols = model.fit()\n",
247 | "print('Result without cluster')\n",
248 | "print(result_ols.summary2())"
249 | ]
250 | },
251 | {
252 | "cell_type": "markdown",
253 | "metadata": {},
254 | "source": [
255 | "#### Compare Means with t tests"
256 | ]
257 | },
258 | {
259 | "cell_type": "code",
260 | "execution_count": 12,
261 | "metadata": {},
262 | "outputs": [],
263 | "source": [
264 | "y0 = data[data['expid'] == 0]['if_click']"
265 | ]
266 | },
267 | {
268 | "cell_type": "code",
269 | "execution_count": 13,
270 | "metadata": {},
271 | "outputs": [
272 | {
273 | "name": "stdout",
274 | "output_type": "stream",
275 | "text": [
276 | "0.010374999999999995\n"
277 | ]
278 | }
279 | ],
280 | "source": [
281 | "y1 = data[data['expid'] == 1]['if_click']\n",
282 | "mean_d = np.mean(y1)-np.mean(y0)\n",
283 | "print(mean_d)"
284 | ]
285 | },
286 | {
287 | "cell_type": "code",
288 | "execution_count": 14,
289 | "metadata": {},
290 | "outputs": [
291 | {
292 | "name": "stdout",
293 | "output_type": "stream",
294 | "text": [
295 | "(-2.590388082735368, 0.009595515482880781, 15920.640661495236)\n"
296 | ]
297 | }
298 | ],
299 | "source": [
300 | "cm = sms.CompareMeans(sms.DescrStatsW(y0), sms.DescrStatsW(y1))\n",
301 | "print(cm.ttest_ind(alternative='two-sided', usevar='unequal'))"
302 | ]
303 | },
304 | {
305 | "cell_type": "code",
306 | "execution_count": null,
307 | "metadata": {},
308 | "outputs": [],
309 | "source": []
310 | },
311 | {
312 | "cell_type": "code",
313 | "execution_count": null,
314 | "metadata": {},
315 | "outputs": [],
316 | "source": []
317 | }
318 | ],
319 | "metadata": {
320 | "kernelspec": {
321 | "display_name": "Python 3",
322 | "language": "python",
323 | "name": "python3"
324 | },
325 | "language_info": {
326 | "codemirror_mode": {
327 | "name": "ipython",
328 | "version": 3
329 | },
330 | "file_extension": ".py",
331 | "mimetype": "text/x-python",
332 | "name": "python",
333 | "nbconvert_exporter": "python",
334 | "pygments_lexer": "ipython3",
335 | "version": "3.8.5"
336 | }
337 | },
338 | "nbformat": 4,
339 | "nbformat_minor": 4
340 | }
341 |
--------------------------------------------------------------------------------
/Class Exercises/L5/variance_lift.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 3,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "import numpy as np, statsmodels.stats.api as sms\n",
10 | "import itertools\n",
11 | "import matplotlib.pyplot as plt\n",
12 | "from matplotlib.ticker import NullFormatter\n",
13 | "import pandas as pd\n",
14 | "import numpy as np\n",
15 | "import matplotlib.ticker as ticker\n",
16 | "import random\n",
17 | "from sklearn import preprocessing"
18 | ]
19 | },
20 | {
21 | "cell_type": "code",
22 | "execution_count": 4,
23 | "metadata": {},
24 | "outputs": [
25 | {
26 | "name": "stdout",
27 | "output_type": "stream",
28 | "text": [
29 | "1.5000000000000013\n"
30 | ]
31 | }
32 | ],
33 | "source": [
34 | "#Population Characteristics\n",
35 | "lift = 1.1\n",
36 | "ctr0=0.5\n",
37 | "n0=1000\n",
38 | "n1=1000\n",
39 | "ctrl = np.random.binomial(30, p=ctr0, size=n0) * 1.0\n",
40 | "test = np.random.binomial(30, p=ctr0*lift, size=n1) * 1.0\n",
41 | "delta_p = 30*ctr0*(lift-1)\n",
42 | "print(delta_p)"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": 5,
48 | "metadata": {},
49 | "outputs": [
50 | {
51 | "name": "stdout",
52 | "output_type": "stream",
53 | "text": [
54 | "1.0918612408272181\n"
55 | ]
56 | }
57 | ],
58 | "source": [
59 | "# Y1 bar and Y0 bar\n",
60 | "m1=np.mean(test)\n",
61 | "m0=np.mean(ctrl) \n",
62 | "lift=m1/m0\n",
63 | "# variance of Y1 and Yo\n",
64 | "var0 = np.var(ctrl,ddof=1)\n",
65 | "var1 = np.var(test,ddof=1)\n",
66 | "print(lift)"
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "execution_count": 6,
72 | "metadata": {},
73 | "outputs": [
74 | {
75 | "name": "stdout",
76 | "output_type": "stream",
77 | "text": [
78 | "0.007885785785785786 0.007203514514514514\n"
79 | ]
80 | }
81 | ],
82 | "source": [
83 | "# variance of Y1 bar and Y0 bar\n",
84 | "var_m0=var0/n0\n",
85 | "var_m1=var1/n1\n",
86 | "print(var_m0, var_m1)"
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": 7,
92 | "metadata": {},
93 | "outputs": [],
94 | "source": [
95 | "var_lift = (1/m0**2)*var_m1+(m1**2/m0**4)*var_m0"
96 | ]
97 | },
98 | {
99 | "cell_type": "code",
100 | "execution_count": 8,
101 | "metadata": {},
102 | "outputs": [],
103 | "source": [
104 | "se_lift=np.sqrt(var_lift)"
105 | ]
106 | },
107 | {
108 | "cell_type": "code",
109 | "execution_count": 9,
110 | "metadata": {},
111 | "outputs": [
112 | {
113 | "name": "stdout",
114 | "output_type": "stream",
115 | "text": [
116 | "0.008596330540126679\n"
117 | ]
118 | }
119 | ],
120 | "source": [
121 | "print(se_lift)"
122 | ]
123 | },
124 | {
125 | "cell_type": "code",
126 | "execution_count": 10,
127 | "metadata": {},
128 | "outputs": [],
129 | "source": [
130 | "ci = (lift-1.96*se_lift,lift+1.96*se_lift)"
131 | ]
132 | },
133 | {
134 | "cell_type": "code",
135 | "execution_count": 11,
136 | "metadata": {},
137 | "outputs": [
138 | {
139 | "name": "stdout",
140 | "output_type": "stream",
141 | "text": [
142 | "(1.0750124329685697, 1.1087100486858665)\n"
143 | ]
144 | }
145 | ],
146 | "source": [
147 | "print(ci)"
148 | ]
149 | },
150 | {
151 | "cell_type": "code",
152 | "execution_count": 10,
153 | "metadata": {},
154 | "outputs": [
155 | {
156 | "name": "stdout",
157 | "output_type": "stream",
158 | "text": [
159 | "Requirement already satisfied: bootstrapped in /Users/shanh18/opt/anaconda3/lib/python3.7/site-packages (0.0.2)\n",
160 | "Requirement already satisfied: numpy>=1.11.1 in /Users/shanh18/opt/anaconda3/lib/python3.7/site-packages (from bootstrapped) (1.18.1)\n",
161 | "Requirement already satisfied: matplotlib>=1.5.3 in /Users/shanh18/opt/anaconda3/lib/python3.7/site-packages (from bootstrapped) (3.1.3)\n",
162 | "Requirement already satisfied: pandas>=0.18.1 in /Users/shanh18/opt/anaconda3/lib/python3.7/site-packages (from bootstrapped) (1.0.1)\n",
163 | "Requirement already satisfied: kiwisolver>=1.0.1 in /Users/shanh18/opt/anaconda3/lib/python3.7/site-packages (from matplotlib>=1.5.3->bootstrapped) (1.1.0)\n",
164 | "Requirement already satisfied: cycler>=0.10 in /Users/shanh18/opt/anaconda3/lib/python3.7/site-packages (from matplotlib>=1.5.3->bootstrapped) (0.10.0)\n",
165 | "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /Users/shanh18/opt/anaconda3/lib/python3.7/site-packages (from matplotlib>=1.5.3->bootstrapped) (2.4.6)\n",
166 | "Requirement already satisfied: python-dateutil>=2.1 in /Users/shanh18/opt/anaconda3/lib/python3.7/site-packages (from matplotlib>=1.5.3->bootstrapped) (2.8.1)\n",
167 | "Requirement already satisfied: pytz>=2017.2 in /Users/shanh18/opt/anaconda3/lib/python3.7/site-packages (from pandas>=0.18.1->bootstrapped) (2019.3)\n",
168 | "Requirement already satisfied: setuptools in /Users/shanh18/opt/anaconda3/lib/python3.7/site-packages (from kiwisolver>=1.0.1->matplotlib>=1.5.3->bootstrapped) (46.0.0.post20200309)\n",
169 | "Requirement already satisfied: six in /Users/shanh18/opt/anaconda3/lib/python3.7/site-packages (from cycler>=0.10->matplotlib>=1.5.3->bootstrapped) (1.14.0)\n",
170 | "Note: you may need to restart the kernel to use updated packages.\n"
171 | ]
172 | }
173 | ],
174 | "source": [
175 | "pip install bootstrapped"
176 | ]
177 | },
178 | {
179 | "cell_type": "code",
180 | "execution_count": 15,
181 | "metadata": {},
182 | "outputs": [],
183 | "source": [
184 | "import bootstrapped.bootstrap as bs\n",
185 | "import bootstrapped.compare_functions as bs_compare\n",
186 | "import bootstrapped.stats_functions as bs_stats"
187 | ]
188 | },
189 | {
190 | "cell_type": "code",
191 | "execution_count": 16,
192 | "metadata": {},
193 | "outputs": [],
194 | "source": [
195 | "ctrl = np.array(ctrl)\n",
196 | "test = np.array(test)"
197 | ]
198 | },
199 | {
200 | "cell_type": "code",
201 | "execution_count": 17,
202 | "metadata": {},
203 | "outputs": [
204 | {
205 | "name": "stdout",
206 | "output_type": "stream",
207 | "text": [
208 | "9.18612408272182 (7.508417171051148, 10.811030595629683)\n"
209 | ]
210 | }
211 | ],
212 | "source": [
213 | "print(bs.bootstrap_ab(\n",
214 | " test, \n",
215 | " ctrl, \n",
216 | " stat_func=bs_stats.mean,\n",
217 | " compare_func=bs_compare.percent_change,\n",
218 | " alpha=0.05))"
219 | ]
220 | },
221 | {
222 | "cell_type": "code",
223 | "execution_count": null,
224 | "metadata": {},
225 | "outputs": [],
226 | "source": []
227 | },
228 | {
229 | "cell_type": "code",
230 | "execution_count": null,
231 | "metadata": {},
232 | "outputs": [],
233 | "source": []
234 | },
235 | {
236 | "cell_type": "code",
237 | "execution_count": null,
238 | "metadata": {},
239 | "outputs": [],
240 | "source": []
241 | }
242 | ],
243 | "metadata": {
244 | "kernelspec": {
245 | "display_name": "Python 3",
246 | "language": "python",
247 | "name": "python3"
248 | },
249 | "language_info": {
250 | "codemirror_mode": {
251 | "name": "ipython",
252 | "version": 3
253 | },
254 | "file_extension": ".py",
255 | "mimetype": "text/x-python",
256 | "name": "python",
257 | "nbconvert_exporter": "python",
258 | "pygments_lexer": "ipython3",
259 | "version": "3.8.5"
260 | }
261 | },
262 | "nbformat": 4,
263 | "nbformat_minor": 4
264 | }
265 |
--------------------------------------------------------------------------------
/Class Exercises/L6/Interleaving.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Class Exercises/L6/Interleaving.xlsx
--------------------------------------------------------------------------------
/Class Exercises/L6/Split Traffic.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "import numpy as np, statsmodels.stats.api as sms\n",
10 | "import matplotlib.pyplot as plt\n",
11 | "import pandas as pd"
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": 15,
17 | "metadata": {},
18 | "outputs": [],
19 | "source": [
20 | "lift = 1.01\n",
21 | "p0 = 0.5\n",
22 | "#Given a fixed size of sample\n",
23 | "totalsamplesize=20000"
24 | ]
25 | },
26 | {
27 | "cell_type": "code",
28 | "execution_count": 16,
29 | "metadata": {},
30 | "outputs": [],
31 | "source": [
32 | "#population mean difference = p1-p0=p0*(lift-1)\n",
33 | "delta=p0*(lift-1)"
34 | ]
35 | },
36 | {
37 | "cell_type": "code",
38 | "execution_count": 17,
39 | "metadata": {},
40 | "outputs": [
41 | {
42 | "name": "stdout",
43 | "output_type": "stream",
44 | "text": [
45 | "0.0050000000000000044 0.5\n"
46 | ]
47 | }
48 | ],
49 | "source": [
50 | "#p(1-p)\n",
51 | "variance=p0*(1-p0)\n",
52 | "std=np.sqrt(variance)\n",
53 | "print(delta,std)"
54 | ]
55 | },
56 | {
57 | "cell_type": "markdown",
58 | "metadata": {},
59 | "source": [
60 | "**Using Simulation**"
61 | ]
62 | },
63 | {
64 | "cell_type": "code",
65 | "execution_count": 6,
66 | "metadata": {},
67 | "outputs": [],
68 | "source": [
69 | "power=[]\n",
70 | "n=100\n",
71 | "m=500\n",
72 | "for s in range(500):\n",
73 | " k =2500+25*(s+1)-100\n",
74 | " ci=[]\n",
75 | " for i in range(n):\n",
76 | " ctrl = np.random.binomial(1, p0, totalsamplesize-k)\n",
77 | " test = np.random.binomial(1, p0*lift, k)\n",
78 | " cm = sms.CompareMeans(sms.DescrStatsW(test), sms.DescrStatsW(ctrl))\n",
79 | " a,b = cm.tconfint_diff(alpha=0.05, alternative='two-sided', usevar='unequal')\n",
80 | " ci.append((a,b))\n",
81 | " t2=sum((x[0]<=0 and x[1]>=0) for x in ci)/n\n",
82 | " pw=1-t2\n",
83 | " # k1/k0\n",
84 | " r=(15000-k)/k\n",
85 | " power.append((r,pw))\n",
86 | " "
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": 7,
92 | "metadata": {},
93 | "outputs": [
94 | {
95 | "data": {
96 | "text/plain": [
97 | "Text(0, 0.5, 'Power')"
98 | ]
99 | },
100 | "execution_count": 7,
101 | "metadata": {},
102 | "output_type": "execute_result"
103 | },
104 | {
105 | "data": {
106 | "image/png": "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\n",
107 | "text/plain": [
108 | ""
109 | ]
110 | },
111 | "metadata": {
112 | "needs_background": "light"
113 | },
114 | "output_type": "display_data"
115 | }
116 | ],
117 | "source": [
118 | "l_y=[x[1] for x in power]\n",
119 | "s_x=[x[0] for x in power]\n",
120 | "\n",
121 | "plt.plot(s_x,l_y)\n",
122 | "plt.title('Traffic Split')\n",
123 | "plt.xlabel('Ratio')\n",
124 | "plt.ylabel('Power')"
125 | ]
126 | },
127 | {
128 | "cell_type": "markdown",
129 | "metadata": {},
130 | "source": [
131 | "**Using the function**"
132 | ]
133 | },
134 | {
135 | "cell_type": "code",
136 | "execution_count": 18,
137 | "metadata": {},
138 | "outputs": [],
139 | "source": [
140 | "from statsmodels.stats.power import zt_ind_solve_power"
141 | ]
142 | },
143 | {
144 | "cell_type": "code",
145 | "execution_count": 19,
146 | "metadata": {},
147 | "outputs": [
148 | {
149 | "name": "stdout",
150 | "output_type": "stream",
151 | "text": [
152 | "0.0050000000000000044 0.010000000000000009\n"
153 | ]
154 | }
155 | ],
156 | "source": [
157 | "effectsize=delta/std\n",
158 | "print(delta,effectsize)"
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": 20,
164 | "metadata": {},
165 | "outputs": [
166 | {
167 | "name": "stdout",
168 | "output_type": "stream",
169 | "text": [
170 | "0.4492753623188406 0.08749203476222268\n",
171 | "0.47058823529411764 0.08815202921008315\n",
172 | "0.4925373134328358 0.08877665993026321\n",
173 | "0.5151515151515151 0.08936587305120942\n",
174 | "0.5384615384615384 0.08991961833450068\n",
175 | "0.5625 0.09043784907560412\n",
176 | "0.5873015873015873 0.09092052201105622\n",
177 | "0.6129032258064516 0.09136759723198883\n",
178 | "0.639344262295082 0.09177903810393061\n",
179 | "0.6666666666666666 0.09215481119281485\n",
180 | "0.6949152542372882 0.09249488619713445\n",
181 | "0.7241379310344828 0.09279923588618337\n",
182 | "0.7543859649122807 0.0930678360443371\n",
183 | "0.7857142857142857 0.09330066542132252\n",
184 | "0.8181818181818182 0.09349770568843596\n",
185 | "0.8518518518518519 0.09365894140067338\n",
186 | "0.8867924528301887 0.09378435996474113\n",
187 | "0.9230769230769231 0.09387395161291817\n",
188 | "0.9607843137254902 0.09392770938275073\n",
189 | "1.0 0.09394562910255964\n",
190 | "1.0408163265306123 0.09392770938275073\n",
191 | "1.0833333333333333 0.09387395161291817\n",
192 | "1.127659574468085 0.09378435996474113\n",
193 | "1.1739130434782612 0.09365894140067338\n",
194 | "1.2222222222222223 0.09349770568843596\n",
195 | "1.2727272727272727 0.09330066542132252\n",
196 | "1.3255813953488371 0.0930678360443371\n",
197 | "1.380952380952381 0.09279923588618337\n",
198 | "1.4390243902439024 0.09249488619713445\n",
199 | "1.5 0.09215481119281485\n",
200 | "1.564102564102564 0.09177903810393061\n",
201 | "1.631578947368421 0.09136759723198883\n",
202 | "1.7027027027027026 0.09092052201105622\n",
203 | "1.7777777777777777 0.09043784907560412\n",
204 | "1.8571428571428572 0.08991961833450068\n",
205 | "1.9411764705882353 0.08936587305120942\n",
206 | "2.0303030303030303 0.08877665993026321\n",
207 | "2.125 0.08815202921008315\n",
208 | "2.225806451612903 0.08749203476222268\n",
209 | "2.3333333333333335 0.0867967341971172\n"
210 | ]
211 | }
212 | ],
213 | "source": [
214 | "power=[]\n",
215 | "lpw=[]\n",
216 | "for s in range(30,70):\n",
217 | " k1 =((s+1)/100)*15000\n",
218 | " k0 = 15000-k1\n",
219 | " r = k1/k0\n",
220 | " pw=zt_ind_solve_power(effect_size=effectsize, nobs1=k0, alpha=0.05, ratio=r, alternative='two-sided')\n",
221 | " power.append((r,pw))\n",
222 | " lpw.append(pw)\n",
223 | " print(r,pw) "
224 | ]
225 | },
226 | {
227 | "cell_type": "code",
228 | "execution_count": 21,
229 | "metadata": {},
230 | "outputs": [
231 | {
232 | "name": "stdout",
233 | "output_type": "stream",
234 | "text": [
235 | "0.09394562910255964\n"
236 | ]
237 | }
238 | ],
239 | "source": [
240 | "#Find the max power\n",
241 | "maxpw=np.max(lpw)\n",
242 | "print(maxpw)"
243 | ]
244 | },
245 | {
246 | "cell_type": "code",
247 | "execution_count": 22,
248 | "metadata": {},
249 | "outputs": [
250 | {
251 | "name": "stdout",
252 | "output_type": "stream",
253 | "text": [
254 | "[1.0]\n"
255 | ]
256 | }
257 | ],
258 | "source": [
259 | "# Find ratio of power = maxpw\n",
260 | "index_=[power.index(x) for x in power if x[1]==maxpw]\n",
261 | "max_r=[power[i][0] for i in index_]\n",
262 | "print(max_r)"
263 | ]
264 | },
265 | {
266 | "cell_type": "code",
267 | "execution_count": 23,
268 | "metadata": {},
269 | "outputs": [
270 | {
271 | "data": {
272 | "text/plain": [
273 | "Text(0, 0.5, 'Power')"
274 | ]
275 | },
276 | "execution_count": 23,
277 | "metadata": {},
278 | "output_type": "execute_result"
279 | },
280 | {
281 | "data": {
282 | "image/png": "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\n",
283 | "text/plain": [
284 | ""
285 | ]
286 | },
287 | "metadata": {
288 | "needs_background": "light"
289 | },
290 | "output_type": "display_data"
291 | }
292 | ],
293 | "source": [
294 | "l_y=[x[1] for x in power]\n",
295 | "s_x=[x[0] for x in power]\n",
296 | "\n",
297 | "plt.plot(s_x,l_y)\n",
298 | "plt.title('Traffic Split')\n",
299 | "plt.xlabel('Ratio')\n",
300 | "plt.ylabel('Power')"
301 | ]
302 | },
303 | {
304 | "cell_type": "code",
305 | "execution_count": null,
306 | "metadata": {},
307 | "outputs": [],
308 | "source": []
309 | },
310 | {
311 | "cell_type": "code",
312 | "execution_count": null,
313 | "metadata": {},
314 | "outputs": [],
315 | "source": []
316 | }
317 | ],
318 | "metadata": {
319 | "kernelspec": {
320 | "display_name": "Python 3",
321 | "language": "python",
322 | "name": "python3"
323 | },
324 | "language_info": {
325 | "codemirror_mode": {
326 | "name": "ipython",
327 | "version": 3
328 | },
329 | "file_extension": ".py",
330 | "mimetype": "text/x-python",
331 | "name": "python",
332 | "nbconvert_exporter": "python",
333 | "pygments_lexer": "ipython3",
334 | "version": "3.7.6"
335 | }
336 | },
337 | "nbformat": 4,
338 | "nbformat_minor": 4
339 | }
340 |
--------------------------------------------------------------------------------
/Class Exercises/L6/cluster.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "## Regression with Clustered Standard Errors"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 16,
13 | "metadata": {},
14 | "outputs": [],
15 | "source": [
16 | "import numpy as np, statsmodels.stats.api as sms\n",
17 | "import itertools\n",
18 | "import matplotlib.pyplot as plt\n",
19 | "from matplotlib.ticker import NullFormatter\n",
20 | "import pandas as pd\n",
21 | "import numpy as np\n",
22 | "import matplotlib.ticker as ticker\n",
23 | "import random\n",
24 | "from sklearn import preprocessing"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": 17,
30 | "metadata": {},
31 | "outputs": [],
32 | "source": [
33 | "infile = 'exp_data_cluster.csv' \n",
34 | "data = pd.read_csv(infile)"
35 | ]
36 | },
37 | {
38 | "cell_type": "code",
39 | "execution_count": 18,
40 | "metadata": {},
41 | "outputs": [
42 | {
43 | "data": {
44 | "text/plain": [
45 | "(16000, 4)"
46 | ]
47 | },
48 | "execution_count": 18,
49 | "metadata": {},
50 | "output_type": "execute_result"
51 | }
52 | ],
53 | "source": [
54 | "data.shape"
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": 19,
60 | "metadata": {},
61 | "outputs": [
62 | {
63 | "data": {
64 | "text/html": [
65 | "\n",
66 | "\n",
79 | "
\n",
80 | " \n",
81 | " \n",
82 | " | \n",
83 | " user | \n",
84 | " adid | \n",
85 | " expid | \n",
86 | " if_click | \n",
87 | "
\n",
88 | " \n",
89 | " \n",
90 | " \n",
91 | " 0 | \n",
92 | " 92092 | \n",
93 | " 1e4fb0d22340fdf9ee02b6ae4a7d9a83 | \n",
94 | " 1 | \n",
95 | " 0 | \n",
96 | "
\n",
97 | " \n",
98 | " 1 | \n",
99 | " 878501 | \n",
100 | " 97fc187415fe1785d5ee02bfd348968e | \n",
101 | " 0 | \n",
102 | " 0 | \n",
103 | "
\n",
104 | " \n",
105 | " 2 | \n",
106 | " 266367 | \n",
107 | " 0b0fa14b56d3741178196daaa92e6a1e | \n",
108 | " 1 | \n",
109 | " 0 | \n",
110 | "
\n",
111 | " \n",
112 | " 3 | \n",
113 | " 329319 | \n",
114 | " 1f1fe825014d9e9a0881233d9950bd43 | \n",
115 | " 1 | \n",
116 | " 0 | \n",
117 | "
\n",
118 | " \n",
119 | " 4 | \n",
120 | " 64672 | \n",
121 | " 5b2ae85128137e449eb015f6de78add5 | \n",
122 | " 0 | \n",
123 | " 0 | \n",
124 | "
\n",
125 | " \n",
126 | "
\n",
127 | "
"
128 | ],
129 | "text/plain": [
130 | " user adid expid if_click\n",
131 | "0 92092 1e4fb0d22340fdf9ee02b6ae4a7d9a83 1 0\n",
132 | "1 878501 97fc187415fe1785d5ee02bfd348968e 0 0\n",
133 | "2 266367 0b0fa14b56d3741178196daaa92e6a1e 1 0\n",
134 | "3 329319 1f1fe825014d9e9a0881233d9950bd43 1 0\n",
135 | "4 64672 5b2ae85128137e449eb015f6de78add5 0 0"
136 | ]
137 | },
138 | "execution_count": 19,
139 | "metadata": {},
140 | "output_type": "execute_result"
141 | }
142 | ],
143 | "source": [
144 | "data.head()"
145 | ]
146 | },
147 | {
148 | "cell_type": "code",
149 | "execution_count": 20,
150 | "metadata": {},
151 | "outputs": [],
152 | "source": [
153 | "import statsmodels.formula.api as smf"
154 | ]
155 | },
156 | {
157 | "cell_type": "markdown",
158 | "metadata": {},
159 | "source": [
160 | "#### OLS with Clustered SE"
161 | ]
162 | },
163 | {
164 | "cell_type": "code",
165 | "execution_count": 24,
166 | "metadata": {},
167 | "outputs": [
168 | {
169 | "name": "stdout",
170 | "output_type": "stream",
171 | "text": [
172 | "Result with cluster\n",
173 | " Results: Ordinary least squares\n",
174 | "==================================================================\n",
175 | "Model: OLS Adj. R-squared: 0.000 \n",
176 | "Dependent Variable: if_click AIC: 1467.5819\n",
177 | "Date: 2023-02-06 20:39 BIC: 1482.9425\n",
178 | "No. Observations: 16000 Log-Likelihood: -731.79 \n",
179 | "Df Model: 1 F-statistic: 6.710 \n",
180 | "Df Residuals: 15998 Prob (F-statistic): 0.00960 \n",
181 | "R-squared: 0.000 Scale: 0.064166 \n",
182 | "--------------------------------------------------------------------\n",
183 | " Coef. Std.Err. z P>|z| [0.025 0.975]\n",
184 | "--------------------------------------------------------------------\n",
185 | "Intercept 0.0638 0.0027 23.3379 0.0000 0.0584 0.0691\n",
186 | "expid 0.0104 0.0040 2.5904 0.0096 0.0025 0.0182\n",
187 | "------------------------------------------------------------------\n",
188 | "Omnibus: 10828.253 Durbin-Watson: 2.012 \n",
189 | "Prob(Omnibus): 0.000 Jarque-Bera (JB): 91921.719\n",
190 | "Skew: 3.401 Prob(JB): 0.000 \n",
191 | "Kurtosis: 12.572 Condition No.: 3 \n",
192 | "==================================================================\n",
193 | "\n"
194 | ]
195 | }
196 | ],
197 | "source": [
198 | "# users' behaviors of the same ads are correlated.\n",
199 | "model = smf.ols(formula='if_click ~ expid', data=data)\n",
200 | "result = model.fit(cov_type='cluster', cov_kwds = {'groups': data.user})\n",
201 | "print('Result with cluster')\n",
202 | "print(result.summary2())"
203 | ]
204 | },
205 | {
206 | "cell_type": "markdown",
207 | "metadata": {},
208 | "source": [
209 | "#### OLS without Clustered SE"
210 | ]
211 | },
212 | {
213 | "cell_type": "code",
214 | "execution_count": 23,
215 | "metadata": {},
216 | "outputs": [
217 | {
218 | "name": "stdout",
219 | "output_type": "stream",
220 | "text": [
221 | "Result without cluster\n",
222 | " Results: Ordinary least squares\n",
223 | "==================================================================\n",
224 | "Model: OLS Adj. R-squared: 0.000 \n",
225 | "Dependent Variable: if_click AIC: 1467.5819\n",
226 | "Date: 2023-02-06 20:39 BIC: 1482.9425\n",
227 | "No. Observations: 16000 Log-Likelihood: -731.79 \n",
228 | "Df Model: 1 F-statistic: 6.710 \n",
229 | "Df Residuals: 15998 Prob (F-statistic): 0.00960 \n",
230 | "R-squared: 0.000 Scale: 0.064166 \n",
231 | "--------------------------------------------------------------------\n",
232 | " Coef. Std.Err. t P>|t| [0.025 0.975]\n",
233 | "--------------------------------------------------------------------\n",
234 | "Intercept 0.0638 0.0028 22.5098 0.0000 0.0582 0.0693\n",
235 | "expid 0.0104 0.0040 2.5904 0.0096 0.0025 0.0182\n",
236 | "------------------------------------------------------------------\n",
237 | "Omnibus: 10828.253 Durbin-Watson: 2.012 \n",
238 | "Prob(Omnibus): 0.000 Jarque-Bera (JB): 91921.719\n",
239 | "Skew: 3.401 Prob(JB): 0.000 \n",
240 | "Kurtosis: 12.572 Condition No.: 3 \n",
241 | "==================================================================\n",
242 | "\n"
243 | ]
244 | }
245 | ],
246 | "source": [
247 | "result = model.fit()\n",
248 | "print('Result without cluster')\n",
249 | "print(result.summary2())"
250 | ]
251 | },
252 | {
253 | "cell_type": "markdown",
254 | "metadata": {},
255 | "source": [
256 | "#### Compare Means with t tests"
257 | ]
258 | },
259 | {
260 | "cell_type": "code",
261 | "execution_count": 7,
262 | "metadata": {},
263 | "outputs": [],
264 | "source": [
265 | "y0 = data[data['expid'] == 0]['if_click']"
266 | ]
267 | },
268 | {
269 | "cell_type": "code",
270 | "execution_count": 8,
271 | "metadata": {},
272 | "outputs": [
273 | {
274 | "name": "stdout",
275 | "output_type": "stream",
276 | "text": [
277 | "0.010374999999999995\n"
278 | ]
279 | }
280 | ],
281 | "source": [
282 | "y1 = data[data['expid'] == 1]['if_click']\n",
283 | "mean_d = np.mean(y1)-np.mean(y0)\n",
284 | "print(mean_d)"
285 | ]
286 | },
287 | {
288 | "cell_type": "code",
289 | "execution_count": 9,
290 | "metadata": {},
291 | "outputs": [
292 | {
293 | "name": "stdout",
294 | "output_type": "stream",
295 | "text": [
296 | "(-2.590388082735368, 0.009595515482880781, 15920.640661495236)\n"
297 | ]
298 | }
299 | ],
300 | "source": [
301 | "cm = sms.CompareMeans(sms.DescrStatsW(y0), sms.DescrStatsW(y1))\n",
302 | "print(cm.ttest_ind(alternative='two-sided', usevar='unequal'))"
303 | ]
304 | },
305 | {
306 | "cell_type": "code",
307 | "execution_count": null,
308 | "metadata": {},
309 | "outputs": [],
310 | "source": []
311 | },
312 | {
313 | "cell_type": "code",
314 | "execution_count": null,
315 | "metadata": {},
316 | "outputs": [],
317 | "source": []
318 | }
319 | ],
320 | "metadata": {
321 | "kernelspec": {
322 | "display_name": "Python 3",
323 | "language": "python",
324 | "name": "python3"
325 | },
326 | "language_info": {
327 | "codemirror_mode": {
328 | "name": "ipython",
329 | "version": 3
330 | },
331 | "file_extension": ".py",
332 | "mimetype": "text/x-python",
333 | "name": "python",
334 | "nbconvert_exporter": "python",
335 | "pygments_lexer": "ipython3",
336 | "version": "3.8.5"
337 | }
338 | },
339 | "nbformat": 4,
340 | "nbformat_minor": 4
341 | }
342 |
--------------------------------------------------------------------------------
/Class Exercises/L6/variance_lift.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 60,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "import numpy as np, statsmodels.stats.api as sms\n",
10 | "import itertools\n",
11 | "import matplotlib.pyplot as plt\n",
12 | "from matplotlib.ticker import NullFormatter\n",
13 | "import pandas as pd\n",
14 | "import numpy as np\n",
15 | "import matplotlib.ticker as ticker\n",
16 | "import random\n",
17 | "from sklearn import preprocessing"
18 | ]
19 | },
20 | {
21 | "cell_type": "code",
22 | "execution_count": 75,
23 | "metadata": {},
24 | "outputs": [
25 | {
26 | "name": "stdout",
27 | "output_type": "stream",
28 | "text": [
29 | "2.999999999999999\n"
30 | ]
31 | }
32 | ],
33 | "source": [
34 | "#Population Characteristics\n",
35 | "lift = 1.2\n",
36 | "ctr0=0.5\n",
37 | "#30*ctr0*lift-30*ctr0\n",
38 | "delta_p = 30*ctr0*(lift-1)\n",
39 | "print(delta_p) "
40 | ]
41 | },
42 | {
43 | "cell_type": "code",
44 | "execution_count": 76,
45 | "metadata": {},
46 | "outputs": [],
47 | "source": [
48 | "#Sample Characteristics\n",
49 | "n0=1000\n",
50 | "n1=1000\n",
51 | "ctrl = np.random.binomial(30, p=ctr0, size=n0) * 1.0\n",
52 | "test = np.random.binomial(30, p=ctr0*lift, size=n1) * 1.0"
53 | ]
54 | },
55 | {
56 | "cell_type": "code",
57 | "execution_count": 77,
58 | "metadata": {},
59 | "outputs": [
60 | {
61 | "name": "stdout",
62 | "output_type": "stream",
63 | "text": [
64 | "1.2041074881642995\n"
65 | ]
66 | }
67 | ],
68 | "source": [
69 | "# Y1 bar and Y0 bar\n",
70 | "m1=np.mean(test)\n",
71 | "m0=np.mean(ctrl) \n",
72 | "lift_ob=m1/m0\n",
73 | "print(lift_ob)"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": 78,
79 | "metadata": {},
80 | "outputs": [
81 | {
82 | "name": "stdout",
83 | "output_type": "stream",
84 | "text": [
85 | "7.204195195195196 7.113749749749751\n"
86 | ]
87 | }
88 | ],
89 | "source": [
90 | "# variance of Y1 and Yo\n",
91 | "var0 = np.var(ctrl,ddof=1)\n",
92 | "var1 = np.var(test,ddof=1)\n",
93 | "print(var0,var1)"
94 | ]
95 | },
96 | {
97 | "cell_type": "code",
98 | "execution_count": 79,
99 | "metadata": {},
100 | "outputs": [
101 | {
102 | "name": "stdout",
103 | "output_type": "stream",
104 | "text": [
105 | "0.007204195195195196 0.007113749749749751\n"
106 | ]
107 | }
108 | ],
109 | "source": [
110 | "# variance of Y1 bar,m1 and Y0 bar,m0\n",
111 | "var_m0=var0/n0\n",
112 | "var_m1=var1/n1\n",
113 | "print(var_m0, var_m1)"
114 | ]
115 | },
116 | {
117 | "cell_type": "code",
118 | "execution_count": 80,
119 | "metadata": {},
120 | "outputs": [],
121 | "source": [
122 | "#var(lift)\n",
123 | "var_lift = (1/m0**2)*var_m1+(m1**2/m0**4)*var_m0"
124 | ]
125 | },
126 | {
127 | "cell_type": "code",
128 | "execution_count": 81,
129 | "metadata": {},
130 | "outputs": [],
131 | "source": [
132 | "se_lift=np.sqrt(var_lift)"
133 | ]
134 | },
135 | {
136 | "cell_type": "code",
137 | "execution_count": 82,
138 | "metadata": {},
139 | "outputs": [
140 | {
141 | "name": "stdout",
142 | "output_type": "stream",
143 | "text": [
144 | "0.008835774960112465\n"
145 | ]
146 | }
147 | ],
148 | "source": [
149 | "print(se_lift)"
150 | ]
151 | },
152 | {
153 | "cell_type": "code",
154 | "execution_count": 83,
155 | "metadata": {},
156 | "outputs": [],
157 | "source": [
158 | "ci = (lift-1.96*se_lift,lift+1.96*se_lift)"
159 | ]
160 | },
161 | {
162 | "cell_type": "code",
163 | "execution_count": 84,
164 | "metadata": {},
165 | "outputs": [
166 | {
167 | "name": "stdout",
168 | "output_type": "stream",
169 | "text": [
170 | "(1.1826818810781796, 1.2173181189218203)\n"
171 | ]
172 | }
173 | ],
174 | "source": [
175 | "print(ci)"
176 | ]
177 | },
178 | {
179 | "cell_type": "code",
180 | "execution_count": 85,
181 | "metadata": {},
182 | "outputs": [
183 | {
184 | "name": "stdout",
185 | "output_type": "stream",
186 | "text": [
187 | "Requirement already satisfied: bootstrapped in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (0.0.2)\n",
188 | "Requirement already satisfied: matplotlib>=1.5.3 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from bootstrapped) (3.3.2)\n",
189 | "Requirement already satisfied: pandas>=0.18.1 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from bootstrapped) (1.1.3)\n",
190 | "Requirement already satisfied: numpy>=1.11.1 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from bootstrapped) (1.19.2)\n",
191 | "Requirement already satisfied: cycler>=0.10 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (0.10.0)\n",
192 | "Requirement already satisfied: certifi>=2020.06.20 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (2020.6.20)\n",
193 | "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.3 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (2.4.7)\n",
194 | "Requirement already satisfied: pillow>=6.2.0 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (8.0.1)\n",
195 | "Requirement already satisfied: kiwisolver>=1.0.1 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (1.3.0)\n",
196 | "Requirement already satisfied: python-dateutil>=2.1 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from matplotlib>=1.5.3->bootstrapped) (2.8.1)\n",
197 | "Requirement already satisfied: pytz>=2017.2 in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from pandas>=0.18.1->bootstrapped) (2020.1)\n",
198 | "Requirement already satisfied: six in /Users/shan_huang/opt/anaconda3/lib/python3.8/site-packages (from cycler>=0.10->matplotlib>=1.5.3->bootstrapped) (1.15.0)\n",
199 | "Note: you may need to restart the kernel to use updated packages.\n"
200 | ]
201 | }
202 | ],
203 | "source": [
204 | "pip install bootstrapped"
205 | ]
206 | },
207 | {
208 | "cell_type": "code",
209 | "execution_count": 86,
210 | "metadata": {},
211 | "outputs": [],
212 | "source": [
213 | "import bootstrapped.bootstrap as bs\n",
214 | "import bootstrapped.compare_functions as bs_compare\n",
215 | "import bootstrapped.stats_functions as bs_stats"
216 | ]
217 | },
218 | {
219 | "cell_type": "code",
220 | "execution_count": 87,
221 | "metadata": {},
222 | "outputs": [],
223 | "source": [
224 | "ctrl = np.array(ctrl)\n",
225 | "test = np.array(test)"
226 | ]
227 | },
228 | {
229 | "cell_type": "code",
230 | "execution_count": 88,
231 | "metadata": {},
232 | "outputs": [
233 | {
234 | "name": "stdout",
235 | "output_type": "stream",
236 | "text": [
237 | "20.410748816429955 (18.735809923471688, 22.158128040221964)\n"
238 | ]
239 | }
240 | ],
241 | "source": [
242 | "print(bs.bootstrap_ab(\n",
243 | " test, \n",
244 | " ctrl, \n",
245 | " stat_func=bs_stats.mean,\n",
246 | " compare_func=bs_compare.percent_change,\n",
247 | " alpha=0.05))"
248 | ]
249 | },
250 | {
251 | "cell_type": "code",
252 | "execution_count": null,
253 | "metadata": {},
254 | "outputs": [],
255 | "source": []
256 | },
257 | {
258 | "cell_type": "code",
259 | "execution_count": null,
260 | "metadata": {},
261 | "outputs": [],
262 | "source": []
263 | },
264 | {
265 | "cell_type": "code",
266 | "execution_count": null,
267 | "metadata": {},
268 | "outputs": [],
269 | "source": []
270 | }
271 | ],
272 | "metadata": {
273 | "kernelspec": {
274 | "display_name": "Python 3",
275 | "language": "python",
276 | "name": "python3"
277 | },
278 | "language_info": {
279 | "codemirror_mode": {
280 | "name": "ipython",
281 | "version": 3
282 | },
283 | "file_extension": ".py",
284 | "mimetype": "text/x-python",
285 | "name": "python",
286 | "nbconvert_exporter": "python",
287 | "pygments_lexer": "ipython3",
288 | "version": "3.8.5"
289 | }
290 | },
291 | "nbformat": 4,
292 | "nbformat_minor": 4
293 | }
294 |
--------------------------------------------------------------------------------
/Class Exercises/L6/~$Interleaving.xlsx:
--------------------------------------------------------------------------------
1 | Microsoft Office User M i c r o s o f t O f f i c e U s e r
--------------------------------------------------------------------------------
/Class Exercises/L7/Control_Variables.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "import numpy as np\n",
10 | "import statsmodels.stats.api as sms\n",
11 | "import matplotlib.pyplot as plt\n",
12 | "import pandas as pd\n",
13 | "import statsmodels.formula.api as smf\n",
14 | "import random"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 2,
20 | "metadata": {},
21 | "outputs": [],
22 | "source": [
23 | "infile = 'exp_data_3.csv'\n",
24 | "df = pd.read_csv(infile)"
25 | ]
26 | },
27 | {
28 | "cell_type": "code",
29 | "execution_count": 3,
30 | "metadata": {},
31 | "outputs": [
32 | {
33 | "data": {
34 | "text/html": [
35 | "\n",
36 | "\n",
49 | "
\n",
50 | " \n",
51 | " \n",
52 | " | \n",
53 | " user | \n",
54 | " click | \n",
55 | " like | \n",
56 | " age | \n",
57 | " gender | \n",
58 | " friend_cnt | \n",
59 | " sns_like_cnt | \n",
60 | " sns_comment_cnt | \n",
61 | " pre_click | \n",
62 | " treat | \n",
63 | "
\n",
64 | " \n",
65 | " \n",
66 | " \n",
67 | " 0 | \n",
68 | " 1 | \n",
69 | " 1 | \n",
70 | " 0 | \n",
71 | " 34 | \n",
72 | " 2 | \n",
73 | " 230 | \n",
74 | " 209 | \n",
75 | " 320 | \n",
76 | " 1 | \n",
77 | " 0 | \n",
78 | "
\n",
79 | " \n",
80 | " 1 | \n",
81 | " 4 | \n",
82 | " 0 | \n",
83 | " 0 | \n",
84 | " 26 | \n",
85 | " 2 | \n",
86 | " 168 | \n",
87 | " 46 | \n",
88 | " 113 | \n",
89 | " 0 | \n",
90 | " 0 | \n",
91 | "
\n",
92 | " \n",
93 | " 2 | \n",
94 | " 5 | \n",
95 | " 0 | \n",
96 | " 0 | \n",
97 | " 24 | \n",
98 | " 2 | \n",
99 | " 105 | \n",
100 | " 7 | \n",
101 | " 30 | \n",
102 | " 0 | \n",
103 | " 1 | \n",
104 | "
\n",
105 | " \n",
106 | " 3 | \n",
107 | " 6 | \n",
108 | " 0 | \n",
109 | " 0 | \n",
110 | " 39 | \n",
111 | " 1 | \n",
112 | " 167 | \n",
113 | " 23 | \n",
114 | " 35 | \n",
115 | " 0 | \n",
116 | " 0 | \n",
117 | "
\n",
118 | " \n",
119 | " 4 | \n",
120 | " 7 | \n",
121 | " 0 | \n",
122 | " 0 | \n",
123 | " 39 | \n",
124 | " 2 | \n",
125 | " 443 | \n",
126 | " 24 | \n",
127 | " 155 | \n",
128 | " 0 | \n",
129 | " 1 | \n",
130 | "
\n",
131 | " \n",
132 | " ... | \n",
133 | " ... | \n",
134 | " ... | \n",
135 | " ... | \n",
136 | " ... | \n",
137 | " ... | \n",
138 | " ... | \n",
139 | " ... | \n",
140 | " ... | \n",
141 | " ... | \n",
142 | " ... | \n",
143 | "
\n",
144 | " \n",
145 | " 95 | \n",
146 | " 137 | \n",
147 | " 0 | \n",
148 | " 0 | \n",
149 | " 27 | \n",
150 | " 2 | \n",
151 | " 485 | \n",
152 | " 61 | \n",
153 | " 53 | \n",
154 | " 0 | \n",
155 | " 1 | \n",
156 | "
\n",
157 | " \n",
158 | " 96 | \n",
159 | " 138 | \n",
160 | " 0 | \n",
161 | " 0 | \n",
162 | " 34 | \n",
163 | " 2 | \n",
164 | " 387 | \n",
165 | " 1764 | \n",
166 | " 1983 | \n",
167 | " 0 | \n",
168 | " 1 | \n",
169 | "
\n",
170 | " \n",
171 | " 97 | \n",
172 | " 139 | \n",
173 | " 0 | \n",
174 | " 0 | \n",
175 | " 30 | \n",
176 | " 2 | \n",
177 | " 555 | \n",
178 | " 30 | \n",
179 | " 318 | \n",
180 | " 0 | \n",
181 | " 0 | \n",
182 | "
\n",
183 | " \n",
184 | " 98 | \n",
185 | " 140 | \n",
186 | " 0 | \n",
187 | " 0 | \n",
188 | " 28 | \n",
189 | " 2 | \n",
190 | " 202 | \n",
191 | " 105 | \n",
192 | " 328 | \n",
193 | " 0 | \n",
194 | " 0 | \n",
195 | "
\n",
196 | " \n",
197 | " 99 | \n",
198 | " 141 | \n",
199 | " 0 | \n",
200 | " 0 | \n",
201 | " 19 | \n",
202 | " 1 | \n",
203 | " 262 | \n",
204 | " 97 | \n",
205 | " 167 | \n",
206 | " 0 | \n",
207 | " 1 | \n",
208 | "
\n",
209 | " \n",
210 | "
\n",
211 | "
100 rows × 10 columns
\n",
212 | "
"
213 | ],
214 | "text/plain": [
215 | " user click like age gender friend_cnt sns_like_cnt sns_comment_cnt \\\n",
216 | "0 1 1 0 34 2 230 209 320 \n",
217 | "1 4 0 0 26 2 168 46 113 \n",
218 | "2 5 0 0 24 2 105 7 30 \n",
219 | "3 6 0 0 39 1 167 23 35 \n",
220 | "4 7 0 0 39 2 443 24 155 \n",
221 | ".. ... ... ... ... ... ... ... ... \n",
222 | "95 137 0 0 27 2 485 61 53 \n",
223 | "96 138 0 0 34 2 387 1764 1983 \n",
224 | "97 139 0 0 30 2 555 30 318 \n",
225 | "98 140 0 0 28 2 202 105 328 \n",
226 | "99 141 0 0 19 1 262 97 167 \n",
227 | "\n",
228 | " pre_click treat \n",
229 | "0 1 0 \n",
230 | "1 0 0 \n",
231 | "2 0 1 \n",
232 | "3 0 0 \n",
233 | "4 0 1 \n",
234 | ".. ... ... \n",
235 | "95 0 1 \n",
236 | "96 0 1 \n",
237 | "97 0 0 \n",
238 | "98 0 0 \n",
239 | "99 0 1 \n",
240 | "\n",
241 | "[100 rows x 10 columns]"
242 | ]
243 | },
244 | "execution_count": 3,
245 | "metadata": {},
246 | "output_type": "execute_result"
247 | }
248 | ],
249 | "source": [
250 | "df.head(100)"
251 | ]
252 | },
253 | {
254 | "cell_type": "code",
255 | "execution_count": 4,
256 | "metadata": {},
257 | "outputs": [
258 | {
259 | "data": {
260 | "text/plain": [
261 | "(7999, 10)"
262 | ]
263 | },
264 | "execution_count": 4,
265 | "metadata": {},
266 | "output_type": "execute_result"
267 | }
268 | ],
269 | "source": [
270 | "df.shape"
271 | ]
272 | },
273 | {
274 | "cell_type": "markdown",
275 | "metadata": {},
276 | "source": [
277 | "### **1. CUPED**\n",
278 | "Controlled Experiments by Utilizing Pre-Experiment Data (Deng, Xu, Kohavi, & Walker, 2013) \n",
279 | "Remove variance in a metric that can be accounted for by pre-experiment information.\n",
280 | "Control Variates: Pre-experiment information.\n"
281 | ]
282 | },
283 | {
284 | "cell_type": "markdown",
285 | "metadata": {},
286 | "source": [
287 | "#### 1.1 Define CUPED"
288 | ]
289 | },
290 | {
291 | "cell_type": "code",
292 | "execution_count": 5,
293 | "metadata": {},
294 | "outputs": [
295 | {
296 | "name": "stdout",
297 | "output_type": "stream",
298 | "text": [
299 | "0.05154226423839803\n"
300 | ]
301 | }
302 | ],
303 | "source": [
304 | "#x is preclick\n",
305 | "var_x=np.var(df.pre_click, ddof=1)\n",
306 | "print(var_x)"
307 | ]
308 | },
309 | {
310 | "cell_type": "code",
311 | "execution_count": 7,
312 | "metadata": {},
313 | "outputs": [
314 | {
315 | "name": "stdout",
316 | "output_type": "stream",
317 | "text": [
318 | "0.03190474453217632\n"
319 | ]
320 | }
321 | ],
322 | "source": [
323 | "#np.cov returns a var-cov metrix\n",
324 | "cov_xy = np.cov(df.pre_click,df.click, ddof=1)[0][1]\n",
325 | "print(cov_xy)"
326 | ]
327 | },
328 | {
329 | "cell_type": "code",
330 | "execution_count": 8,
331 | "metadata": {},
332 | "outputs": [
333 | {
334 | "name": "stdout",
335 | "output_type": "stream",
336 | "text": [
337 | "0.6190016097198905\n"
338 | ]
339 | }
340 | ],
341 | "source": [
342 | "theta = cov_xy/var_x\n",
343 | "print(theta)\n",
344 | "df['theta']=theta "
345 | ]
346 | },
347 | {
348 | "cell_type": "code",
349 | "execution_count": 15,
350 | "metadata": {},
351 | "outputs": [
352 | {
353 | "name": "stdout",
354 | "output_type": "stream",
355 | "text": [
356 | "0.0010019387709386388\n"
357 | ]
358 | }
359 | ],
360 | "source": [
361 | "# different X\n",
362 | "var_x=np.var(df.age, ddof=1)\n",
363 | "cov_xy = np.cov(df.age,df.click, ddof=1)[0][1]\n",
364 | "theta = cov_xy/var_x\n",
365 | "print(theta)"
366 | ]
367 | },
368 | {
369 | "cell_type": "code",
370 | "execution_count": 9,
371 | "metadata": {},
372 | "outputs": [
373 | {
374 | "data": {
375 | "text/html": [
376 | "\n",
377 | "\n",
390 | "
\n",
391 | " \n",
392 | " \n",
393 | " | \n",
394 | " user | \n",
395 | " click | \n",
396 | " like | \n",
397 | " age | \n",
398 | " gender | \n",
399 | " friend_cnt | \n",
400 | " sns_like_cnt | \n",
401 | " sns_comment_cnt | \n",
402 | " pre_click | \n",
403 | " treat | \n",
404 | " theta | \n",
405 | " click_cuped | \n",
406 | "
\n",
407 | " \n",
408 | " \n",
409 | " \n",
410 | " 0 | \n",
411 | " 1 | \n",
412 | " 1 | \n",
413 | " 0 | \n",
414 | " 34 | \n",
415 | " 2 | \n",
416 | " 230 | \n",
417 | " 209 | \n",
418 | " 320 | \n",
419 | " 1 | \n",
420 | " 0 | \n",
421 | " 0.619002 | \n",
422 | " 0.380998 | \n",
423 | "
\n",
424 | " \n",
425 | " 1 | \n",
426 | " 4 | \n",
427 | " 0 | \n",
428 | " 0 | \n",
429 | " 26 | \n",
430 | " 2 | \n",
431 | " 168 | \n",
432 | " 46 | \n",
433 | " 113 | \n",
434 | " 0 | \n",
435 | " 0 | \n",
436 | " 0.619002 | \n",
437 | " 0.000000 | \n",
438 | "
\n",
439 | " \n",
440 | " 2 | \n",
441 | " 5 | \n",
442 | " 0 | \n",
443 | " 0 | \n",
444 | " 24 | \n",
445 | " 2 | \n",
446 | " 105 | \n",
447 | " 7 | \n",
448 | " 30 | \n",
449 | " 0 | \n",
450 | " 1 | \n",
451 | " 0.619002 | \n",
452 | " 0.000000 | \n",
453 | "
\n",
454 | " \n",
455 | " 3 | \n",
456 | " 6 | \n",
457 | " 0 | \n",
458 | " 0 | \n",
459 | " 39 | \n",
460 | " 1 | \n",
461 | " 167 | \n",
462 | " 23 | \n",
463 | " 35 | \n",
464 | " 0 | \n",
465 | " 0 | \n",
466 | " 0.619002 | \n",
467 | " 0.000000 | \n",
468 | "
\n",
469 | " \n",
470 | " 4 | \n",
471 | " 7 | \n",
472 | " 0 | \n",
473 | " 0 | \n",
474 | " 39 | \n",
475 | " 2 | \n",
476 | " 443 | \n",
477 | " 24 | \n",
478 | " 155 | \n",
479 | " 0 | \n",
480 | " 1 | \n",
481 | " 0.619002 | \n",
482 | " 0.000000 | \n",
483 | "
\n",
484 | " \n",
485 | " ... | \n",
486 | " ... | \n",
487 | " ... | \n",
488 | " ... | \n",
489 | " ... | \n",
490 | " ... | \n",
491 | " ... | \n",
492 | " ... | \n",
493 | " ... | \n",
494 | " ... | \n",
495 | " ... | \n",
496 | " ... | \n",
497 | " ... | \n",
498 | "
\n",
499 | " \n",
500 | " 95 | \n",
501 | " 137 | \n",
502 | " 0 | \n",
503 | " 0 | \n",
504 | " 27 | \n",
505 | " 2 | \n",
506 | " 485 | \n",
507 | " 61 | \n",
508 | " 53 | \n",
509 | " 0 | \n",
510 | " 1 | \n",
511 | " 0.619002 | \n",
512 | " 0.000000 | \n",
513 | "
\n",
514 | " \n",
515 | " 96 | \n",
516 | " 138 | \n",
517 | " 0 | \n",
518 | " 0 | \n",
519 | " 34 | \n",
520 | " 2 | \n",
521 | " 387 | \n",
522 | " 1764 | \n",
523 | " 1983 | \n",
524 | " 0 | \n",
525 | " 1 | \n",
526 | " 0.619002 | \n",
527 | " 0.000000 | \n",
528 | "
\n",
529 | " \n",
530 | " 97 | \n",
531 | " 139 | \n",
532 | " 0 | \n",
533 | " 0 | \n",
534 | " 30 | \n",
535 | " 2 | \n",
536 | " 555 | \n",
537 | " 30 | \n",
538 | " 318 | \n",
539 | " 0 | \n",
540 | " 0 | \n",
541 | " 0.619002 | \n",
542 | " 0.000000 | \n",
543 | "
\n",
544 | " \n",
545 | " 98 | \n",
546 | " 140 | \n",
547 | " 0 | \n",
548 | " 0 | \n",
549 | " 28 | \n",
550 | " 2 | \n",
551 | " 202 | \n",
552 | " 105 | \n",
553 | " 328 | \n",
554 | " 0 | \n",
555 | " 0 | \n",
556 | " 0.619002 | \n",
557 | " 0.000000 | \n",
558 | "
\n",
559 | " \n",
560 | " 99 | \n",
561 | " 141 | \n",
562 | " 0 | \n",
563 | " 0 | \n",
564 | " 19 | \n",
565 | " 1 | \n",
566 | " 262 | \n",
567 | " 97 | \n",
568 | " 167 | \n",
569 | " 0 | \n",
570 | " 1 | \n",
571 | " 0.619002 | \n",
572 | " 0.000000 | \n",
573 | "
\n",
574 | " \n",
575 | "
\n",
576 | "
100 rows × 12 columns
\n",
577 | "
"
578 | ],
579 | "text/plain": [
580 | " user click like age gender friend_cnt sns_like_cnt sns_comment_cnt \\\n",
581 | "0 1 1 0 34 2 230 209 320 \n",
582 | "1 4 0 0 26 2 168 46 113 \n",
583 | "2 5 0 0 24 2 105 7 30 \n",
584 | "3 6 0 0 39 1 167 23 35 \n",
585 | "4 7 0 0 39 2 443 24 155 \n",
586 | ".. ... ... ... ... ... ... ... ... \n",
587 | "95 137 0 0 27 2 485 61 53 \n",
588 | "96 138 0 0 34 2 387 1764 1983 \n",
589 | "97 139 0 0 30 2 555 30 318 \n",
590 | "98 140 0 0 28 2 202 105 328 \n",
591 | "99 141 0 0 19 1 262 97 167 \n",
592 | "\n",
593 | " pre_click treat theta click_cuped \n",
594 | "0 1 0 0.619002 0.380998 \n",
595 | "1 0 0 0.619002 0.000000 \n",
596 | "2 0 1 0.619002 0.000000 \n",
597 | "3 0 0 0.619002 0.000000 \n",
598 | "4 0 1 0.619002 0.000000 \n",
599 | ".. ... ... ... ... \n",
600 | "95 0 1 0.619002 0.000000 \n",
601 | "96 0 1 0.619002 0.000000 \n",
602 | "97 0 0 0.619002 0.000000 \n",
603 | "98 0 0 0.619002 0.000000 \n",
604 | "99 0 1 0.619002 0.000000 \n",
605 | "\n",
606 | "[100 rows x 12 columns]"
607 | ]
608 | },
609 | "execution_count": 9,
610 | "metadata": {},
611 | "output_type": "execute_result"
612 | }
613 | ],
614 | "source": [
615 | "df['click_cuped']=df.click - df.pre_click*theta\n",
616 | "df.head(100)"
617 | ]
618 | },
619 | {
620 | "cell_type": "markdown",
621 | "metadata": {},
622 | "source": [
623 | "#### 1.2 T-Test Without CUPED"
624 | ]
625 | },
626 | {
627 | "cell_type": "code",
628 | "execution_count": 12,
629 | "metadata": {},
630 | "outputs": [
631 | {
632 | "name": "stdout",
633 | "output_type": "stream",
634 | "text": [
635 | "-0.003601024491467819\n"
636 | ]
637 | }
638 | ],
639 | "source": [
640 | "d_0 = df[df['treat'] == 0]['click']\n",
641 | "d_1 = df[df['treat'] == 1]['click']\n",
642 | "diff = np.mean(d_1) - np.mean(d_0)\n",
643 | "print(diff)"
644 | ]
645 | },
646 | {
647 | "cell_type": "code",
648 | "execution_count": 13,
649 | "metadata": {},
650 | "outputs": [
651 | {
652 | "name": "stdout",
653 | "output_type": "stream",
654 | "text": [
655 | "0.004052064006037295 (-0.8886889462018719, 0.3741970443208038, 7984.625655071232)\n"
656 | ]
657 | }
658 | ],
659 | "source": [
660 | "cm = sms.CompareMeans(sms.DescrStatsW(d_1), sms.DescrStatsW(d_0))\n",
661 | "ttest = cm.ttest_ind(alternative = 'two-sided', usevar = 'unequal')\n",
662 | "se = cm.std_meandiff_separatevar\n",
663 | "print(se,ttest)"
664 | ]
665 | },
666 | {
667 | "cell_type": "markdown",
668 | "metadata": {},
669 | "source": [
670 | "#### 1.3 T-Test With CUPED"
671 | ]
672 | },
673 | {
674 | "cell_type": "code",
675 | "execution_count": 11,
676 | "metadata": {},
677 | "outputs": [
678 | {
679 | "name": "stdout",
680 | "output_type": "stream",
681 | "text": [
682 | "-0.003997530453238325\n"
683 | ]
684 | }
685 | ],
686 | "source": [
687 | "d_0_cuped = df[df['treat'] == 0]['click_cuped']\n",
688 | "d_1_cuped = df[df['treat'] == 1]['click_cuped']\n",
689 | "diff = np.mean(d_1_cuped) - np.mean(d_0_cuped)\n",
690 | "print(diff)"
691 | ]
692 | },
693 | {
694 | "cell_type": "code",
695 | "execution_count": 13,
696 | "metadata": {},
697 | "outputs": [
698 | {
699 | "name": "stdout",
700 | "output_type": "stream",
701 | "text": [
702 | "0.0025601980289050017 (-1.5614145500096597, 0.1184656562164157, 7973.716532346689)\n"
703 | ]
704 | }
705 | ],
706 | "source": [
707 | "cm = sms.CompareMeans(sms.DescrStatsW(d_1_cuped), sms.DescrStatsW(d_0_cuped))\n",
708 | "ttest = cm.ttest_ind(alternative = 'two-sided', usevar = 'unequal')\n",
709 | "se = cm.std_meandiff_separatevar\n",
710 | "print(se,ttest)"
711 | ]
712 | },
713 | {
714 | "cell_type": "markdown",
715 | "metadata": {},
716 | "source": [
717 | "### **2. Regression**"
718 | ]
719 | },
720 | {
721 | "cell_type": "code",
722 | "execution_count": 16,
723 | "metadata": {},
724 | "outputs": [
725 | {
726 | "name": "stdout",
727 | "output_type": "stream",
728 | "text": [
729 | " OLS Regression Results \n",
730 | "==============================================================================\n",
731 | "Dep. Variable: click R-squared: 0.000\n",
732 | "Model: OLS Adj. R-squared: -0.000\n",
733 | "Method: Least Squares F-statistic: 0.7893\n",
734 | "Date: Thu, 16 Feb 2023 Prob (F-statistic): 0.374\n",
735 | "Time: 20:05:01 Log-Likelihood: 2312.1\n",
736 | "No. Observations: 7999 AIC: -4620.\n",
737 | "Df Residuals: 7997 BIC: -4606.\n",
738 | "Df Model: 1 \n",
739 | "Covariance Type: nonrobust \n",
740 | "==============================================================================\n",
741 | " coef std err t P>|t| [0.025 0.975]\n",
742 | "------------------------------------------------------------------------------\n",
743 | "Intercept 0.0358 0.003 12.526 0.000 0.030 0.041\n",
744 | "treat -0.0036 0.004 -0.888 0.374 -0.012 0.004\n",
745 | "==============================================================================\n",
746 | "Omnibus: 7871.185 Durbin-Watson: 1.990\n",
747 | "Prob(Omnibus): 0.000 Jarque-Bera (JB): 234297.485\n",
748 | "Skew: 5.142 Prob(JB): 0.00\n",
749 | "Kurtosis: 27.438 Cond. No. 2.61\n",
750 | "==============================================================================\n",
751 | "\n",
752 | "Notes:\n",
753 | "[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n"
754 | ]
755 | }
756 | ],
757 | "source": [
758 | "mod = smf.ols(formula='click ~ treat', data=df)\n",
759 | "res = mod.fit()\n",
760 | "print(res.summary())"
761 | ]
762 | },
763 | {
764 | "cell_type": "markdown",
765 | "metadata": {},
766 | "source": [
767 | "#### 2.1 Regression + pre_click (control variable)"
768 | ]
769 | },
770 | {
771 | "cell_type": "code",
772 | "execution_count": 17,
773 | "metadata": {},
774 | "outputs": [
775 | {
776 | "name": "stdout",
777 | "output_type": "stream",
778 | "text": [
779 | " OLS Regression Results \n",
780 | "==============================================================================\n",
781 | "Dep. Variable: click R-squared: 0.601\n",
782 | "Model: OLS Adj. R-squared: 0.601\n",
783 | "Method: Least Squares F-statistic: 6029.\n",
784 | "Date: Thu, 16 Feb 2023 Prob (F-statistic): 0.00\n",
785 | "Time: 20:06:30 Log-Likelihood: 5989.1\n",
786 | "No. Observations: 7999 AIC: -1.197e+04\n",
787 | "Df Residuals: 7996 BIC: -1.195e+04\n",
788 | "Df Model: 2 \n",
789 | "Covariance Type: nonrobust \n",
790 | "==============================================================================\n",
791 | " coef std err t P>|t| [0.025 0.975]\n",
792 | "------------------------------------------------------------------------------\n",
793 | "Intercept 0.0023 0.002 1.230 0.219 -0.001 0.006\n",
794 | "treat -0.0040 0.003 -1.562 0.118 -0.009 0.001\n",
795 | "pre_click 0.6190 0.006 109.799 0.000 0.608 0.630\n",
796 | "==============================================================================\n",
797 | "Omnibus: 4168.834 Durbin-Watson: 1.993\n",
798 | "Prob(Omnibus): 0.000 Jarque-Bera (JB): 142812.742\n",
799 | "Skew: -1.877 Prob(JB): 0.00\n",
800 | "Kurtosis: 23.357 Cond. No. 5.05\n",
801 | "==============================================================================\n",
802 | "\n",
803 | "Notes:\n",
804 | "[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n"
805 | ]
806 | }
807 | ],
808 | "source": [
809 | "mod = smf.ols(formula='click ~ treat + pre_click', data=df)\n",
810 | "res = mod.fit()\n",
811 | "print(res.summary())"
812 | ]
813 | },
814 | {
815 | "cell_type": "markdown",
816 | "metadata": {},
817 | "source": [
818 | "### 2.2 + Gender"
819 | ]
820 | },
821 | {
822 | "cell_type": "code",
823 | "execution_count": 18,
824 | "metadata": {},
825 | "outputs": [
826 | {
827 | "name": "stdout",
828 | "output_type": "stream",
829 | "text": [
830 | " OLS Regression Results \n",
831 | "==============================================================================\n",
832 | "Dep. Variable: click R-squared: 0.003\n",
833 | "Model: OLS Adj. R-squared: 0.003\n",
834 | "Method: Least Squares F-statistic: 12.22\n",
835 | "Date: Thu, 16 Feb 2023 Prob (F-statistic): 5.01e-06\n",
836 | "Time: 20:07:41 Log-Likelihood: 2323.9\n",
837 | "No. Observations: 7999 AIC: -4642.\n",
838 | "Df Residuals: 7996 BIC: -4621.\n",
839 | "Df Model: 2 \n",
840 | "Covariance Type: nonrobust \n",
841 | "==============================================================================\n",
842 | " coef std err t P>|t| [0.025 0.975]\n",
843 | "------------------------------------------------------------------------------\n",
844 | "Intercept 0.0667 0.007 9.580 0.000 0.053 0.080\n",
845 | "treat -0.0037 0.004 -0.918 0.359 -0.012 0.004\n",
846 | "gender -0.0198 0.004 -4.864 0.000 -0.028 -0.012\n",
847 | "==============================================================================\n",
848 | "Omnibus: 7846.678 Durbin-Watson: 1.990\n",
849 | "Prob(Omnibus): 0.000 Jarque-Bera (JB): 231655.229\n",
850 | "Skew: 5.119 Prob(JB): 0.00\n",
851 | "Kurtosis: 27.295 Cond. No. 7.75\n",
852 | "==============================================================================\n",
853 | "\n",
854 | "Notes:\n",
855 | "[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n"
856 | ]
857 | }
858 | ],
859 | "source": [
860 | "mod = smf.ols(formula='click ~ treat + gender', data=df)\n",
861 | "res = mod.fit()\n",
862 | "print(res.summary())"
863 | ]
864 | },
865 | {
866 | "cell_type": "markdown",
867 | "metadata": {},
868 | "source": [
869 | "#### + Gender, Pre-Click"
870 | ]
871 | },
872 | {
873 | "cell_type": "code",
874 | "execution_count": 19,
875 | "metadata": {},
876 | "outputs": [
877 | {
878 | "name": "stdout",
879 | "output_type": "stream",
880 | "text": [
881 | " OLS Regression Results \n",
882 | "==============================================================================\n",
883 | "Dep. Variable: click R-squared: 0.602\n",
884 | "Model: OLS Adj. R-squared: 0.602\n",
885 | "Method: Least Squares F-statistic: 4032.\n",
886 | "Date: Thu, 16 Feb 2023 Prob (F-statistic): 0.00\n",
887 | "Time: 20:09:31 Log-Likelihood: 5996.7\n",
888 | "No. Observations: 7999 AIC: -1.199e+04\n",
889 | "Df Residuals: 7995 BIC: -1.196e+04\n",
890 | "Df Model: 3 \n",
891 | "Covariance Type: nonrobust \n",
892 | "==============================================================================\n",
893 | " coef std err t P>|t| [0.025 0.975]\n",
894 | "------------------------------------------------------------------------------\n",
895 | "Intercept 0.0180 0.004 4.063 0.000 0.009 0.027\n",
896 | "treat -0.0041 0.003 -1.585 0.113 -0.009 0.001\n",
897 | "gender -0.0101 0.003 -3.904 0.000 -0.015 -0.005\n",
898 | "pre_click 0.6183 0.006 109.697 0.000 0.607 0.629\n",
899 | "==============================================================================\n",
900 | "Omnibus: 4157.532 Durbin-Watson: 1.995\n",
901 | "Prob(Omnibus): 0.000 Jarque-Bera (JB): 141808.657\n",
902 | "Skew: -1.870 Prob(JB): 0.00\n",
903 | "Kurtosis: 23.285 Cond. No. 8.77\n",
904 | "==============================================================================\n",
905 | "\n",
906 | "Notes:\n",
907 | "[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n"
908 | ]
909 | }
910 | ],
911 | "source": [
912 | "mod = smf.ols(formula='click ~ treat + gender + pre_click', data=df)\n",
913 | "res = mod.fit()\n",
914 | "print(res.summary())"
915 | ]
916 | },
917 | {
918 | "cell_type": "code",
919 | "execution_count": null,
920 | "metadata": {},
921 | "outputs": [],
922 | "source": []
923 | }
924 | ],
925 | "metadata": {
926 | "kernelspec": {
927 | "display_name": "Python 3",
928 | "language": "python",
929 | "name": "python3"
930 | },
931 | "language_info": {
932 | "codemirror_mode": {
933 | "name": "ipython",
934 | "version": 3
935 | },
936 | "file_extension": ".py",
937 | "mimetype": "text/x-python",
938 | "name": "python",
939 | "nbconvert_exporter": "python",
940 | "pygments_lexer": "ipython3",
941 | "version": "3.8.5"
942 | }
943 | },
944 | "nbformat": 4,
945 | "nbformat_minor": 4
946 | }
947 |
--------------------------------------------------------------------------------
/Class Exercises/Readme:
--------------------------------------------------------------------------------
1 | These are the class exercises that I have designed to enhance students' understanding of concepts and methods in A/B testing. Most of them are in Python.
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Teaching & Learning: Digital Experimentation & A/B Testing in Product Management
2 |
3 | These course materials were initially designed for teaching the Masters of Science in Business Analytics and Marketing program since 2021, at HKU Business School, focusing on the principles and practices of A/B testing. I aim to extend their usefulness to a wider audience, encompassing both learners and educators in the field of A/B testing. The materials include both lecture notes and class exercises in Python, which can serve as a foundation for developing assignments. The course has been meticulously developed from the ground up, ensuring that all content is original. Notably, the primary source of information for this course is my practical experience and research in the field of A/B testing. Additionally, I incorporate insights and some materials from 'Kohavi et al. (2020)'. My practical experience mainly stems from my consultancy and research collaborations with the WeChat A/B testing team at Tencent, China. In addition, I welcome any input related to teaching and learning A/B tests. Understanding this knowledge will benefit practitioners by enabling them to use data for making decisions more scientifically.
4 |
5 | Reference:
6 | Kohavi, Ron, Diane Tang, and Ya Xu. Trustworthy online controlled experiments: A practical guide to a/b testing. Cambridge University Press, 2020.
7 |
8 | **Course Instructor**: [Shan Huang](https://www.shanhhuang.com/), an assistant professor in Marketing at HKU Business School. Email: shanhh@hku.hk
9 |
10 | **Course TA**: Chen Wang, who is a PhD student at HKU Business School. Email: annacwang@connect.hku.hk,
11 |
12 | **Course Description**:
13 |
14 | The newly emerging capability to rapidly deploy and iterate online controlled experiments to assist decision-making in organizations is one of the most significant innovations in today’s technology industry. As more and more social interactions, decisions, opinions, and transactions are mediated by online platforms, digital experiments are becoming increasingly crucial for firms to understand their user behaviors and make product decisions. This course will cover the most cutting-edge digital experimentation methods used in the daily operations at large technology firms. We will also share the key lessons and pitfalls encountered in practice. Topics include the statistics behind experiments, experimental design, methods of analyzing experiments, A/B testing platforms and culture in organizations, recent developments in digital experimentation, and observational causal studies. Students will also learn how to conduct and analyze online experiments using programming languages, such as python, and Large Language Models.
15 |
16 | **Course Roadmap**:
17 |
18 | 1. A comprehensive overview of AB testing
19 |
20 | 2. Statistics behind A/B testing
21 | * Statistical tests (t, z, chi-square)
22 | * Confidence intervals
23 | * Type I error & Multiple Testing
24 | * Type II Error & Power Analysis
25 | * Regression
26 |
27 | 3. Internal & External Validity
28 | * SUTVA (network interferences)
29 | * Survivorship bias
30 | * Sanity Checks (SRM, Randomisation checks, A/A tests)
31 | * Heterogeneous Treatment Effects (HTE)
32 |
33 | 4. Improve Sensitivity
34 | * Ratio metrics (e.g., lift etc.)
35 | * Increase N (pooled control group, split sample)
36 | * Increase effect size (Triggering Experiments)
37 | * Reduce variance (transform metrics and interleaving design, paried design)
38 | * Stratification (post and at assignment, block design)
39 | * Regression with controls, CUPED
40 |
41 |
42 | 5. Observational Causal Studies
43 | * Interrupted time series (ITS)
44 | * Regression discontinuity design (RDD)
45 | * Difference-in-Difference (DID)
46 | * Propensity score matching (PSM)
47 |
48 |
--------------------------------------------------------------------------------
/Slides/Guest_Lecture_KennyXie.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Slides/Guest_Lecture_KennyXie.pdf
--------------------------------------------------------------------------------
/Slides/Guest_Lecture_Tencent.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Slides/Guest_Lecture_Tencent.pdf
--------------------------------------------------------------------------------
/Slides/JasonMa_Tencent_PresentationHK.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Slides/JasonMa_Tencent_PresentationHK.pdf
--------------------------------------------------------------------------------
/Slides/L1 - AB -Testing Overview_SH.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Slides/L1 - AB -Testing Overview_SH.pdf
--------------------------------------------------------------------------------
/Slides/L2-Statistics1_SH.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Slides/L2-Statistics1_SH.pdf
--------------------------------------------------------------------------------
/Slides/L3-Statistics2_SH.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Slides/L3-Statistics2_SH.pdf
--------------------------------------------------------------------------------
/Slides/L4-InternalExternalValidity_SH.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Slides/L4-InternalExternalValidity_SH.pdf
--------------------------------------------------------------------------------
/Slides/L5-Improve_SensitivityI_SH.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Slides/L5-Improve_SensitivityI_SH.pdf
--------------------------------------------------------------------------------
/Slides/L6 - ImproveSensitivity II-SH.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Slides/L6 - ImproveSensitivity II-SH.pdf
--------------------------------------------------------------------------------
/Slides/L7- ObservationalCausal-SH.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shanmit/Course---Digital-Experimentation-Methods-A-B-Testing/f3d4458d60a1001ee71f46fffee2963235a23d03/Slides/L7- ObservationalCausal-SH.pdf
--------------------------------------------------------------------------------
/Slides/Readme.md:
--------------------------------------------------------------------------------
1 | This folder contains presentation slides for all the lectures I've created on A/B testing.
2 |
--------------------------------------------------------------------------------