Missing data — কীভাবে ভরাব
এই পাঠে যা শিখবেন
- MCAR, MAR, MNAR — missing-এর তিন ধরন
- কখন drop, কখন impute
- Simple ও advanced imputation technique
- "Missing" নিজেই signal — কীভাবে ব্যবহার করবেন
- Sklearn-এ practical imputation pipeline
১ · কেন missing data হয়
বাস্তব-জগতের ডেটা প্রায় কখনোই complete না। Daraz-এর order form-এ phone optional, কেউ দেননি — missing। Hospital-এ blood-test হয়নি কারণ রোগী আগেই ছেড়ে দিয়েছেন — missing। Survey-এ income লিখতে অস্বস্তি — missing। মানুষ, system, sensor — সবার সীমাবদ্ধতায় missing dataMissing Dataএকটি observation-এর কোনো column-এ value উপস্থিত নেই। NaN (Not a Number), None, NULL, "?", "" বিভিন্ন form-এ থাকতে পারে। তৈরি হয়।
ML মডেল most algorithm NaN handle করতে পারে না। তাই missing-এর সাথে কী করব — সিদ্ধান্ত নিতে হয়। কিন্তু সিদ্ধান্ত-এর আগে প্রশ্ন: missing হলো কেন?
২ · MCAR, MAR, MNAR — তিন ধরন
১) MCAR — Missing Completely At Random: missing হওয়ার সম্ভাবনা data-র কোনো variable-এর উপর নির্ভর করে না।
২) MAR — Missing At Random: missing-এর সম্ভাবনা observed অন্য variable-এর উপর নির্ভর করে।
৩) MNAR — Missing Not At Random: missing-এর সম্ভাবনা missing value নিজের উপরই নির্ভর করে।
MCAR উদাহরণ: sensor random failure — যেকোনো reading miss।
MAR উদাহরণ: পুরুষেরা income কম report করেন — missing-এর সম্ভাবনা gender (observed)-এর উপর নির্ভরশীল।
MNAR উদাহরণ: উচ্চ-আয়ের মানুষ income লিখতে চান না — missing-এর সম্ভাবনা income (যা missing) নিজেই উপর নির্ভর।
৩ · কীভাবে চিনব কোন ধরন
MCAR test (Little's MCAR test) আছে, কিন্তু practical:
- MCAR check: missing rate কি সব subgroup-এ একই?
df.groupby('district')['col'].apply(lambda x: x.isnull().mean())। - MAR check: missing flag বানিয়ে অন্য variable-এর সাথে correlation।
- MNAR check: impossible to test from data alone — domain knowledge দরকার।
"Missing rate" measure:
$$\text{missing rate} = \frac{\text{NaN count}}{\text{total rows}} \times 100\%$$
৪ · Strategy ১ — Deletion
(ক) Listwise (row drop):
df.dropna()— যে row-এ কোনো NaN, সেটা বাদ।- সরল, কিন্তু data হারানো বেশি।
- উপযুক্ত: missing < ৫% এবং MCAR।
(খ) Pairwise:
- প্রতিটি analysis-এ যে variable লাগে, শুধু সেই গুলোতে missing-এ row drop।
- Statistical analysis-এ ব্যবহৃত, ML-এ rare।
(গ) Column drop:
df.drop(columns=['col'])— column-এ missing > ৫০-৭০%, drop সবচেয়ে সহজ।- কিন্তু সেই column যদি predictive থাকত — তথ্য হারালেন।
৫ · Strategy ২ — Simple imputation
Numeric column-এ:
- Mean: sensitive to outlier; symmetric distribution-এ ভাল।
- Median: robust; skewed distribution-এ preferred।
- Constant (০, -১): domain-specific, যেমন "no purchase" = ০।
Categorical column-এ:
- Mode: সবচেয়ে frequent category।
- "Missing" নতুন category: "Unknown" — missing-এ pattern থাকলে ভাল।
সমস্যা: mean-imputation variance underestimate করে, correlation distort করে। সরল কিন্তু crude।
৬ · Strategy ৩ — KNN imputation
KNN imputerK-Nearest Neighbors Imputerএকটি missing value-এর জন্য — k-জন closest non-missing neighbor খুঁজে তাদের average দিয়ে fill। Distance metric: Euclidean সাধারণত। — missing row-এর সবচেয়ে কাছের k-জন non-missing row খুঁজে — তাদের গড় দিয়ে fill। Sklearn-এ KNNImputer।
সুবিধা: non-linear relationship ধরে; mean-এর চেয়ে accurate।
অসুবিধা: বড় data-তে slow ($O(n^2)$ distance), scaling sensitive।
৭ · Strategy ৪ — Iterative imputation (MICE)
MICE (Multiple Imputation by Chained Equations): প্রতিটি column-কে অন্য column থেকে regression দিয়ে predict — iterative। Sklearn-এ IterativeImputer।
- প্রতিটি missing column-এ initial impute (mean)।
- একটি column-এর missing কে অন্য সব column থেকে regression দিয়ে re-impute।
- সব column-এ rotate; converge না হওয়া পর্যন্ত repeat।
Best statistical-quality, কিন্তু expensive। Survey-research-এ standard।
৮ · "Missing" নিজেই signal
Bangladesh fintech-এ "income" missing — সাধারণত সেই user reluctant disclose। "Missing" predictive। কী করব?
- একটি indicator column যোগ করুন:
df['income_missing'] = df['income'].isnull().astype(int)। - তারপর income-এ impute করুন।
- মডেল দু'টি signal পায়: "missing হয়েছিল কি না" ও "imputed value কত"।
Tree-based model (XGBoost, LightGBM) NaN নিজেই handle করতে পারে — split-এর সময় missing-কে আলাদা branch-এ পাঠায়। Linear model-এ এই facility নেই।
৯ · Pandas ও Sklearn কোড
import pandas as pd
import numpy as np
# নকল bKash data with missing
np.random.seed(0)
df = pd.DataFrame({
'age': np.random.randint(18, 65, 100).astype(float),
'income': np.random.lognormal(10, 0.8, 100),
'district': np.random.choice(['Dhaka','Chattogram','Sylhet'], 100)
})
# inject missing
df.loc[np.random.choice(df.index, 15), 'income'] = np.nan
df.loc[np.random.choice(df.index, 5), 'age'] = np.nan
print("Missing per column:")
print(df.isnull().sum())
print(f"\nMissing rate (income): {df['income'].isnull().mean():.1%}")
# Simple imputation
df_simple = df.copy()
df_simple['age'] = df_simple['age'].fillna(df_simple['age'].median())
df_simple['income'] = df_simple['income'].fillna(df_simple['income'].median())
# Indicator column
df_simple['income_was_missing'] = df['income'].isnull().astype(int)
print("\nAfter imputation:")
print(df_simple.isnull().sum())
print(df_simple.head())
১০ · KNN imputer — sklearn
import pandas as pd, numpy as np
from sklearn.impute import KNNImputer
np.random.seed(0)
df = pd.DataFrame({
'age': np.random.randint(18, 65, 50).astype(float),
'income': np.random.lognormal(10, 0.8, 50),
'spend': np.random.normal(5000, 1500, 50)
})
df.loc[[2, 7, 14], 'income'] = np.nan
df.loc[[3, 9], 'age'] = np.nan
# KNN with 5 neighbors
imp = KNNImputer(n_neighbors=5)
filled = imp.fit_transform(df)
df_filled = pd.DataFrame(filled, columns=df.columns)
print("Original (with NaN):")
print(df.head(15))
print("\nKNN-imputed:")
print(df_filled.head(15).round(0))
১১ · Bangladesh-context উদাহরণ
- NID database: ১৯৭০-র আগের জন্ম-তারিখ approximate — "১লা জানুয়ারী" placeholder। এটা missing-as-encoded।
- bKash KYC: "occupation" optional field — ৩০-৪০% missing। MAR (urban-এ কম missing)।
- Hospital records: blood pressure missing — সাধারণত যাদের measure হয়নি (MNAR — অসুস্থ ছিলেন না)।
- Pathao ride: "rating" optional — যাঁরা rate করেননি, তাঁরা সাধারণত neutral। "Missing = neutral 4-star" assumption।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ আপনার hospital dataset-এ "blood pressure" column-এ ৪০% missing। এটা MCAR/MAR/MNAR? কীভাবে confirm করবেন? কী strategy?
৪০% missing — significant। সরাসরি drop সম্ভব না (অর্ধেক rows হারাব), simple impute বিপজ্জনক (BP medical decision-এ critical)।
Pattern detection:
- MCAR ধারণা: nurse random forgot — সব patient-এ equal probability।
- MAR ধারণা: outpatient (kort visit)-এ BP measure হয় না, inpatient-এ হয় — visit_type observed।
- MNAR ধারণা: high-BP patient-রা dizzy হয়ে চলে গেছেন measurement-এর আগে — value নিজেই missing-এর কারণ।
Confirm-এর পদ্ধতি:
df['bp_missing'] = df['bp'].isnull()— flag column।- flag বনাম visit_type, age, department crosstab। Outpatient-এ ৭০%, inpatient-এ ১০% — strong MAR signal।
- Domain expert (doctor) interview: "BP কখন measure হয় না?"
- MNAR test: hospital protocol — কখন BP optional? যদি রোগী সরে যায় — pattern চেক।
Strategy proposed:
- Drop-এর বদলে — keep with imputation।
- Flag column রাখুন: bp_missing।
- MICE/IterativeImputer ব্যবহার করুন — visit_type, age, weight, diagnosis থেকে predict।
- Sensitivity analysis: imputed vs non-imputed-এ মডেলের behavior দেখুন।
সাবধানতা:
- Medical context-এ false-impute বিপজ্জনক। "Imputed BP = 120" decision-এ confidence কম।
- Production-এ — uncertainty quantification (multiple imputation, draw from posterior)।
- Document: "এই row-এর BP imputed" — clinician notice করতে পারেন।
Bangladesh hospital context:
- BSMMU, Square, Apollo — different protocols।
- Government hospital-এ documentation incomplete বেশি — MNAR risk।
- Public health study-তে BMRC ethics — imputation methodology pre-register।
মূল উপলব্ধি: ৪০% missing = serious problem। Statistical method-এর পাশাপাশি domain dialogue অপরিহার্য। Health data-তে imputation = clinical decision-এ amplified risk। চিন্তাভাবনা সর্বোচ্চ।
প্র ০২ আপনার কাছে ১০০ column-এর data, প্রতিটিতে ১% missing। Listwise drop-এ কত % row হারাবেন? কেন?
এটি statistical paradox যা অনেককে অবাক করে। সরল calculation:
$$P(\text{row complete}) = (1 - 0.01)^{100} = 0.99^{100} \approx 0.366$$
$$P(\text{row dropped}) = 1 - 0.366 = 0.634 \approx 63.4\%$$
অর্থাৎ — ১% missing প্রতি column-এ থাকলেও — listwise drop-এ ~৬৩% data যাবে। বিধ্বংসী।
কেন এমন:
- প্রতিটি column independent missing।
- একটি row বাঁচবে শুধু যদি সব ১০০ column-এ value থাকে।
- Probability product: ০.৯৯ × ০.৯৯ × ... ১০০ বার।
- ৫০ column হলেও ~৬০% থাকে; ১০০-তে ৩৭%।
উদাহরণ:
- ১ লাখ user × ১০০ column survey।
- প্রতিটি column-এ ১% missing।
- Listwise: ৩৬,৬০০ user বাঁচবে।
- Imputation-এর সাথে: পুরো ১,০০,০০০ ব্যবহার সম্ভব।
আরও বাস্তব numbers:
- ৫% missing প্রতি column, ১০ column → $0.95^{10} = 60\%$ retain।
- ৫% missing, ৫০ column → $0.95^{50} = 7.7\%$ retain।
- ১০% missing, ২০ column → $0.9^{20} = 12\%$ retain।
Implication:
- "Listwise deletion সবসময় safe" — myth।
- Wide dataset (অনেক column)-এ listwise destructive।
- Imputation almost always preferred — even simple mean।
Mitigation strategies:
- Missing pattern visualization: missingno library — heatmap। কোন column-এ correlated missing?
- Column drop: high-missing column drop, low-missing impute।
- Threshold-based: "row-এ > ৩টি missing হলে drop, না হলে impute" — hybrid।
Sklearn-এ: Pipeline-এ SimpleImputer বা IterativeImputer — listwise অপ্রয়োজন।
মূল উপলব্ধি: Math-এর intuition-এ "১% missing = ১% data হারানো" — but reality "১% × N column = compounded loss"। Wide data-তে imputation indispensable। এই calculation মাথায় থাকলে — junior থেকে senior data scientist-এ leap।
প্র ০৩ "Missing data is not data" — এই statement-এর বিরুদ্ধে কী বলতে পারেন? কীভাবে missingness নিজেই predictive feature?
আশ্চর্যের ব্যাপার — অনেক production system-এ missing-pattern primary signal। উদাহরণ ও কেন:
(১) Loan default prediction
- "Phone number" missing-এর rate default-এর সাথে highly correlated।
- Reason: legitimate borrower contact-এর সব info দেন; defaulter intent থেকে hide করেন।
- Feature:
n_missing_fields— strong predictor।
(২) Credit card fraud
- Stolen card-এ "billing zip" wrong/missing।
- "Address verification" failed/missing — fraud signal।
- Feature:
address_fields_missing।
(৩) Healthcare
- "Lab test" missing — সাধারণত doctor order করেননি (low concern) বা patient avoid করেছেন (concern)।
- Pattern complex, কিন্তু missing nature-ই signal।
(৪) E-commerce
- Daraz-এ "review_text" missing — neutral satisfaction (passive)।
- "Phone verification" skipped — quick checkout, less commitment।
- Feature:
has_phone_verified।
কেন missingness predictive:
- Selection bias: কে disclosure করতে চায় — non-random।
- Engagement signal: বেশি field fill = বেশি committed।
- Detection avoidance: bad actor specific pattern hide করেন।
Implementation pattern:
- প্রতিটি missing-prone column-এ
{col}_missingindicator। - Aggregate:
n_missing,missing_rate_per_row। - Cross-feature: "address_missing AND phone_missing" — compound signal।
- Tree model কে এই indicator feature feed।
সাবধানতা:
- Imputation flatten করে dilute: impute করার আগে indicator-এ capture।
- Model interpretation: "missing-related feature important" — stakeholder-কে explain।
- Fairness: protected group-এ missing pattern bias বহন করতে পারে।
Bangladesh-specific examples:
- NID number-এ "0000" — placeholder, NID নেই (rural elderly)।
- Mobile-banking KYC-এ "occupation" missing → informal worker।
- Election Commission data-তে "education" missing → privacy concern।
Quote-worthy idea (Rubin): "There is no consensus among statisticians about the best procedure to use." — অর্থাৎ context-dependent, generic rule নেই।
মূল উপলব্ধি: "Data clean" ≠ "missing fix"। Missing-pattern itself rich information। ভাল data scientist missingness কে first-class feature-এ promote করেন।
প্র ০৪ Mean imputation কেন variance underestimate করে? উদাহরণসহ ব্যাখ্যা করুন।
এটি statistical truth যা প্রতিটি data scientist-কে জানতে হয়। সরল উদাহরণ:
সেটআপ:
- True data: $[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]$।
- Mean = ৫.৫, std = ৩.০৩।
- ৫টি random missing করি: $[?, 2, ?, 4, ?, 6, ?, 8, ?, 10]$।
- Observed mean (২,৪,৬,৮,১০) = ৬।
Mean impute: $[6, 2, 6, 4, 6, 6, 6, 8, 6, 10]$ — ৫টি ৬ যোগ।
Imputed std:
- True std (পূর্ণ): ৩.০৩।
- Imputed std: ১.৭০ (নিচে)।
- Variance loss: ($1.7^2$ vs $3.0^2$) = ২.৯ vs ৯.০ = ৬৮% reduction।
কেন এমন:
- প্রতিটি impute = mean। Mean-এর variance = ০।
- Spread artificially compressed।
- Distribution shape distorted — সরু, সরু, সরু।
আরও subtle ক্ষতি:
(১) Correlation-এ bias
- X ও Y correlated; X-এ missing।
- Mean-impute X — correlation toward 0 attenuate।
- Reason: imputed X-এ no variance, তাই Y-এর সাথে relationship lose।
(২) Standard error underestimate
- Confidence interval narrower than truth।
- "Significance" overstated — false positive risk।
(৩) Regression coefficient bias
- Linear regression-এ slope toward zero।
- "Effect size" underestimated।
সমাধান:
- Stochastic imputation: mean + random noise (mean-এ residual draw)।
- Multiple imputation (MI): m টি plausible value generate করুন → m model fit → result combine।
- MICE: Iterative regression-based — variance preserved।
- Bayesian imputation: uncertainty explicit।
Multiple imputation example:
- Missing-এ ৫টি plausible value draw (different seed)।
- ৫ ভিন্ন complete dataset।
- প্রতিটিতে model fit।
- Coefficient গড় + variance combine (Rubin's rules)।
- Final result variance properly include করে।
R-এ mice package, Python-এ fancyimpute বা statsmodels support।
Practical guidance:
- EDA-তে quick mean-impute OK।
- Production model-এ MICE বা KNN।
- Statistical inference (publication, regulatory) — multiple imputation mandatory।
- Tree model-এ NaN as-is — no imputation needed।
Bangladesh research context:
- Health survey (BDHS) — multiple imputation standard।
- Economic survey (BBS) — imputation methodology documented।
- Academic paper-এ "we used mean imputation" → reviewer সাধারণত reject।
মূল উপলব্ধি: Mean imputation simple কিন্তু statistically lazy। Real spread preserved রাখতে — multiple imputation বা model-based। Missing handling = inference quality-এর সরাসরি determinant।
অনুশীলন
-
Missing rate calculation: একটি DataFrame-এ ১০০ column, প্রতিটিতে ২% missing। Listwise dropped-এর পর কত % row বাঁচবে?
$0.98^{100} \approx 0.133 = 13.3\%$ row বাঁচবে। ৮৬.৭% হারাবেন।
Conclusion: imputation almost mandatory wide dataset-এ।
-
Indicator + impute pipeline: "income" column-এ NaN-এর জন্য — indicator column বানান এবং median দিয়ে fill করুন। Pandas-এ লিখুন।
df['income_missing'] = df['income'].isnull().astype(int) df['income'] = df['income'].fillna(df['income'].median())এই pattern Bangladesh fintech KYC pipeline-এ standard। missing flag + median-fill = robust baseline।
-
KNN vs mean comparison: Sklearn-এর Iris dataset-এ ১০% missing inject করুন একটি column-এ। Mean ও KNN imputation compare করুন original-এর সাথে — কোনটা বেশি accurate?
from sklearn.datasets import load_iris from sklearn.impute import SimpleImputer, KNNImputer import numpy as np iris = load_iris(as_frame=True).frame X = iris.drop(columns=['target']).values mask = np.random.rand(*X.shape) < 0.1 X_missing = X.copy() X_missing[mask] = np.nan mean_imp = SimpleImputer(strategy='mean').fit_transform(X_missing) knn_imp = KNNImputer(n_neighbors=5).fit_transform(X_missing) print(f"Mean MSE: {np.nanmean((mean_imp - X)**2):.3f}") print(f"KNN MSE: {np.nanmean((knn_imp - X)**2):.3f}")সাধারণত KNN MSE কম — কারণ ভিন্ন species-এ value আলাদা; KNN species-aware fill।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পাঠ ১৮ · Outlier detection পরবর্তী পাঠ Missing-এর পর — extreme value কীভাবে handle।
- পাঠ ১৬ · EDA আগের পাঠ Missing detect-এর process EDA-তে।
- পাঠ ২০ · Feature scaling এই পাঠের সাথে সম্পর্কিত Imputation-এর পর scaling।
- সব AI Courses দেখুন ABCL TECH Python, ML, DL, NLP, CV, GenAI, RL, MLOps — সব AI কোর্স একসাথে।