Skip to content

সমাধান — অধ্যায় ১.৪ · Correlation & Bivariate Exploration

অধ্যায় part-1-descriptive/01-04-correlation-bivariate.md-এর section ৭-এর সব অনুশীলনীর পূর্ণ সমাধান। প্রতিটি সংখ্যাগত ফল NumPy / SciPy দিয়ে যাচাই করা হয়েছে।


Conceptual (ধারণাভিত্তিক)

৭.১ ★ — \(r\) কী ধরে, কী ধরে না

Pearson \(r\) কেবল direction (positive/negative — চিহ্ন থেকে) এবং linear strength (১-এর কতটা কাছে — মান থেকে) ধরে। সে form ধরে না — একটি বাঁকা সম্পর্ককে দুর্বল linear হিসেবে ভুল পড়তে পারে (Anscombe II)। সে outlier-ও আলাদাভাবে ধরে না — বরং একটি outlier তার মানকে নাটকীয়ভাবে টানতে পারে (Anscombe III, IV)। তাই \(r\) কখনো scatterplot-এর বিকল্প নয়; এটি ছবিকে সংখ্যায় সংক্ষেপ করে মাত্র, ছবির সব তথ্য ধরে না।

৭.২ ★ — covariance বনাম correlation-এর ব্যাখ্যাযোগ্যতা

covariance-এর একক হলো (x-এর একক) \(\times\) (y-এর একক) — যেমন উচ্চতা-ওজনের covariance "cm·kg"-এ। ফলে তার মান একক বদলালেই বদলে যায় (m-এ মাপলে ১০০ গুণ ছোট), তাই "বড়" না "ছোট" বলার কোনো সর্বজনীন মাপকাঠি নেই। correlation \(r = \operatorname{cov}/(s_x s_y)\)-এ উপরে-নিচে একক কাটাকাটি হয়ে যায়, ফলে \(r\) একটি বিশুদ্ধ সংখ্যা যার সর্বদা একই সীমা \([-1,1]\) — তাই তার মান সরাসরি ব্যাখ্যাযোগ্য।

৭.৩ ★★ — কম্বল ও অসুস্থতার ভুল causal যুক্তি

এখানে correlation থেকে সরাসরি causation টানা হয়েছে, যা ভুল। কম্বল বিক্রি (\(x\)) ও ঠান্ডাজনিত অসুস্থতা (\(y\)) — দুটোই একটি তৃতীয় confounder $z = $ শীত/ঠান্ডা আবহাওয়া-র ফল: ঠান্ডা পড়লে মানুষ কম্বল কেনে (\(z \to x\)), আবার ঠান্ডায় সর্দি-কাশি বাড়ে (\(z \to y\))। তাই \(x\)\(y\) একসাথে চলে, কিন্তু একটি অন্যটিকে ঘটায় না — কম্বল পোড়ালে অসুস্থতা কমবে না। প্রকৃত কারণ যাচাই করতে হলে আবহাওয়া স্থির রেখে (বা randomized experiment-এ) দেখতে হবে।

৭.৪ ★★ — Anscombe III থেকে outlier বাদ দিলে

Dataset III-এর ১১টি বিন্দুর মধ্যে ১০টি প্রায় নিখুঁত সরলরেখায়, একটি বিন্দু রেখা থেকে অনেক উপরে (outlier)। এই outlier রেখা থেকে দূরে বলে \(r\)-কে ১ থেকে টেনে \(0.816\)-এ নামিয়েছে। সেটি বাদ দিলে বাকি ১০ বিন্দু এতই রৈখিক যে \(r\) প্রায় \(1.0\)-তে বেড়ে যাবে (\(\approx 0.9998\))। শিক্ষা: একটিমাত্র outlier correlation-কে ব্যাপকভাবে নামাতে (বা বাড়াতে) পারে — তাই outlier পরীক্ষা অপরিহার্য।


Computational (গণনাভিত্তিক)

৭.৫ ★ — হাতে cov ও \(r\)

\(x=(2,4,6,8)\), \(y=(1,3,2,4)\), \(n=4\)\(\bar x = \frac{2+4+6+8}{4}=5\), \(\bar y = \frac{1+3+2+4}{4}=2.5\)

\(x_i\) \(y_i\) \(x_i-\bar x\) \(y_i-\bar y\) গুণফল \((x_i-\bar x)^2\) \((y_i-\bar y)^2\)
2 1 \(-3\) \(-1.5\) \(4.5\) \(9\) \(2.25\)
4 3 \(-1\) \(0.5\) \(-0.5\) \(1\) \(0.25\)
6 2 \(1\) \(-0.5\) \(-0.5\) \(1\) \(0.25\)
8 4 \(3\) \(1.5\) \(4.5\) \(9\) \(2.25\)
যোগ \(\mathbf{8}\) \(\mathbf{20}\) \(\mathbf{5}\)

$$ \operatorname{cov}(x,y) = \frac{8}{4-1} = \frac{8}{3} \approx 2.667 . $$ $$ s_x = \sqrt{\tfrac{20}{3}} \approx 2.582, \quad s_y = \sqrt{\tfrac{5}{3}} \approx 1.291, \qquad r = \frac{8/3}{2.582 \times 1.291} = \frac{8}{\sqrt{20}\sqrt{5}} = \frac{8}{10} = 0.80 . $$ (শেষ ধাপে \(n-1\) কাটাকাটি করে সরাসরি যোগফল ব্যবহার সহজ: \(r = \frac{\sum \text{prod}}{\sqrt{\sum xx}\sqrt{\sum yy}} = \frac{8}{\sqrt{100}} = 0.80\)।) NumPy-তে np.corrcoef দেয় ঠিক \(0.8000\)

৭.৬ ★★ — নিখুঁত নিম্নমুখী রেখা

\(y = 12 - 2x\) একটি নিখুঁত সরলরেখা যার slope ঋণাত্মক (\(a=-2<0\))। যেহেতু সব বিন্দু ঠিক একটি নিম্নমুখী রেখায়, অনুমান \(r = -1\)। যাচাই: deviation \(y_i - \bar y = -2(x_i - \bar x)\), তাই $$ r = \frac{\sum (x_i-\bar x)\cdot(-2)(x_i-\bar x)}{\sqrt{\sum(x_i-\bar x)^2}\,\sqrt{\sum 4(x_i-\bar x)^2}} = \frac{-2\sum(x_i-\bar x)^2}{2\sum(x_i-\bar x)^2} = -1 . $$ NumPy: np.corrcoef([1,2,3,4,5],[10,8,6,4,2])[0,1] \(= -1.0\) (floating-point-এ \(-0.99999\ldots\))।

৭.৭ ★★ — outlier-এ Pearson বনাম Spearman

মূল data \(x=y=(1,2,3,4,5)\) নিখুঁত বাড়তি রেখা, তাই আগে Pearson \(=1.0\) এবং Spearman \(=1.0\)

এবার \(y=(1,2,3,4,50)\) (শেষ মান \(5\to50\)): - Pearson শেষ বিন্দুর বিশাল deviation-এ টানে — মান নেমে \(\approx 0.743\) (অনেক বদল)। - Spearman কেবল rank দেখে: \(50\) এখনো সবচেয়ে বড় মান, তাই rank অপরিবর্তিত \((1,2,3,4,5)\)Spearman \(=1.0\)-ই থাকে (কোনো বদল নেই)।

তাই Pearson বেশি বদলায়, কারণ সে প্রকৃত মান (ও তার বিশাল deviation) ব্যবহার করে; Spearman rank-ভিত্তিক বলে চরম মানে অনেক বেশি robust। যাচাই: Pearson \(0.7433\), Spearman \(1.0\)


Proof-based (প্রমাণভিত্তিক)

৭.৮ ★★ — \(\operatorname{cov}(x,x)=s_x^2\) এবং \(r_{xx}=1\)

covariance-এর সংজ্ঞায় \(y=x\) (তাই \(\bar y = \bar x\)) বসাই: $$ \operatorname{cov}(x,x) = \frac{1}{n-1}\sum_{i=1}^n (x_i-\bar x)(x_i-\bar x) = \frac{1}{n-1}\sum_{i=1}^n (x_i-\bar x)^2 = s_x^2 . $$ অর্থাৎ variance হলো নিজের সাথে নিজের covariance। এবার correlation-এর সূত্রে \(y=x\): $$ r_{xx} = \frac{\operatorname{cov}(x,x)}{s_x \, s_x} = \frac{s_x^2}{s_x^2} = 1 \qquad (s_x \ne 0). \qquad \blacksquare $$ এজন্যই correlation matrix-এর কর্ণ সর্বদা \(1\) — প্রতিটি variable নিজের সাথে নিখুঁতভাবে correlated।

৭.৯ ★★★ — নিখুঁত রেখায় \(r=\pm 1\)

ধরুন \(y_i = a x_i + b\) (\(a \ne 0\))। তাহলে \(\bar y = a\bar x + b\), সুতরাং $$ y_i - \bar y = (a x_i + b) - (a\bar x + b) = a(x_i - \bar x). $$ এটি \(r\)-এর সূত্রে বসাই। Numerator: $$ \sum (x_i-\bar x)(y_i-\bar y) = \sum (x_i-\bar x)\cdot a(x_i-\bar x) = a\sum (x_i-\bar x)^2 . $$ Denominator: $$ \sqrt{\sum (x_i-\bar x)^2}\;\sqrt{\sum (y_i-\bar y)^2} = \sqrt{\sum (x_i-\bar x)^2}\;\sqrt{a^2 \sum (x_i-\bar x)^2} = \lvert a\rvert \sum (x_i-\bar x)^2 . $$ ভাগ করলে $$ r = \frac{a \sum (x_i-\bar x)^2}{\lvert a\rvert \sum (x_i-\bar x)^2} = \frac{a}{\lvert a\rvert} = \operatorname{sign}(a). $$ তাই \(a>0 \Rightarrow r = +1\) এবং \(a<0 \Rightarrow r = -1\)\(\blacksquare\) (লক্ষ করুন এটি ৪.১-এর "\(r=\cos\theta\), আর নিখুঁত রেখা মানে দুই vector সমান্তরাল"-এর বীজগাণিতিক রূপ।)


Coding (Python)

৭.১০ ★★ — from scratch Pearson

import numpy as np

def pearson_from_scratch(x, y):
    x = np.asarray(x, float); y = np.asarray(y, float)
    xc, yc = x - x.mean(), y - y.mean()          # centering
    num = xc @ yc                                # centered dot product
    den = np.sqrt(xc @ xc) * np.sqrt(yc @ yc)    # ||xc|| * ||yc||
    return num / den

x = np.array([1., 2, 3, 4, 5])
y = np.array([2., 4, 5, 4, 5])
r_scratch = pearson_from_scratch(x, y)
r_numpy   = np.corrcoef(x, y)[0, 1]
print(r_scratch, r_numpy)                         # 0.7745966... 0.7745966...
print("match?", np.isclose(r_scratch, r_numpy))   # True

লক্ষণীয়: \(n-1\) লাগেনি, কারণ numerator ও denominator-এ একই \(\frac{1}{n-1}\) গুণক কাটাকাটি হয়ে যায় — তাই centered dot product / (norm × norm) সরাসরি \(r\) দেয়। ফল np.corrcoef-এর সাথে হুবহু মেলে (\(0.7746\))।

৭.১১ ★★★ — cubic monotonic সম্পর্কে Pearson বনাম Spearman

import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from scipy import stats

rng = np.random.default_rng(0)
n = 2000
x = rng.uniform(-3, 3, n)
y = x**3 + rng.normal(0, 3, n)        # প্রবল monotonic, কিন্তু non-linear (cubic)

r_p = stats.pearsonr(x, y).statistic
r_s = stats.spearmanr(x, y).statistic
print(f"Pearson  = {r_p:.4f}")        # ~0.878
print(f"Spearman = {r_s:.4f}")        # ~0.889  (Pearson-এর চেয়ে বেশি)

fig, (axL, axR) = plt.subplots(1, 2, figsize=(11, 4.5))
axL.scatter(x, y, s=8, alpha=0.4, color="#2b6cb0")
axL.set_title(f"scatter: Pearson={r_p:.2f}, Spearman={r_s:.2f}")
axL.set_xlabel("x"); axL.set_ylabel("y = x^3 + noise")
hb = axR.hexbin(x, y, gridsize=35, cmap="viridis", mincnt=1)
axR.set_title("hexbin density (N=2000)")
axR.set_xlabel("x"); axR.set_ylabel("y")
fig.colorbar(hb, ax=axR, label="count")
fig.tight_layout()
fig.savefig("cubic_relationship.png", dpi=150)

ব্যাখ্যা: Pearson \(\approx 0.878\), Spearman \(\approx 0.889\) — Spearman সামান্য বেশি। কারণ সম্পর্কটি monotonic (x বাড়লে \(x^3\) সবসময় বাড়ে) কিন্তু non-linear (cubic curve)। Pearson সরলরেখা থেকে বিচ্যুতির জন্য শাস্তি দেয়, তাই ১-এর কিছুটা নিচে নামে। Spearman কেবল ক্রম দেখে — আর ক্রম প্রায় নিখুঁতভাবে রক্ষিত (noise অল্প কিছু জোড়ার rank উল্টে দেয় মাত্র), তাই সে ১-এর আরও কাছে থাকে। curve যত বেশি বাঁকা (কিন্তু একমুখী), Pearson ও Spearman-এর ব্যবধান তত বাড়ে — এটিই Spearman ব্যবহারের মূল যুক্তি।