Skip to main content

Kotlin Notebook

Run this tutorial as a Kotlin Notebook with interactive Kandy charts — all code cells, DataFrame outputs, and visualizations included.
This tutorial walks through two real-world A/B test datasets end-to-end:
  • E-commerce Landing Page (Kaggle) — ~294K users randomly assigned to old vs new checkout page, binary outcome (converted / not)
  • Marketing Campaign (Kaggle) — daily campaign metrics (spend, clicks, impressions, purchases) for control vs test campaign
Structure:
  • Act 1 — Binary metric: conversion rate (proportion z-test, chi-squared, Bayesian)
  • Act 2 — Rate metrics: CTR, purchase rate (paired t-test, Wilcoxon, effect sizes, correlation)
This tutorial uses Kotlin DataFrame for data loading and Kandy for visualization. These are Kotlin Notebook dependencies — the kstats statistical functions work in any Kotlin environment.

Quick Reference: Which Test to Use?


Act 1: Binary Metric — Conversion Rate

1. Data Loading and Cleaning

Dataset: ~294K users randomly assigned to control (old page) or treatment (new page), binary outcome (converted / not).
The dataset has 294,478 rows and 5 columns with an overall conversion rate of ~12%.
Conversion rates by group

2. SRM Check — Sample Ratio Mismatch

Before any hypothesis test, verify that randomization worked correctly. If the split ratio deviates from 50/50 more than chance would allow, the experiment is compromised — all downstream results are untrustworthy. is checked with a one-sample proportion z-test: is the observed split consistent with a 50/50 ratio?
p >> 0.05 — no SRM detected. The 50/50 split is intact and randomization looks correct.

3. Power Analysis — Pre-Experiment Planning

should happen before data collection to determine the required sample size. We ask: “How many users do we need to detect a 1 percentage point lift from a 12% baseline with 80% power at alpha = 0.05?” This ensures the experiment is neither underpowered (missing real effects) nor wasteful (running longer than necessary).
Required sample size vs power With ~145K users per group, the experiment is massively overpowered for a 1 pp lift — power is effectively 100%. The is Cohen’s h = 0.0104, meaning the experiment can detect extremely small differences.

4. Primary Test — Two-Sample Proportion z-Test

The core question: is the conversion rate different between control and treatment? For comparing two binomial proportions on large samples, the proportion z-test is the standard method. It compares the observed difference against sampling variability under the null hypothesis of equal rates.
p > 0.05 — we cannot reject the null hypothesis. The new page does not significantly change conversion rate. The 95% for the difference includes zero, consistent with no effect.

One-sided check

The company only cares if the new page is better. A one-sided test has more power to detect an improvement, but p ≈ 0.905 here strongly suggests the treatment is actually worse (or at best equal).

5. Effect Size — Cohen’s h

A answers “is there a difference?”. answers “how big is the difference?” With N=290K even tiny differences can become “significant”. Cohen’s h puts the difference on a standardized scale independent of sample size.
Cohen's h by conversion lift from 12% baseline The chart shows Cohen’s h for various conversion lifts from a 12% baseline. The red line marks the “small effect” threshold (h = 0.2). A 1 pp lift barely registers; you need at least a 3-5 pp lift to reach a small effect.

6. Confidence Intervals — Wilson Score

The Wald CI from the z-test can misbehave near 0 or 1. The Wilson score interval is recommended for per-group conversion rate estimates, especially with small samples.
The intervals overlap substantially, consistent with no meaningful difference.

7. Robustness Check — Chi-Squared Test

The same hypothesis can be tested with a 2x2 contingency table. For large N the chi-squared statistic equals z² — a useful sanity check.
Both tests agree: no significant difference. z² ≈ χ² confirms internal consistency.

8. Bayesian A/B Testing

The frequentist approach gives a binary answer: reject or don’t reject. The Bayesian approach answers a more intuitive question: what is the probability that the treatment is better? We use the Beta-Binomial conjugate model:
  • Prior: Beta(1, 1) — uninformative (uniform on [0, 1])
  • Posterior: Beta(1 + successes, 1 + failures) — updated belief after seeing data
  • Decision: Compare posterior distributions via Monte Carlo sampling
Bayesian posterior distributions for control and treatment
The Bayesian approach tells the same story: P(treatment > control) is only ~9.5%. Most organizations require P(B > A) > 95% to ship a change. Frequentist vs Bayesian:
  • Frequentist: “We cannot reject H₀” — binary decision, p-value depends on sample size
  • Bayesian: “There’s a ~9.5% chance the new page is better” — direct probability statement, more intuitive for stakeholders
Both agree: there is no compelling evidence to launch the new page.
We used a uniform Beta(1,1) prior. With N=145K observations, the prior has virtually no effect on the posterior. For smaller experiments (N < 1000), consider using an informative prior based on historical conversion rates.

Act 2: Continuous Metrics — Marketing Campaign

We now switch to continuous metrics where different statistical tools are needed. Dataset: Marketing Campaign A/B Testing — daily campaign metrics for control vs test campaign over 30 days.

9. Compute Rate Metrics

Why rates, not raw counts? The two groups have very different exposure: treatment received ~30% fewer impressions but ~12% more spend. Comparing raw daily counts would conflate the campaign effect with the exposure difference. Instead, we normalize by daily impressions to get CTR (clicks / impressions) and purchase rate (purchases / impressions). Why paired tests? Since control and test observations are matched by date, a paired t-test (or Wilcoxon signed-rank) removes day-to-day variability, increasing power compared to an independent-samples test.

10. EDA — Paired Differences

Before running hypothesis tests, visualize the data to understand its structure and spot potential issues.
Strip plot with mean ± SE — each dot is one day; the treatment mean is clearly higher, but individual days vary widely.CTR strip plot with mean and standard errorBox plot — the treatment median sits above the control range, with several high-CTR outlier days.CTR boxplot by groupTime series — the treatment (red) consistently exceeds control (blue) day-over-day, supporting a paired test design.CTR time series by group
The treatment group shows higher CTR and purchase rate across most days, with notably more variance. The strip and box plots confirm a clear upward shift in the treatment group.

11. Assumption Checks

For paired tests, we check the differences (treatment minus control per day):
  1. Normality of differences (Shapiro-Wilk) — are the paired differences approximately normal?
  2. Homogeneity of variance (Levene) — reported for completeness, though paired tests do not require it.
Decision tree for paired data:
  • Shapiro-Wilk on differences passes (p > 0.05) → paired t-test is primary
  • Shapiro-Wilk fails → paired t-test is often robust to mild non-normality, but at N ≈ 29 results should be interpreted cautiously. The Wilcoxon signed-rank serves as a sensitivity check — if both tests agree, the conclusion is more trustworthy
  • No need to check equal variances — paired tests work on differences, not separate groups
We report both parametric (paired t-test) and non-parametric (Wilcoxon signed-rank) tests.

12. Hypothesis Tests — Paired t-test and Wilcoxon Signed-Rank

Both parametric and non-parametric tests agree on both metrics: the treatment campaign has significantly higher CTR and purchase rate. This agreement strengthens our confidence despite the non-normal differences.

13. Effect Size — Paired Cohen’s dz

For paired designs, Cohen’s dz = mean(differences) / SD(differences) is the appropriate effect size. It captures how large the within-pair differences are relative to their variability.
Unlike unpaired Cohen’s d (which uses pooled between-group SD), dz directly reflects how consistently one condition outperforms the other across matched pairs. Larger dz values indicate more consistent day-over-day advantages for the treatment group.

14. Multiple Comparison Correction

We tested two metrics: CTR and Purchase Rate. Testing multiple hypotheses inflates the chance of false positives (Type I error). Three correction methods: Use FWER (Bonferroni/Holm) when any false positive is costly (e.g., regulatory). Use FDR (BH) when screening many metrics and can tolerate some false positives.
All p-values remain significant after correction with any method. Raw vs adjusted p-values comparison

15. Metric Correlation — CTR vs Purchase Rate

Are our two test metrics correlated? Bonferroni controls FWER regardless of dependence structure, but when metrics are positively correlated the correction becomes more conservative than necessary.
Scatter plot — each point is one campaign-day; the positive trend confirms that higher-CTR days also see more purchases per impression. CTR vs purchase rate scatter plot Correlation heatmap — Pearson r across all rate and exposure metrics. CTR and purchase rate (r = 0.75) are the strongest pair. Correlation matrix heatmap CTR and purchase rate are strongly correlated (r = 0.75). This means the Bonferroni/Holm corrections are more conservative than necessary — the true FWER is below the nominal alpha. With two correlated metrics, both corrections are acceptable.

Summary

Act 2 methodology note: The marketing campaign groups had very different exposure levels (treatment received ~30% fewer impressions but ~12% more spend). All Act 2 analyses use rate metrics (per impression) to remove this confound, and paired tests matched by date to control for day-level variability.
Caveat on Act 2 power: With only ~29 matched pairs, the study has moderate power (~55% for a medium effect dz ≈ 0.4). The significant results correspond to medium-to-large effects (dz ≈ 0.59-0.75), well above the detectable threshold. Nevertheless, the wide confidence intervals reflect the small sample. Business conclusion: The new landing page does not improve conversion rate — the experiment was well-powered (>99% to detect a 1 pp lift) and both frequentist and Bayesian analyses agree. For the marketing campaign, both CTR and purchase rate are significantly higher in the treatment group after Holm correction for multiple comparisons. However, with only 29 matched days the effect size estimates are imprecise; a longer experiment would narrow the confidence intervals and confirm the magnitude of the improvement.

See Also

A/B Testing How-To

Concise step-by-step guide for running A/B tests with kstats using synthetic data.

Testing Assumptions

Verify normality, variance homogeneity, and distributional fit before applying parametric methods.

Hypothesis Testing Module

Full reference for all hypothesis tests available in kstats.

Correlation Module

Pearson, Spearman, and Kendall correlation with significance tests.
Last modified on April 8, 2026