A/B Test Results Analysis Questions
Learn to analyze results from A/B tests and experiments. Understand key statistics: sample size, statistical significance, confidence intervals, and p-values at a practical level (not deep theory). Practice interpreting test results: 'Is this difference real or just noise?' Learn common mistakes: stopping tests early, p-hacking, and running too many tests simultaneously.
EasyTechnical
76 practiced
Implement in Python a function that takes successes and sample sizes for control and treatment and returns the two-sided p-value and a 95% confidence interval for the difference in proportions using the normal approximation. Your function should handle edge cases such as zero counts and return results in a clear numeric format.
Sample Answer
Approach: use the two-proportion z-test (pooled proportion) for the two-sided p-value and the normal-approx 95% CI for the difference p_t - p_c. Handle edge cases (zero counts, n=0) and return clear numeric outputs.Key points:- Uses pooled SE for hypothesis test (correct for testing equality) and unpooled SE for CI (standard practice).- Complexity: O(1) time and O(1) space.Edge cases:- Raises on n=0.- Handles pooled SE = 0 (all successes or all failures).Alternatives: use Fisher's exact test for small counts or Wilson score intervals for better CI coverage with small samples.
python
import math
from typing import Tuple
def two_prop_z_test(success_c: int, n_c: int, success_t: int, n_t: int, alpha: float = 0.05) -> Tuple[float, Tuple[float, float]]:
"""
Returns (p_value_two_sided, (ci_lower, ci_upper)) for difference in proportions (treatment - control)
using normal approximation.
Raises ValueError for non-positive sample sizes.
"""
if n_c <= 0 or n_t <= 0:
raise ValueError("Sample sizes must be > 0.")
# sample proportions
p_c = success_c / n_c
p_t = success_t / n_t
diff = p_t - p_c
# pooled proportion for hypothesis p_t == p_c (used in z for p-value)
pooled = (success_c + success_t) / (n_c + n_t)
se_pooled = math.sqrt(pooled * (1 - pooled) * (1/n_c + 1/n_t))
# handle zero SE (happens when pooled is 0 or 1)
if se_pooled == 0:
# if pooled exactly 0 or 1, then proportions are identical at extremes => p-value 1 if diff==0 else 0
p_value = 1.0 if abs(diff) < 1e-12 else 0.0
else:
z = diff / se_pooled
# two-sided p-value
p_value = 2 * (1 - 0.5*(1 + math.erf(abs(z)/math.sqrt(2))))
# standard error for confidence interval (unpooled)
se_ci = math.sqrt(p_t*(1-p_t)/n_t + p_c*(1-p_c)/n_c)
# z critical for two-sided alpha (approx)
z_crit = abs(math.sqrt(2) * math.erfinv(1 - alpha)) if hasattr(math, "erfinv") else 1.96
# math.erfinv exists in Python 3.8+; fallback to 1.96 for 95%
if 'erfinv' in dir(math):
z_crit = math.sqrt(2) * math.erfinv(1 - alpha)
ci_lower = diff - z_crit * se_ci
ci_upper = diff + z_crit * se_ci
return float(p_value), (float(ci_lower), float(ci_upper))MediumTechnical
84 practiced
Implement in Python a bootstrap routine that computes a 95% confidence interval for the median revenue per user given a vector of per-user revenues. Your function should be efficient for large samples and allow specifying number of bootstrap iterations and random seed.
Sample Answer
To compute a nonparametric 95% CI for the median efficiently, use resampling with an explicit RNG, vectorized index sampling (avoids Python loops), and percentiles of bootstrap medians. Below is a production-ready Python function using numpy that supports large samples, configurable iterations, and a seed.Key points:- Vectorized index sampling avoids Python-level loops and scales to large n and B.- Time: O(B * n) dominated by building samples and computing medians. Space: O(B * n) if storing all samples; if memory is tight, compute medians in batches to reduce peak memory to O(n).- Edge cases: handle NaNs, empty input, small n (bootstrap still valid but CI may be wide). For better accuracy with small samples or skewed distributions consider BCa bootstrap or increased B.- Alternatives: bootstrap-t (requires standard error estimate per resample), or analytic asymptotic CIs based on sample median and density estimate.
python
import numpy as np
def bootstrap_median_ci(revenues, n_boot=10000, ci=95, seed=None):
"""
Compute a bootstrap confidence interval for the median.
revenues: 1D array-like of per-user revenues
n_boot: number of bootstrap iterations
ci: percentile CI width (e.g., 95)
seed: int or None for reproducibility
Returns: (median_point_estimate, lower_bound, upper_bound)
"""
x = np.asarray(revenues)
if x.ndim != 1:
raise ValueError("revenues must be a 1D array-like")
x = x[~np.isnan(x)] # drop NaNs
n = x.size
if n == 0:
raise ValueError("no valid observations")
rng = np.random.default_rng(seed)
# sample indices in a (n_boot, n) matrix efficiently
idx = rng.integers(0, n, size=(n_boot, n))
samples = x[idx] # shape (n_boot, n)
medians = np.median(samples, axis=1)
lower_p = (100 - ci) / 2
upper_p = 100 - lower_p
lo, hi = np.percentile(medians, [lower_p, upper_p])
return np.median(x), lo, hiHardSystem Design
82 practiced
Design the data analysis pipeline to safely run thousands of concurrent experiments prioritized by product teams. Address randomization, traffic allocation, experiment metadata, metric computation, monitoring for SRM and instrumentation issues, and safe retirement of experiments.
Sample Answer
Requirements & constraints:- Run thousands of concurrent experiments across product teams with independent traffic allocation, stable randomization, low-latency metric computation, robust monitoring (SRM, instrumentation), and safe retirement.- Non-functional: scale to 10M+ daily users, <1% experiment-induced harm, support both online/nearline analysis, reproducible assignments.High-level architecture:- Assignment service + feature-flagging (real-time decisioning)- Event collection bus (Kafka)- Stream processing (Flink / Spark Structured Streaming) for real-time metrics & checks- Batch ETL (Spark) for heavy/backfill metrics- Metrics store / OLAP (ClickHouse or Pinot) + aggregated metrics DB- Experiment metadata service (Postgres + versioned Git-backed configs)- Monitoring & alerting (Prometheus/Grafana, ML anomaly detectors)- Jobs/orchestrator (Airflow / Dagster)Core design details1) Randomization & traffic allocation- Use deterministic, cryptographic hash bucketing: bucket = H(user_id || experiment_id || salt) mod N. This ensures stable assignment across services and seed rotation.- Support hierarchical bucketing (user/device/session) and identity stitching policies.- Allocation metadata: store target allocation (e.g., 30% treatment, 70% control), start/ramp schedule, guardrail metrics, and priority/owner.- Early-override: allow targeting rules and mutual-exclusion groups to prevent overlapping feature conflicts.2) Experiment metadata- Schema: experiment_id, owners, hypothesis, start/end, allocation, status (draft/running/ramping/paused/retired), randomization_salt, instrumentation_checklist, metrics & statistical model definitions, priority.- Version & audit trail: every change creates an immutable revision. CI validates configs (e.g., overlapping allocations).- API + UI for discovery and RBAC.3) Metric computation- Events emitted with assignment metadata (experiment_id, bucket, variant, timestamp). If not possible, join via bucketing at ingestion.- Real-time aggregation: stream jobs compute per-variant aggregates and send to OLAP and alerting. Use windowing and approximate algorithms for cardinality/heavy hitters.- Batch recomputation: nightly backfill performing canonical joins (user state) to ensure reproducibility; store canonical snapshots for reproducibility.- Metric definitions centralized (SQL or DSL) with test harness. Support proportions, means, quantiles, ratios; compute variance via delta-method or bootstrap where needed.- Multiple analysis modes: frequentist (t-tests, chi-square) and sequential-aware (alpha-spending, Bayesian credible intervals). Track peeking policies.4) SRM & instrumentation monitoring- SRM: automatic sample-ratio-mismatch checks using chi-square or binomial tests per experiment and per identity segment. Compute expected vs observed counts; alert if p < threshold after multiple-testing correction (Benjamini-Hochberg).- Instrumentation checks: sentinel metrics (event arrival rate, schema drift, missing fields). Use anomaly detection (EWMA, STL, ML) to detect drops/spikes and compare treatment/control parity on non-target metrics.- Health dashboard: per-experiment health score (SRM, event coverage, variance inflation, data lag). Integrate automated pauses for critical failures.5) Safe retirement & lifecycle- Retirement workflow: ramp-down -> hold-out validation window -> canonical backfill -> analysis signoff -> retire. Enforce retention period for data & audit.- Automatic rollback triggers: if guardrail metrics cross thresholds or severe SRM/instrumentation failures.- Post-mortem artifacts: final analysis notebook, reproducible query IDs, and archived experiment config.Scalability & performance- Use stateless assignment service + CDN edge bucketing where low-latency required.- Kafka partitions by user shard; stream jobs scale horizontally. OLAP engine tuned for aggregated rollups (hourly/daily) to reduce cardinality.- Cost trade-off: more frequent canonical recompute increases correctness but costs more; use tiered approach (real-time approximate + nightly exact).Trade-offs & considerations- Deterministic hashing avoids storage of assignments but requires stable salt management.- Online metrics are faster for alerts; nightly recompute for final inference ensures correctness.- Multiple-testing: with thousands of experiments, control false discovery via FDR procedures and conservative thresholds.- Privacy & compliance: PII handling, consent gating, and differential privacy options for sensitive metrics.Example checks and formulas- SRM chi-square: X2 = sum((obs_i - exp_i)^2 / exp_i); df = k-1.- For proportions, use pooled z-test or Wilson intervals; for sequential testing use alpha-spending (O’Brien-Fleming) or Bayesian posterior monitoring.This pipeline balances scalability, statistical rigor, and operational safety: deterministic bucketing for reproducible randomization, centralized metadata/versioning for traceability, streaming + batch metric computation for fast alerts and accurate final analysis, automated SRM/instrumentation monitoring with enforced safety gates, and a controlled retirement workflow to avoid silent regressions.
HardTechnical
89 practiced
Explain regression to the mean and how it can bias interpretations when teams chase top-performing variations or respond to early spikes. Provide experimental design and analysis practices to avoid being misled by regression to the mean.
Sample Answer
Regression to the mean: when you select units because they had an extreme measurement (very high/low), their subsequent measurements tend to be closer to the population average simply because of random fluctuation (noise), not because of a real change. If a team “chases” a top-performing variation seen early in an A/B test or reacts to a sales spike, they risk attributing natural reversion to the mean to their intervention.Why this biases decisions- Selection on extremes inflates apparent effect size: extreme winners are partially extreme due to noise; the next observation drops, producing a false impression of deterioration when you change course.- Early stopping or responding to spikes amplifies noise-driven mistakes (Type M and S errors).Practices to avoid being misled1. Randomized control and concurrent comparison: always compare to a randomized control group running at the same time; this isolates treatment effect from mean reversion.2. Pre-specify analysis plan and sample size: avoid peeking and decisions based on transient extremes.3. Use sufficient sample sizes and run tests long enough to average out short-term noise and seasonality.4. Holdout and replication: replicate winners in fresh experiments or use holdout periods before rolling out broadly.5. Use shrinkage/regularization or Bayesian hierarchical models: estimate treatment effects with partial pooling to pull extreme estimates toward the population mean (reduces over-estimation of winners).6. Adjust for regression analytically: when selecting top-k, correct expected winner bias via “winner’s curse” adjustments or cross-validation (estimate effect on data not used for selection).7. Sequential testing corrections: apply methods (alpha-spending, Bayes) if you must look at results repeatedly.8. Monitor control trends and decompose variability: separate signal from noise by modeling time-series components (trend, seasonality, autocorrelation) and measurement error.9. Use uplift/heterogeneous treatment effect estimation carefully: validate discovered segments on held-out data before acting.Concrete example: if you pick the variant with the largest uplift after first week, its true expected uplift is lower than observed; repeat the experiment or use a Bayesian posterior to temper the initial estimate before rollout.Bottom line: treat early extremes as suggestive hypotheses, not definitive winners; rely on randomized comparisons, adequate sample size, replication, and shrinkage/Bayesian inference to avoid being fooled by regression to the mean.
HardTechnical
69 practiced
You run an experiment that increases click-through-rate (CTR) by 8% but reduces average order value (AOV) by 2%. Outline analytical methods to combine these signals into a decision: back-of-envelope expected revenue per user calculation, funnel/probability modeling, and approaches for multi-objective optimization or policy evaluation.
Sample Answer
Start with a clear objective: maximize expected revenue per user (RPU) while respecting risk/other KPIs. I’ll give concrete calculations, funnel/probability modeling, and multi-objective/policy-eval approaches.1) Back-of-envelope RPU- Baseline metrics: CTR0, AOV0, conv_rate0 (click→purchase), other monetization per visit M0.- Experiment changes: CTR↑8% (CTR1 = 1.08·CTR0), AOV↓2% (AOV1 = 0.98·AOV0).- RPU ≈ visit_rate * CTR * conv_rate * AOV (or simply CTR*conv_rate*AOV if per visit).- Example: if conv_rate0=0.10 and CTR0=0.20, AOV0=$50: RPU0 = 0.20*0.10*$50 = $1.00 RPU1 = 1.08*0.20 * 0.10 * 0.98*$50 = $1.0584 → +5.84% revenue per user.- Compute delta and use delta method or bootstrap to get CI and p-value for RPU difference (propagate uncertainty from CTR, conv_rate, AOV).2) Funnel / probability modeling- Decompose into stages: Impression → Click (p_click) → Add-to-cart (p_atc|click) → Purchase (p_buy|atc) → Spend (AOV|buy).- Fit logistic/GLM or hierarchical Bayesian models for each conditional probability to estimate how treatment affects stages (and interactions).- Use joint simulation: sample parameter posteriors and propagate through funnel to get posterior of RPU and distribution of long-tail metrics (LTV).- Test heterogeneous effects: regression with interactions (treatment × segment features) or causal forests / uplift models to find segments where AOV drop is/ isn’t offset by CTR gains.3) Multi-objective optimization & policy evaluation- Scalarization: define utility U = α·Revenue + β·Retention + γ·NPS (choose weights from stakeholders or economic values). Optimize for U; perform sensitivity analysis across weights.- Pareto frontier: compute trade-off curve between CTR/AOV (or revenue vs. another KPI) to visualize non-dominated policies.- Cost-sensitive loss: train models to directly predict RPU uplift (loss = negative revenue), or use doubly-robust uplift estimation to learn treatment policy.- Online policy evaluation: run offline policy evaluation (IPW, doubly robust) then A/B or multi-armed bandit: - Contextual bandits (e.g., Thompson Sampling / UCB) to allocate traffic adaptively and maximize cumulative revenue while learning. - Constrain exploration to keep losses bounded (constrained bandits or safe policy learning).- Business calibration: convert per-user RPU uplift to aggregate financials (expected incremental revenue = uplift * monthly active users * retention multiplier), include costs (infrastructure, UX changes).Practical checklist before decision:- Statistical significance and power for RPU (use bootstrap/ Bayesian posteriors)- Heterogeneity analysis (segments where AOV drop is large)- Sensitivity to conversion assumptions (simulate conv_rate changes)- Risk tolerance and long-term impact (e.g., lower AOV could imply different customer cohort quality)- Recommend: if RPU uplift is positive and CI excludes practical loss, rollout; else run targeted rollout via contextual policy to segments with positive predicted uplift while continuing data collection.
Unlock Full Question Bank
Get access to hundreds of A/B Test Results Analysis interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.