Appearance
🎮 Data Wrangler — Pandas Method Challenge!
Bạn là Data Analyst tại ShopVN — sàn e-commerce top 5 Việt Nam. Sáng nay, team Data Engineering gửi cho bạn dataset bán hàng tháng 2/2026 — nhưng data bẩn kinh khủng! CEO cần báo cáo doanh thu chiều nay. Mission: chọn đúng Pandas method để clean 7 vấn đề data trong thời gian ngắn nhất! 🧹
🎯 Mục tiêu học tập
Sau khi hoàn thành game, bạn sẽ:
- Xử lý missing values — chọn đúng giữa
dropna(),fillna(),interpolate() - Phát hiện & xóa duplicates —
duplicated(),drop_duplicates() - Chuyển đổi data types —
astype(),pd.to_datetime(),pd.to_numeric() - Làm sạch strings —
.str.strip(),.str.lower(),.str.replace() - Xử lý inconsistent formats — chuẩn hóa ngày tháng, số điện thoại, tên
- Merge DataFrames —
pd.merge()với đúnghowvàon - Phát hiện outliers — dùng Numpy boolean masking + IQR method
📜 Luật chơi
┌──────────────────────────────────────────────────────┐
│ BẠN = Data Wrangler 🧹🔧 │
│ DATA = Dataset e-commerce bẩn 10,000+ dòng │
│ MỖI VÒNG = 1 vấn đề data → chọn Pandas method đúng │
│ 3 LỰA CHỌN mỗi vòng — chỉ 1 đáp án tối ưu │
│ MỤC TIÊU = Thu thập ≥ 80 XP để đạt hạng Gold 🥇 │
└──────────────────────────────────────────────────────┘Cách tính điểm mỗi vòng:
| Thành phần | XP |
|---|---|
| Trả lời đúng | +10 XP (Vòng 1–2), +12 XP (Vòng 3–4), +15 XP (Vòng 5–6), +18 XP (Vòng 7) |
| Trả lời sai | +0 XP |
| Không dùng hint | +2 XP bonus ⚡ |
| Giải thích đúng lý do | +3 XP bonus 🧠 |
Tổng XP tối đa: 10+10+12+12+15+15+18 = 92 XP (chưa tính bonus)
Nguyên tắc quan trọng:
- 🔒 Ưu tiên phương pháp không mất data —
fillna()thường tốt hơndropna()khi % missing nhỏ - ⚖️ Hiểu trade-off mỗi method — mỗi cách clean đều có pros/cons
🏆 Bảng xếp hạng & Huy hiệu
Ranks
| Hạng | XP | Mô tả |
|---|---|---|
| 🥇 Gold — Data Wrangler Pro | ≥ 80 XP | Bạn clean data như chuyên gia! Sẵn sàng EDA |
| 🥈 Silver — Data Cleaner | ≥ 55 XP | Tốt! Cần luyện thêm merge & outlier handling |
| 🥉 Bronze — Data Rookie | ≥ 35 XP | Ổn cho ngày đầu — ôn lại Pandas basics |
| 💀 Game Over | < 35 XP | Data vẫn bẩn — quay lại đọc Buổi 8 nhé! |
Huy hiệu đặc biệt
| Badge | Điều kiện | Mô tả |
|---|---|---|
| 🎯 Perfect Clean | Đúng 1 vòng + không dùng hint | Sạch bóng! |
| 🔥 Clean Streak | 3 vòng liên tiếp đúng | Chuỗi clean liên hoàn! |
| 🧠 Method Master | Giải thích đúng lý do ≥ 5 vòng | Hiểu sâu từng method! |
| ⚡ Speed Cleaner | Hoàn thành 7 vòng trong < 10 phút | Nhanh như .dropna()! |
| 🏆 Full Pipeline | Đúng tất cả 7 vòng | Data Wrangler huyền thoại! |
| 🧹 First Scrub | Đúng vòng đầu tiên | Bước đầu sạch sẽ! |
| 💡 No Hints Hero | Không dùng hint cả game | Tự clean bằng kiến thức! |
| 🛡️ Comeback Analyst | Sai 2 vòng đầu, đúng 5 vòng sau | Không bao giờ bỏ cuộc! |
| 🔗 Merge King | Đúng vòng merge (Vòng 6) | Master of JOINs! |
🎲 Chỉ số theo dõi
| Chỉ số | Icon | Mô tả | Mục tiêu |
|---|---|---|---|
| Method Accuracy | 🎯 | Số vòng chọn đúng method / tổng 7 vòng | ≥ 6/7 |
| Data Quality After | 📊 | Mức improve data quality sau mỗi vòng | Tăng đều |
| Speed | ⏱️ | Tổng thời gian hoàn thành game | < 15 phút |
📋 Kịch bản chi tiết
🧹 Vòng 1: Missing Values — "Cột price bị NaN" ⭐ Dễ
Dataset đơn hàng có 8% cột
pricebị NaN — CEO cần tổng doanh thu!
💬 Slack từ Data Lead:
"Em ơi, cột price có ~800 dòng bị NaN trên tổng 10,000. Cần tính tổng doanh thu — xử lý missing values sao cho không mất quá nhiều data nhé!"
Data sample:
| order_id | product | category | price | quantity |
|---|---|---|---|---|
| 1001 | Laptop Dell | Điện Tử | 15000000 | 1 |
| 1002 | Áo thun | Thời Trang | NaN | 2 |
| 1003 | Chuột Logitech | Điện Tử | 350000 | 3 |
| 1004 | Sữa rửa mặt | Mỹ Phẩm | NaN | 1 |
| 1005 | Bàn phím cơ | Điện Tử | 1200000 | 1 |
Vấn đề: 8% dòng có price = NaN. Cần tính tổng revenue = price × quantity.
Lựa chọn:
| Pandas Method | Code | |
|---|---|---|
| A | dropna() — Xóa tất cả dòng có NaN | df.dropna(subset=["price"], inplace=True) |
| B | fillna(median) — Điền median theo category | df["price"] = df.groupby("category")["price"].transform(lambda x: x.fillna(x.median())) |
| C | fillna(0) — Điền 0 vào NaN | df["price"].fillna(0, inplace=True) |
💡 Hint (−2 XP)
Xóa 8% data = mất 800 đơn hàng → doanh thu bị thiếu. Điền 0 = giá sản phẩm là 0 (vô lý). Có cách nào ước lượng hợp lý dựa trên các sản phẩm cùng category không?
Đáp án & Giải thích
✅ Đáp án đúng: B — fillna(median) theo category
Lý do:
- A sai vì
dropna()xóa 800 dòng (8%) → mất doanh thu đáng kể, vi phạm nguyên tắc "không mất data" - C sai vì
fillna(0)biến giá thành 0 → revenue = 0 → sai logic nghiệp vụ (không có sản phẩm giá 0) - B đúng vì
mediantheo category ước lượng hợp lý — sản phẩm Điện Tử có median price riêng, Thời Trang có median riêng. Median bền hơn mean với outliers (ví dụ: laptop 15 triệu kéo mean lên)
XP: +10 | Bonus: +2 (no hint), +3 (đúng lý do)
🧹 Vòng 2: Duplicates — "Đơn hàng bị trùng" ⭐ Dễ
Có 342 dòng duplicate do hệ thống sync lỗi — cần loại bỏ!
💬 Slack từ Backend Dev:
"Sorry team, sync service bị retry nên có đơn hàng bị insert nhiều lần. Các bạn remove duplicates giúp nhé!"
Data sample:
| order_id | customer_id | product | amount | order_date |
|---|---|---|---|---|
| 5001 | C101 | Laptop Dell | 15000000 | 2026-02-01 |
| 5001 | C101 | Laptop Dell | 15000000 | 2026-02-01 |
| 5002 | C102 | Tai nghe Sony | 2500000 | 2026-02-01 |
| 5003 | C101 | Chuột Logitech | 450000 | 2026-02-03 |
| 5003 | C101 | Chuột Logitech | 450000 | 2026-02-03 |
Vấn đề: 342 dòng duplicate hoàn toàn (tất cả cột giống nhau). Nếu không xóa → doanh thu bị tính đúp.
Lựa chọn:
| Pandas Method | Code | |
|---|---|---|
| A | drop_duplicates() — toàn bộ cột | df.drop_duplicates(inplace=True) |
| B | drop_duplicates(subset=["order_id"]) — chỉ theo order_id | df.drop_duplicates(subset=["order_id"], keep="first", inplace=True) |
| C | df[~df.duplicated()] — filter bằng boolean mask | df = df[~df.duplicated(subset=["order_id", "product"])] |
💡 Hint (−2 XP)
Duplicate do hệ thống sync = toàn bộ dòng giống nhau. order_id là unique identifier. Cần giữ dòng đầu tiên (keep="first") và xóa các bản copy. Có method nào check theo order_id + giữ bản gốc không?
Đáp án & Giải thích
✅ Đáp án đúng: B — drop_duplicates(subset=["order_id"], keep="first")
Lý do:
- A sai vì
drop_duplicates()không chỉ định subset → nếu 2 dòng khác nhau chỉ 1 cột nhỏ (VD: timestamp khác vài giây), sẽ không bị detect - C partial — hoạt động nhưng check 2 cột (
order_id+product) thay vì dùng primary keyorder_id→ có thể miss case 1 order mua 2 sản phẩm - B đúng vì dùng
order_id(unique identifier) để detect,keep="first"giữ bản gốc, xóa bản copy
XP: +10 | Bonus: +2 (no hint), +3 (đúng lý do)
🧹 Vòng 3: Wrong Data Types — "Cột price là string" ⭐⭐ Trung bình
Cột
pricebị lưu dạng string "1,500,000" thay vì number — không tính toán được!
💬 Slack từ Data Lead:
"Em thử
df['price'].sum()thì ra chuỗi '1,500,0002,500,000...' thay vì tổng. Hình như cột price bị lưu dạng text!"
Data sample:
| order_id | product | price (dtype: object) | quantity |
|---|---|---|---|
| 1001 | Laptop | "15,000,000" | 1 |
| 1002 | Áo thun | "250,000" | 2 |
| 1003 | Chuột | "350,000" | 3 |
| 1004 | Kem | "N/A" | 1 |
| 1005 | Bàn phím | "1,200,000" | 1 |
Vấn đề: Cột price là object (string), có dấu phẩy ngăn cách hàng nghìn, và có giá trị "N/A".
Lựa chọn:
| Pandas Method | Code | |
|---|---|---|
| A | astype(float) trực tiếp | df["price"] = df["price"].astype(float) |
| B | str.replace rồi to_numeric | df["price"] = df["price"].str.replace(",", ""); df["price"] = pd.to_numeric(df["price"], errors="coerce") |
| C | apply(lambda) custom | df["price"] = df["price"].apply(lambda x: float(x) if x != "N/A" else 0) |
💡 Hint (−2 XP)
String "15,000,000" có dấu phẩy → astype(float) sẽ crash. Cần bỏ dấu phẩy trước. "N/A" là text, không phải số → cần xử lý riêng. pd.to_numeric() có parameter errors="coerce" biến giá trị không hợp lệ thành NaN.
Đáp án & Giải thích
✅ Đáp án đúng: B — str.replace(",", "") + pd.to_numeric(errors="coerce")
Lý do:
- A sai vì
astype(float)crash khi gặp dấu phẩy:ValueError: could not convert string to float: '15,000,000' - C partial — hoạt động nhưng chỉ handle "N/A", không handle các invalid values khác (VD: "TBD", "-", " "). Dùng
fillna(0)thay vì để NaN cũng không tối ưu - B đúng vì: (1)
str.replace(",", "")bỏ dấu phẩy, (2)pd.to_numeric(errors="coerce")chuyển sang float, tự biến mọi giá trị invalid thành NaN — tổng quát và an toàn
XP: +12 | Bonus: +2 (no hint), +3 (đúng lý do)
🧹 Vòng 4: Messy Strings — "Tên customer viết lung tung" ⭐⭐ Trung bình
Cột
customer_namecó dấu cách thừa, viết hoa/thường lộn xộn, ký tự lạ!
💬 Slack từ Marketing:
"Chị cần gửi email cho top customers — nhưng tên khách hàng nhìn kinh quá, có tên viết HOA hết, có tên thừa dấu cách, có tên dính ký tự lạ."
Data sample:
| customer_id | customer_name (raw) | |
|---|---|---|
| C101 | " nguyễn văn an " | an@email.com |
| C102 | "TRẦN THỊ BÌNH" | binh@email.com |
| C103 | "lê hoàng cường " | cuong@email.com |
| C104 | " Phạm Thị Dung" | dung@email.com |
| C105 | "VÕ@@minh em" | em@email.com |
Vấn đề: Dấu cách thừa đầu/cuối, double spaces, viết hoa/thường không nhất quán, ký tự đặc biệt lạ.
Lựa chọn:
| Pandas Method | Code | |
|---|---|---|
| A | str.strip() — chỉ xóa dấu cách đầu/cuối | df["customer_name"] = df["customer_name"].str.strip() |
| B | Chain methods — strip + title + replace | df["customer_name"] = df["customer_name"].str.strip().str.replace(r"[^a-zA-ZÀ-ỹ\s]", "", regex=True).str.replace(r"\s+", " ", regex=True).str.title() |
| C | str.upper() — chuyển hết thành chữ hoa | df["customer_name"] = df["customer_name"].str.upper() |
💡 Hint (−2 XP)
Vấn đề có nhiều lớp: dấu cách thừa + ký tự lạ + format chữ hoa/thường. Cần chain nhiều methods theo thứ tự: strip → remove ký tự lạ → chuẩn hóa spaces → title case. .str.title() viết hoa chữ cái đầu mỗi từ.
Đáp án & Giải thích
✅ Đáp án đúng: B — Chain methods: strip → remove special chars → normalize spaces → title
Lý do:
- A sai vì chỉ xử lý 1 trong 4 vấn đề (dấu cách đầu/cuối). Không fix double spaces, ký tự lạ, hay format chữ
- C sai vì
str.upper()biến tất cả thành HOA → "NGUYỄN VĂN AN" — không professional cho email/báo cáo, và không fix spaces/ký tự lạ - B đúng vì xử lý tất cả vấn đề: (1)
strip()bỏ spaces đầu/cuối, (2) regex bỏ ký tự đặc biệt, (3)\s+→" "normalize spaces, (4)title()→ "Nguyễn Văn An" — chuẩn format
Kết quả sau clean:
| customer_id | customer_name (cleaned) |
|---|---|
| C101 | "Nguyễn Văn An" |
| C102 | "Trần Thị Bình" |
| C103 | "Lê Hoàng Cường" |
| C104 | "Phạm Thị Dung" |
| C105 | "Võ Minh Em" |
XP: +12 | Bonus: +2 (no hint), +3 (đúng lý do)
🧹 Vòng 5: Inconsistent Date Formats — "3 kiểu ngày khác nhau" ⭐⭐⭐ Khó
Cột
order_datecó 3 format khác nhau — cần chuẩn hóa để phân tích theo tháng!
💬 Slack từ BI Analyst:
"Anh cần group orders theo tháng nhưng cột order_date có dòng '2026-02-15', có dòng '15/02/2026', có dòng 'Feb 15, 2026'. Chuẩn hóa giúp anh nhé!"
Data sample:
| order_id | order_date (raw) | amount |
|---|---|---|
| 1001 | "2026-02-01" | 5000000 |
| 1002 | "15/02/2026" | 2500000 |
| 1003 | "Feb 03, 2026" | 1200000 |
| 1004 | "2026-02-10" | 8000000 |
| 1005 | "28/02/2026" | 450000 |
Vấn đề: 3 format ngày khác nhau. Cần chuẩn hóa thành datetime64 để groupby theo tháng.
Lựa chọn:
| Pandas Method | Code | |
|---|---|---|
| A | pd.to_datetime() với format cố định | df["order_date"] = pd.to_datetime(df["order_date"], format="%Y-%m-%d") |
| B | pd.to_datetime() với infer_datetime_format | df["order_date"] = pd.to_datetime(df["order_date"], format="mixed", dayfirst=True) |
| C | str.replace() rồi to_datetime | df["order_date"] = df["order_date"].str.replace("/", "-"); df["order_date"] = pd.to_datetime(df["order_date"]) |
💡 Hint (−2 XP)
Có 3 format khác nhau → không thể dùng 1 format cố định. pd.to_datetime() có parameter format="mixed" cho phép parse nhiều format trong cùng 1 cột. dayfirst=True hữu ích khi có format dd/mm/yyyy.
Đáp án & Giải thích
✅ Đáp án đúng: B — pd.to_datetime(format="mixed", dayfirst=True)
Lý do:
- A sai vì
format="%Y-%m-%d"chỉ parse được "2026-02-01", crash khi gặp "15/02/2026" hoặc "Feb 03, 2026" - C sai vì chỉ handle "/" → "-", không handle "Feb 03, 2026" format. Và "15-02-2026" không tự parse đúng nếu thiếu
dayfirst - B đúng vì
format="mixed"cho phép Pandas parse nhiều format trong cùng 1 cột,dayfirst=Trueđảm bảo "15/02/2026" parse thành 15 tháng 2 (không phải tháng 15)
XP: +15 | Bonus: +2 (no hint), +3 (đúng lý do)
🧹 Vòng 6: Merge Conflicts — "JOIN orders với customers" ⭐⭐⭐ Khó
Cần merge bảng
ordersvớicustomers— nhưng có orders không có customer!
💬 Slack từ Data Lead:
"Em merge 2 bảng nhưng mất 500 đơn hàng — hình như có orders mà customer chưa được nhập vào hệ thống. Cần giữ TẤT CẢ đơn hàng, kể cả đơn chưa có customer info!"
Data sample:
Bảng orders (10,000 dòng):
| order_id | customer_id | product | amount |
|---|---|---|---|
| 1001 | C101 | Laptop | 15000000 |
| 1002 | C102 | Áo thun | 500000 |
| 1003 | C999 | Chuột | 350000 |
| 1004 | C101 | Bàn phím | 1200000 |
| 1005 | None | Kem | 250000 |
Bảng customers (8,500 dòng):
| customer_id | name | region | segment |
|---|---|---|---|
| C101 | Nguyễn Văn An | Bắc | Premium |
| C102 | Trần Thị Bình | Nam | Standard |
| C103 | Lê Hoàng Cường | Trung | Premium |
Vấn đề: C999 không tồn tại trong customers. order_id=1005 không có customer_id. Cần giữ tất cả orders.
Lựa chọn:
| Pandas Method | Code | |
|---|---|---|
| A | pd.merge() với how="inner" | df_merged = pd.merge(orders, customers, on="customer_id", how="inner") |
| B | pd.merge() với how="left" | df_merged = pd.merge(orders, customers, on="customer_id", how="left") |
| C | pd.concat() | df_merged = pd.concat([orders, customers], axis=1) |
💡 Hint (−2 XP)
Cần giữ TẤT CẢ đơn hàng kể cả đơn chưa có customer. Trong SQL, đây là LEFT JOIN — giữ toàn bộ bảng bên trái (orders), match được thì điền info, không match thì NaN. pd.merge() tương đương SQL JOIN.
Đáp án & Giải thích
✅ Đáp án đúng: B — pd.merge(how="left")
Lý do:
- A sai vì
innerchỉ giữ rows match được ở cả 2 bảng → mất 500 đơn hàng cócustomer_idkhông tồn tại trongcustomers - C sai vì
pd.concat(axis=1)ghép ngang theo index, KHÔNG match theocustomer_id→ dữ liệu lệch hoàn toàn - B đúng vì
leftjoin giữ toàn bộ orders (bảng trái), match được customer thì điền thông tin, không match thìname/region/segment= NaN → không mất đơn hàng nào
Kết quả merge:
| order_id | customer_id | product | amount | name | region | segment |
|---|---|---|---|---|---|---|
| 1001 | C101 | Laptop | 15000000 | Nguyễn Văn An | Bắc | Premium |
| 1002 | C102 | Áo thun | 500000 | Trần Thị Bình | Nam | Standard |
| 1003 | C999 | Chuột | 350000 | NaN | NaN | NaN |
| 1004 | C101 | Bàn phím | 1200000 | Nguyễn Văn An | Bắc | Premium |
| 1005 | None | Kem | 250000 | NaN | NaN | NaN |
XP: +15 | Bonus: +2 (no hint), +3 (đúng lý do)
🧹 Vòng 7: Outlier Detection — "Đơn hàng 5 tỷ?!" ⭐⭐⭐ Khó (Boss Round!)
CEO hỏi: "Tại sao có đơn hàng 5 tỷ trong dataset? Lọc outliers giúp tôi!"
💬 Slack từ CEO:
"Tổng doanh thu bất thường cao — hình như có đơn hàng giá trị cực lớn. Dùng phương pháp thống kê để phát hiện và flag outliers!"
Data sample (cột amount):
python
import numpy as np
import pandas as pd
amounts = pd.Series([
500000, 1200000, 850000, 2500000, 350000,
15000000, 780000, 5000000000, 920000, 1100000,
# 5,000,000,000 (5 tỷ) = outlier rõ ràng!
])
print(f"Mean: {amounts.mean():,.0f}")
print(f"Median: {amounts.median():,.0f}")
print(f"Std: {amounts.std():,.0f}")Vấn đề: Giá trị 5 tỷ kéo mean lên bất thường. Cần phát hiện outliers bằng phương pháp thống kê.
Lựa chọn:
| Method | Code | |
|---|---|---|
| A | Xóa giá trị > 100 triệu (hardcode) | df = df[df["amount"] <= 100_000_000] |
| B | IQR method với Numpy | Q1 = np.percentile(df["amount"], 25); Q3 = np.percentile(df["amount"], 75); IQR = Q3 - Q1; mask = (df["amount"] >= Q1 - 1.5*IQR) & (df["amount"] <= Q3 + 1.5*IQR); df_clean = df[mask] |
| C | Z-score > 3 | from scipy import stats; z = np.abs(stats.zscore(df["amount"])); df_clean = df[z < 3] |
💡 Hint (−2 XP)
Hardcode threshold = magic number → không tổng quát. IQR (Interquartile Range) là phương pháp phổ biến nhất cho DA: Q1, Q3 → IQR = Q3−Q1 → outlier nếu < Q1−1.5×IQR hoặc > Q3+1.5×IQR. Dùng np.percentile() tính Q1, Q3. Z-score hoạt động nhưng giả định phân phối chuẩn — không phải lúc nào cũng đúng.
Đáp án & Giải thích
✅ Đáp án đúng: B — IQR method với Numpy
Lý do:
- A sai vì 100 triệu là "magic number" — tại sao 100 triệu mà không phải 50 triệu hay 200 triệu? Không có cơ sở thống kê. Nếu dataset thay đổi, threshold cũng phải sửa tay
- C partial — Z-score hoạt động nhưng: (1) cần
scipy(dependency thêm), (2) giả định dữ liệu phân phối chuẩn (normal distribution) — doanh thu e-commerce thường lệch phải (right-skewed), Z-score kém hiệu quả - B đúng vì IQR: (1) không cần giả định phân phối, (2) robust với data skewed, (3) dùng
numpyđã có sẵn, (4) formula chuẩn quốc tế (dùng trong boxplot). Kết quả: Q1, Q3, IQR tự tính từ data → tự điều chỉnh theo dataset
Minh họa IQR:
python
import numpy as np
amounts = np.array([500000, 1200000, 850000, 2500000, 350000,
15000000, 780000, 5000000000, 920000, 1100000])
Q1 = np.percentile(amounts, 25)
Q3 = np.percentile(amounts, 75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
print(f"Q1: {Q1:,.0f} | Q3: {Q3:,.0f} | IQR: {IQR:,.0f}")
print(f"Lower bound: {lower_bound:,.0f}")
print(f"Upper bound: {upper_bound:,.0f}")
print(f"Outliers: {amounts[(amounts < lower_bound) | (amounts > upper_bound)]}")
# → 5,000,000,000 bị flag là outlier ✅XP: +18 | Bonus: +2 (no hint), +3 (đúng lý do)
🏁 Tổng kết
Bảng tổng hợp Pandas Methods
| Vấn đề data | Method chính | Nhớ |
|---|---|---|
| Missing values | fillna(median) theo group | Không mất data, ước lượng hợp lý |
| Duplicates | drop_duplicates(subset, keep) | Dùng primary key, giữ bản gốc |
| Wrong dtypes | str.replace() + pd.to_numeric() | Clean string trước, convert sau |
| Messy strings | .str.strip().str.title() chain | Chain methods theo thứ tự |
| Inconsistent dates | pd.to_datetime(format="mixed") | Tự detect nhiều format |
| Merge conflicts | pd.merge(how="left") | Giữ tất cả bảng chính |
| Outliers | IQR method + np.percentile() | Không cần giả định phân phối |
Tiếp theo
Bạn đã biết chọn đúng method cho từng vấn đề data. Giờ hãy áp dụng tất cả vào Workshop — Data Cleaning Pipeline để xây dựng pipeline cleaning hoàn chỉnh cho dataset e-commerce thực tế! 🚀
💡 Sau game này
- ✅ Bạn biết 7 loại data problem phổ biến nhất
- ✅ Bạn biết Pandas method tối ưu cho từng loại
- ✅ Bạn hiểu trade-off: dropna vs fillna, inner vs left join, IQR vs Z-score
- → Sẵn sàng cho Workshop: áp dụng tất cả vào 1 pipeline hoàn chỉnh!