Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
📐 Week 5 – Statistics और Probability  ·  दिन 31

दिन 31: Correlation और A/B Testing

⏱ 2.5 hours📶 Intermediate → Project🎯 100% self-study
दिन 31 / 60

✅ आज आप सीखेंगे

  • Pearson vs Spearman correlation
  • Correlation, causation क्यों नहीं
  • A/B test और उसका sample size design करना
  • Analysis: z-test, lift का CI, segments
  • Launch का फ़ैसला करना और समझाना

🏢 असली दुनिया में

BazaarKart की design team ने पुराने तीन-step checkout (A) की जगह नया one-page checkout (B) बनाया। 4,000 visitors को random बाँटा गया। B ने 13.6%, A ने 10.7% convert किया। क्या company को सभी 50 lakh monthly visitors के लिए बदलना चाहिए? Flipkart, Swiggy और हर गंभीर product team A/B testing से ही तय करती है।

Correlation

Python
import pandas as pd
h = pd.read_csv("house_prices.csv")
cols = ["area_sqft", "bedrooms", "age_years", "metro_km", "price_lakh"]
print(h[cols].corr(method="pearson").round(2)["price_lakh"])
print(h[cols].corr(method="spearman").round(2)["price_lakh"])
area_sqft 0.83 bedrooms 0.68 age_years -0.15 metro_km -0.20 price_lakh 1.00 Name: price_lakh, dtype: float64 area_sqft 0.81 bedrooms 0.65 age_years -0.16 metro_km -0.16 price_lakh 1.00 Name: price_lakh, dtype: float64

Pearson r

  • सीधी-line वाला रिश्ता मापता है
  • Outliers से प्रभावित
  • लगभग linear numeric data के लिए

Spearman ρ

  • Ranks लेता है – कोई भी लगातार बढ़त/घटत
  • Outliers से कम प्रभावित
  • Skewed data या ranks/ratings के लिए
Python
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(1)
x = rng.uniform(-3, 3, 200)
cases = [("r ≈ 0.9", x, 2 * x + rng.normal(0, 1.4, 200)), ("r ≈ −0.6", x, -x + rng.normal(0, 2, 200)),
         ("r ≈ 0 but strong pattern!", x, x ** 2 + rng.normal(0, 0.6, 200))]
fig, ax = plt.subplots(1, 3, figsize=(12, 3.3))
for a, (t, xx, yy) in zip(ax, cases):
    a.scatter(xx, yy, s=8, color="#4f46e5", alpha=0.6); a.set_title(f"{t}  (r={np.corrcoef(xx, yy)[0, 1]:.2f})")
plt.tight_layout(); plt.show()
तीन scatter plots: मज़बूत positive, मध्यम negative और शून्य correlation वाला U-आकार
हमेशा plot करें – r = 0 का मतलब “कोई रिश्ता नहीं” नहीं, बस “सीधी-line का रिश्ता नहीं”।

Correlation, causation नहीं है

🍦
साझा कारणIce-cream sales और डूबने की घटनाएँ गर्मी में बढ़ती हैं। दोनों की वजह गर्मी।
🔄
उल्टा कारणLoyal customers ज़्यादा support लेते हैं – support अपने-आप loyalty नहीं बनाता।
🎲
संयोगकाफ़ी columns खोजें तो कुछ न कुछ संयोग से correlate करेगा।
🧪
हल: experimentRandom assignment सारे छिपे कारण तोड़ देता है – यही A/B testing है।
Experiments क्यों चाहिए
Python
import pandas as pd
w = pd.read_csv("delhi_weather.csv")
r = w["avg_temp_c"].corr(w["aqi"])
print(f"Temperature vs AQI: r = {r:.2f}")
print("Cold does not create pollution directly: winter brings stubble burning, low wind and")
print("temperature inversion. Temperature is a marker of the season, not the cause.")
Temperature vs AQI: r = -0.91 Cold does not create pollution directly: winter brings stubble burning, low wind and temperature inversion. Temperature is a marker of the season, not the cause.

A/B test: पहले design

  1. 1एक metric: checkout conversion
  2. 2H₀: pB = pA, H₁: pB ≠ pA
  3. 3फ़ायदेमंद न्यूनतम lift: +2 points
  4. 4हर group का sample size
  5. 5Random 50/50 split, पूरे हफ़्ते चलाएँ
  6. 6आख़िर में एक बार analyse
Data देखने से पहले सब तय करें
Python
from statsmodels.stats.power import NormalIndPower
from statsmodels.stats.proportion import proportion_effectsize
effect = proportion_effectsize(0.13, 0.11)                 # detect 11% → 13%
n = NormalIndPower().solve_power(effect_size=effect, alpha=0.05, power=0.8, ratio=1)
print(f"Need about {n:,.0f} visitors per group ({2 * n:,.0f} total) for 80% power")
Need about 4,138 visitors per group (8,275 total) for 80% power
🧠 क्या plan किया vs क्या है

हमारे पास हर group में ~2,000 हैं – +2 points पर 80% power के लिए ज़रूरी ~4,100 का लगभग आधा। असली पर छोटा असर चूक सकता है, इसलिए result significant न हो तो “कोई असर नहीं” कहने की जगह test आगे बढ़ाएँगे।

Experiment का analysis

Python
import pandas as pd
ab = pd.read_csv("ab_test.csv")
print(ab.head(3))
summary = ab.groupby("group")["converted"].agg(visitors="count", conversions="sum", rate="mean")
summary["rate_%"] = (summary["rate"] * 100).round(2)
print(summary.drop(columns="rate"))
print("Device mix by group (randomisation check):")
print((pd.crosstab(ab["group"], ab["device"], normalize="index") * 100).round(1))
user_id group device converted 0 1 A Mobile 0 1 2 B Mobile 0 2 3 A Mobile 0 visitors conversions rate_% group A 1969 211 10.72 B 2031 276 13.59 Device mix by group (randomisation check): device Desktop Mobile group A 31.4 68.6 B 30.4 69.6
Python
import numpy as np
import pandas as pd
from statsmodels.stats.proportion import proportions_ztest, confint_proportions_2indep
ab = pd.read_csv("ab_test.csv")
g = ab.groupby("group")["converted"].agg(["sum", "count"])
z, p = proportions_ztest(count=[g.loc["B", "sum"], g.loc["A", "sum"]], nobs=[g.loc["B", "count"], g.loc["A", "count"]])
pA, pB = g["sum"] / g["count"]
lo, hi = confint_proportions_2indep(g.loc["B", "sum"], g.loc["B", "count"], g.loc["A", "sum"], g.loc["A", "count"])
print(f"A {pA:.2%} → B {pB:.2%} | absolute lift {pB - pA:+.2%} | relative lift {(pB / pA - 1):+.1%}")
print(f"z = {z:.2f}, p = {p:.4f}")
print(f"95% CI for the lift: {lo:+.2%} to {hi:+.2%}")
A 10.72% → B 13.59% | absolute lift +2.87% | relative lift +26.8% z = 2.78, p = 0.0055 95% CI for the lift: +0.85% to +4.90%
Python
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
ab = pd.read_csv("ab_test.csv")
r = ab.groupby(["device", "group"])["converted"].agg(["mean", "count"]).reset_index()
r["se"] = np.sqrt(r["mean"] * (1 - r["mean"]) / r["count"])
fig, ax = plt.subplots(figsize=(8, 3.8))
for i, (grp, c) in enumerate([("A", "#94a3b8"), ("B", "#4f46e5")]):
    d = r[r["group"] == grp]
    ax.bar(np.arange(len(d)) + (i - 0.5) * 0.38, d["mean"] * 100, 0.38, yerr=1.96 * d["se"] * 100, capsize=4, color=c, label=grp)
ax.set_xticks(range(2), r["device"].unique()); ax.set_ylabel("conversion %"); ax.legend(title="checkout")
ax.set_title("New checkout B wins on both devices (95% CI bars)"); plt.show()
print(r.assign(rate_pct=(r["mean"] * 100).round(2))[["device", "group", "count", "rate_pct"]].to_string(index=False))
device group count rate_pct Desktop A 619 11.63 Desktop B 617 14.75 Mobile A 1350 10.30 Mobile B 1414 13.08
Device और checkout version के हिसाब से conversion rate, error bars के साथ
Segments जाँचें ताकि B किसी ज़रूरी group को नुकसान न पहुँचाए।

फ़ैसला और business impact

Python
import pandas as pd
ab = pd.read_csv("ab_test.csv")
rate = ab.groupby("group")["converted"].mean()
visitors, aov = 5_000_000, 1200                      # monthly visitors, average order value ₹
extra_orders = visitors * (rate["B"] - rate["A"])
print(f"Extra orders per month ≈ {extra_orders:,.0f}")
print(f"Extra revenue per month ≈ ₹{extra_orders * aov / 1e7:.1f} crore (point estimate)")
Extra orders per month ≈ 143,663 Extra revenue per month ≈ ₹17.2 crore (point estimate)
💼 एक-slide का जवाब

“नए checkout ने conversion 10.7% से 13.6% किया (p ≈ 0.006; 95% CI लगभग +0.9 से +4.9 points), mobile और desktop दोनों पर। 100% पर launch करें। अनुमानित असर: महीने में लगभग 1.4 lakh ज़्यादा orders। 2 हफ़्ते monitoring जारी रखें।”

⚠️ A/B testing के जाल

Peeking: p < 0.05 होते ही test रोकना झूठी जीत बढ़ाता है। बहुत metrics: कोई एक संयोग से जीतेगा। Novelty effect: users शुरू में नई चीज़ पर ज़्यादा click करते हैं। असमान split: randomisation जाँचें।

🏅 आज के Job Skills

✔ Correlation मापना और समझना✔ Correlation vs causation समझाना✔ Power analysis के साथ A/B test design✔ A/B results analyse करके फ़ैसला सुझाना

Practice tasks

🏋️ Practice – ख़ुद करें

Task 1: tenure_months और total_charges का Pearson और Spearman correlation निकालें। ये क़रीब क्यों हैं?
Solution देखें
Python
import pandas as pd
t = pd.read_csv("telecom_churn.csv").dropna()
print(round(t["tenure_months"].corr(t["total_charges"]), 3), round(t["tenure_months"].corr(t["total_charges"], method="spearman"), 3))
0.888 0.914
Task 2: सिर्फ़ Mobile users के लिए A/B z-test चलाएँ। क्या result अभी भी significant है?
Solution देखें
Python
import pandas as pd
from statsmodels.stats.proportion import proportions_ztest
ab = pd.read_csv("ab_test.csv"); m = ab[ab["device"] == "Mobile"]
g = m.groupby("group")["converted"].agg(["sum", "count"])
z, p = proportions_ztest(g["sum"].values[::-1], g["count"].values[::-1])
print(g); print(f"z = {z:.2f}, p = {p:.4f}")
sum count group A 139 1350 B 185 1414 z = 2.28, p = 0.0228
Task 3: 11% से 12% का lift पकड़ने के लिए हर group में कितने visitors चाहिए?
Solution देखें
Python
from statsmodels.stats.power import NormalIndPower
from statsmodels.stats.proportion import proportion_effectsize
print(round(NormalIndPower().solve_power(proportion_effectsize(0.12, 0.11), alpha=0.05, power=0.8)))
15969

Quick quiz

🧠 Quick Quiz – ख़ुद को जाँचें

1. r = −0.8 मतलब…
−1 के पास = मज़बूत उल्टी चाल।
2. Correlation नहीं कर पाता, A/B testing causation कैसे साबित करता है?
Groups में फ़र्क सिर्फ़ हमारे बदलाव का।
3. p < 0.05 होते ही test रोकना कहलाता है…
यह false positives बढ़ाता है।
4. Sample size कब तय होता है?
Power analysis।
5. दो conversion rates की तुलना कौन सा test करता है?
statsmodels में proportions_ztest।

Interview corner

💼 Interview Corner

A/B test कैसे चलाएँगे, बताइए।

एक मुख्य metric और hypothesis तय करें, minimum detectable effect तय करें, power analysis से sample size निकालें, users को random 50/50 बाँटें, peeking के बिना पूरे हफ़्ते चलाएँ, randomisation जाँचें, z-test और lift का CI निकालें, ज़रूरी segments और guardrail metrics देखें, फिर अनुमानित असर के साथ launch सुझाएँ।

आपका test p = 0.08 दिखाता है। क्या करेंगे?

इसे न जीत कहें न हार। Estimate और CI बताएँ, देखें कि test planned sample size तक पहुँचा या नहीं; कम power हो तो आगे बढ़ाएँ; फ़ैसले से पहले ग़लत होने की कीमत सोचें।

सारांश

  • Linear के लिए Pearson, ranks/skewed के लिए Spearman; हमेशा plot करें।
  • Correlation ≠ causation; random experiments कारण साबित करते हैं।
  • A/B: पहले metric, MDE और sample size तय करें; कभी peek न करें।
  • Lift, CI, p-value, segments और rupee impact बताएँ।
  • Week 5 पूरा – अब आप statistician की तरह सोचते हैं!
➡️ आगे

Week 6: SQL। Day 32: SQLite के साथ SQL basics – SELECT, WHERE, ORDER BY सीधे Python के अंदर।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

Guardrail metric क्या है?
ऐसा metric जो मुख्य metric सुधारते समय बिगड़ना नहीं चाहिए – जैसे नया checkout test करते समय refund rate या page load time।
क्या बहुत कम users में A/B test कर सकते हैं?
सिर्फ़ बड़े असर पकड़ में आएँगे। छोटी sites पर बड़े बदलाव test करें, ज़्यादा समय चलाएँ, या अनिश्चितता के लिए Bayesian methods लें।
← Data Science (60 Days)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

अगला topicदिन 32: SQLite के साथ SQL Basics आपकी प्रगति: 31 / 60 (52%) · Lesson 32 / 60 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें