Appearance
📝 10 phút EDA = 10 giờ phân tích đúng hướng
Mở đầu — "Báo cáo đẹp, số liệu sai, sếp gần mất hợp đồng."
Tùng, 27 tuổi, Data Analyst tại một công ty fintech ở TP.HCM — loại startup đã Series B, sản phẩm chính là ứng dụng cho vay tiêu dùng với 2 triệu người dùng. Tùng là DA duy nhất trong team Product, phụ trách phân tích hành vi người dùng và hiệu suất khoản vay.
Tùng không thiếu kỹ năng. Anh viết Python gọn ghẽ, Pandas chạy trơn tru, biết merge, biết groupby, biết xuất báo cáo Excel đẹp với conditional formatting. Sếp khen Tùng "nhanh và chính xác." Đồng nghiệp gọi anh là "máy xay data."
Nhưng tháng trước, Tùng suýt trở thành "máy xay... sai."
Phòng Business Development cần một báo cáo gấp: phân tích hiệu suất danh mục cho vay Q4/2025 để chuẩn bị pitch với đối tác ngân hàng. Tùng nhận file CSV chứa 680.000 khoản vay — từ ngày giải ngân, số tiền, lãi suất, trạng thái trả nợ, đến thông tin khách hàng.
Tùng làm theo quy trình quen thuộc: pd.read_csv(), dropna(), groupby(), tính trung bình, tính tỷ lệ nợ xấu, xuất biểu đồ. Tổng thời gian: 3 tiếng. Báo cáo đẹp, slide sạch, số liệu rõ ràng.
Kết luận chính của Tùng: "Tỷ lệ nợ xấu toàn danh mục là 2.1% — nằm trong ngưỡng an toàn. Khuyến nghị: mở rộng cho vay."
Sếp Tùng — chị Mai, Head of Product — nhìn báo cáo 30 giây rồi hỏi: "Tùng ơi, 2.1% là trung bình toàn danh mục. Nhưng phân bổ theo nhóm khách hàng thì sao? Có nhóm nào nợ xấu cao bất thường không?"
Tùng chưa kiểm tra. Anh quay lại dữ liệu, group theo customer_segment — và đứng hình.
Nhóm khách hàng "Freelancer" có tỷ lệ nợ xấu 12.7% — gấp 6 lần trung bình. Nhóm "Công nhân nhà máy" ở 8.3%. Hai nhóm này chỉ chiếm 15% tổng danh mục, nên khi tính trung bình chung, con số bị "pha loãng" xuống 2.1%.
Nếu sếp mang con số 2.1% đi pitch với ngân hàng đối tác, rồi đối tác kiểm tra lại phát hiện hai nhóm rủi ro cao — uy tín công ty sẽ bị ảnh hưởng nghiêm trọng.
Tùng toát mồ hôi lạnh. Anh nhắn cho Khoa — anh bạn Senior DA ở một công ty insurtech: "Khoa ơi, mình suýt report sai. Trung bình che giấu hết outlier."
Khoa trả lời: "Mày có EDA trước khi phân tích không?"
"EDA? Mình clean xong rồi nhảy vào tính luôn."
"Đó là vấn đề. EDA không phải bước phụ — nó là bước BẮT BUỘC. Giống như bác sĩ phải khám tổng quát trước khi phẫu thuật. Mày không khám mà cắt luôn — may mà phát hiện trước khi sếp đi pitch."
Phần 1: EDA — Khám tổng quát trước khi "phẫu thuật" dữ liệu
Khoa gọi video call tối hôm đó. Anh bắt đầu bằng một câu hỏi: "Trước khi mổ, bác sĩ làm gì?"
Tùng: "Khám tổng quát, xét nghiệm máu, chụp X-quang..."
Khoa: "Đúng. EDA chính là 'khám tổng quát' cho dataset. Mày cần biết bệnh nhân trước khi quyết định phẫu thuật gì. Dataset có phân phối thế nào? Có outlier không? Các biến quan hệ với nhau ra sao? Không biết những điều này mà nhảy vào phân tích — giống như bác sĩ nhắm mắt mổ."
Khoa hướng dẫn Tùng bắt đầu lại từ đầu — lần này có EDA đàng hoàng:
python
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv("loan_portfolio_q4.csv")
# Bước 1: Nhìn tổng quan — "sinh hiệu" của dataset
print(df.shape)
print(df.dtypes)
print(df.describe())
print(df.isnull().sum())"Bốn dòng code này giống như đo huyết áp, đo nhịp tim, đo nhiệt độ," Khoa ví von. "Chưa biết bệnh gì, nhưng biết bệnh nhân có khỏe không."
df.describe() cho Tùng thấy ngay điều anh bỏ qua lần trước: cột loan_amount có min = 500.000đ và max = 2.8 tỷ. Mean là 15 triệu, nhưng median chỉ 8 triệu — phân phối bị skew phải rất nặng. Và cột interest_rate có giá trị max = 89% — rõ ràng là data entry error.
EDA = Khám sức khỏe tổng quát
Hãy nghĩ EDA như quy trình khám tổng quát trước khi phẫu thuật:
df.shape→ Cân nặng, chiều cao bệnh nhândf.describe()→ Đo huyết áp, nhịp tim, nhiệt độdf.isnull().sum()→ Tìm vết thương chưa được xử lý- Distribution plot → Chụp X-quang
- Correlation matrix → Xét nghiệm máu tổng hợp
Bỏ qua bước nào cũng như bác sĩ "mổ mù" — may thì không sao, xui thì hậu quả nghiêm trọng.
Tùng bắt đầu hiểu. Lần trước anh nhảy thẳng vào groupby().mean() mà không bao giờ nhìn phân phối. Con số trung bình 2.1% đẹp đẽ kia che giấu một sự thật kinh khủng bên dưới — giống như đo nhiệt độ trung bình toàn thân là 37°C, nhưng chân thì 35°C và đầu thì 40°C.
Phần 2: Univariate → Bivariate — Từ một biến đến mối quan hệ
Khoa nói: "EDA có ba tầng. Tầng 1: nhìn từng biến riêng — univariate. Tầng 2: nhìn quan hệ giữa hai biến — bivariate. Tầng 3: nhìn nhiều biến cùng lúc — multivariate. Mày phải đi theo thứ tự, không được nhảy cóc."
Tầng 1 — Univariate:
Tùng vẽ distribution cho cột loan_amount:
python
# Univariate: phân phối số tiền vay
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Histogram
axes[0].hist(df['loan_amount'], bins=50, edgecolor='black', alpha=0.7)
axes[0].set_title('Phân phối số tiền vay')
axes[0].set_xlabel('Số tiền (VNĐ)')
axes[0].axvline(df['loan_amount'].mean(), color='red', linestyle='--', label='Mean')
axes[0].axvline(df['loan_amount'].median(), color='green', linestyle='--', label='Median')
axes[0].legend()
# Boxplot
axes[1].boxplot(df['loan_amount'], vert=True)
axes[1].set_title('Boxplot — Phát hiện Outliers')
plt.tight_layout()
plt.show()Biểu đồ hiện ra — và Tùng thấy rõ: phân phối bị kéo dài sang phải, có một cụm outlier phía trên 500 triệu. Đây là những khoản vay doanh nghiệp nhỏ bị lẫn vào danh mục vay tiêu dùng. Lần trước Tùng tính trung bình mà không loại bỏ nhóm này — nên mean bị kéo lên, che giấu bức tranh thật.
Mean vs Median — Khi trung bình nói dối
Ở Việt Nam, thu nhập bình quân đầu người 2025 khoảng 4.600 USD/năm. Nhưng median (trung vị) thấp hơn nhiều — vì một nhóm nhỏ thu nhập rất cao kéo mean lên. Tương tự, khi dữ liệu bị skew, median đáng tin hơn mean. EDA giúp bạn phát hiện điều này — nếu mean và median khác nhau nhiều, phân phối đang bị lệch.
Tầng 2 — Bivariate:
Tùng tiếp tục khám phá mối quan hệ giữa customer_segment và default_rate:
python
# Bivariate: tỷ lệ nợ xấu theo segment
segment_stats = df.groupby('customer_segment').agg(
total_loans=('loan_id', 'count'),
default_rate=('is_default', 'mean'),
avg_amount=('loan_amount', 'median')
).sort_values('default_rate', ascending=False)
print(segment_stats)
# Visualization
fig, ax = plt.subplots(figsize=(10, 6))
colors = ['#e74c3c' if x > 0.05 else '#2ecc71' for x in segment_stats['default_rate']]
segment_stats['default_rate'].plot(kind='barh', color=colors, ax=ax)
ax.set_title('Tỷ lệ nợ xấu theo phân khúc khách hàng')
ax.set_xlabel('Tỷ lệ nợ xấu')
ax.axvline(x=0.05, color='red', linestyle='--', label='Ngưỡng cảnh báo (5%)')
ax.legend()
plt.tight_layout()
plt.show()Biểu đồ hiện rõ mồn một: Freelancer (12.7%) và Công nhân nhà máy (8.3%) nổi bật đỏ lòm giữa một dãy xanh. Lần trước, Tùng đã không bao giờ nhìn thấy điều này vì anh tính trung bình chung rồi kết luận luôn.
Khoa nhận xét: "Airbnb cũng từng gặp chuyện tương tự. Team Data của họ EDA trên listing data và phát hiện pricing anomalies — có các host đặt giá $1/đêm hoặc $10.000/đêm, kéo lệch toàn bộ phân tích giá trung bình theo khu vực. Nếu không EDA, họ sẽ đưa ra pricing recommendation sai cho hàng triệu host."
Phần 3: Visualization — Ngôn ngữ của EDA
Tùng bắt đầu nhận ra: mấu chốt của EDA không chỉ là code — mà là nhìn. John Tukey, cha đẻ EDA, nói: "The greatest value of a picture is when it forces us to notice what we never expected to see." — biểu đồ tốt buộc bạn nhìn thấy điều bạn không ngờ tới.
Khoa hướng dẫn Tùng bước cuối: multivariate analysis với correlation matrix.
python
# Multivariate: Correlation matrix
numeric_cols = df.select_dtypes(include='number').columns
corr_matrix = df[numeric_cols].corr()
plt.figure(figsize=(10, 8))
sns.heatmap(corr_matrix, annot=True, cmap='RdBu_r', center=0,
fmt='.2f', square=True, linewidths=0.5)
plt.title('Ma trận tương quan — Mối quan hệ giữa các biến số')
plt.tight_layout()
plt.show()Kết quả cho thấy: income và default_rate có tương quan âm mạnh (−0.42) — thu nhập thấp thì khả năng nợ xấu cao hơn. Nhưng bất ngờ hơn: number_of_previous_loans có tương quan dương nhẹ (+0.18) với default_rate — khách hàng vay nhiều lần không nhất thiết "đáng tin" hơn, mà có thể đang "vay đảo nợ."
Tùng trước đó tin rằng khách hàng cũ là khách hàng tốt. Correlation matrix phá vỡ giả định đó.
"Spotify cũng dùng EDA như vậy," Khoa kể thêm. "Trước khi build recommendation model, team Data EDA listening patterns — họ phát hiện một nhóm users nghe nhạc lúc 2-4 giờ sáng với pattern rất khác (nghe đi nghe lại 1 bài). Hóa ra đó là người dùng để chế độ repeat khi ngủ — nếu không EDA, model sẽ recommend sai cho nhóm này."
EDA trước Model — Nguyên tắc vàng
Trong quy trình OSEMN, EDA (Explore) đứng trước Model có lý do:
- EDA phát hiện outlier → quyết định loại bỏ hay giữ
- EDA phát hiện skewness → quyết định dùng mean hay median
- EDA phát hiện correlation → quyết định feature nào đưa vào model
- EDA phát hiện data quality issues → quay lại bước Scrub
Bỏ qua EDA = xây nhà trên nền không khảo sát. Có thể đứng vững, nhưng xác suất sập rất cao.
Tùng viết lại báo cáo. Lần này, anh thêm phần Distribution Analysis, Segment Breakdown, và Correlation Insights. Kết luận mới: "Tỷ lệ nợ xấu trung bình 2.1%, nhưng phân bổ không đều — nhóm Freelancer (12.7%) và Công nhân nhà máy (8.3%) cần chính sách riêng. Khuyến nghị: mở rộng cho vay có chọn lọc, siết điều kiện với hai nhóm rủi ro cao."
Chị Mai đọc báo cáo mới, gật đầu: "Bây giờ mới là insight thật. Cái này mới thuyết phục được đối tác."
Phần 4: EDA Summary — Viết insight cho người không biết code
Khoa dặn thêm: "EDA không chỉ dừng ở biểu đồ. Mày phải viết EDA Summary — tóm tắt bằng ngôn ngữ business. Sếp mày không đọc code, sếp đọc insight."
Tùng học cách viết EDA summary theo format chuẩn:
python
# Template EDA Summary
eda_summary = """
=== EDA SUMMARY: Loan Portfolio Q4/2025 ===
1. DATASET OVERVIEW
- Records: 680,000 | Features: 18 | Period: Oct-Dec 2025
- Missing values: 2.3% (chủ yếu cột income_verified)
2. KEY DISTRIBUTIONS
- loan_amount: Right-skewed (mean 15M, median 8M)
- interest_rate: 1 outlier at 89% (data entry error → removed)
3. SEGMENT INSIGHTS
- Freelancer segment: 12.7% default rate (vs 2.1% avg) ⚠️
- Factory Worker segment: 8.3% default rate ⚠️
- Salaried Employee: 1.2% default rate ✅
4. CORRELATIONS
- income ↔ default_rate: -0.42 (strong negative)
- previous_loans ↔ default_rate: +0.18 (weak positive — ⚠️ unexpected)
5. RECOMMENDATIONS
- Tighten criteria for Freelancer & Factory Worker segments
- Investigate "frequent borrower" pattern (possible debt cycling)
- Remove outlier interest_rate records before modeling
"""
print(eda_summary)Từ hôm đó, Tùng thay đổi quy trình hoàn toàn. Trước khi viết bất kỳ dòng groupby nào, trước khi tính bất kỳ con số nào — anh dành ít nhất 30 phút EDA. Univariate, bivariate, correlation matrix, viết summary. Chậm hơn 30 phút ở đầu, nhưng tiết kiệm hàng giờ phân tích sai hướng.
"10 phút EDA đầu tư ở đầu = 10 giờ không bị lạc đường ở sau," Tùng viết lên sticky note dán cạnh màn hình — ngay cạnh dòng chữ cũ "Automation over manual" mà anh học được từ Pandas.
Kết luận
Tùng không phải DA giỏi nhất. Nhưng sau sự cố tháng trước, anh trở thành DA cẩn thận nhất — người luôn EDA trước khi kết luận.
EDA không phải kỹ thuật cao siêu. Nó là df.describe(), là histogram, là boxplot, là heatmap. Nhưng sức mạnh của nó nằm ở tư duy: không tin vào con số bề mặt, không vội kết luận, và luôn để dữ liệu tự kể chuyện trước khi bạn kể cho sếp.
Nếu bạn đang phân tích mà chưa EDA — hãy dừng lại. Dành 10 phút. Vẽ vài biểu đồ. Nhìn phân phối. Kiểm tra outlier. Xem correlation. Rồi hãy tiếp tục.
Vì con số trung bình — đôi khi nó nói dối.
Điểm chính cần nhớ
- EDA là bước bắt buộc trước mọi phân tích — giống khám tổng quát trước khi phẫu thuật. Bỏ qua EDA là "mổ mù" — may thì ra kết quả đúng, xui thì kết luận sai hoàn toàn.
- Univariate → Bivariate → Multivariate — đi theo thứ tự: xem từng biến, rồi cặp biến, rồi nhiều biến. Không nhảy cóc.
- Mean có thể nói dối — khi dữ liệu bị skew hoặc có outlier, median đáng tin hơn. Distribution plot giúp phát hiện điều này ngay lập tức.
- Visualization là ngôn ngữ của EDA — histogram, boxplot, scatter plot, heatmap. Biểu đồ tốt buộc bạn nhìn thấy điều bạn không ngờ tới.
- Correlation ≠ Causation — tương quan giữa hai biến không có nghĩa biến này gây ra biến kia. EDA giúp bạn phát hiện mối quan hệ, nhưng cần phân tích sâu hơn để hiểu nguyên nhân.
- EDA Summary — kết thúc EDA bằng bản tóm tắt viết bằng ngôn ngữ business. Sếp không đọc code, sếp đọc insight.
- 10 phút EDA = 10 giờ không lạc hướng — đầu tư nhỏ ở đầu, tiết kiệm lớn ở sau. Luôn để dữ liệu tự kể chuyện trước khi bạn kể cho người khác.