Skip to content

📝 1 triệu dòng? Pandas xử lý trong 3 giây

Mở đầu — "File Excel 800.000 dòng, máy đơ 15 phút, rồi crash."

Hùng, 28 tuổi, Data Analyst tại phòng Quản trị rủi ro của một ngân hàng thương mại ở Hà Nội — loại ngân hàng top 10, hàng triệu khách hàng, mỗi ngày phát sinh hàng trăm nghìn giao dịch.

Hùng không dở. Anh tốt nghiệp Ngoại Thương, vào ngân hàng từ vị trí chuyên viên phân tích, được đánh giá cao nhờ khả năng "thuần phục" Excel. Pivot Table lồng nhau 3 tầng? Được. VLOOKUP kết hợp INDEX-MATCH qua 5 sheet? Dễ. Power Query kéo dữ liệu từ 12 file CSV? Hùng làm mắt nhắm mắt mở.

Nhưng tháng 1 năm nay, mọi thứ sụp đổ.

Phòng Quản trị rủi ro nhận yêu cầu từ ban lãnh đạo: phân tích toàn bộ giao dịch năm 2025 để đánh giá mức độ rủi ro tín dụng. File dữ liệu được IT gửi sang — một file CSV chứa 3,2 triệu dòng giao dịch. Hùng mở file bằng Excel.

Chờ 5 phút. Thanh loading chạy được 40%. Chờ thêm 10 phút. Excel hiện thông báo "Not Responding". Hùng kiên nhẫn chờ. Phút thứ 18 — crash. File đóng sập. Không lưu được gì.

Hùng thử lại. Lần này anh chia file thành 4 phần nhỏ, mỗi phần 800.000 dòng. File đầu tiên mở được, nhưng mỗi thao tác filter mất 30 giây. Kéo Pivot Table — đợi 2 phút. Thêm một cột tính toán — Excel đơ thêm 1 phút. Và khi Hùng cố VLOOKUP sang file danh sách khách hàng 200.000 dòng... crash lần hai.

Hùng nhìn đồng hồ: 4 giờ chiều. Deadline báo cáo: ngày mai 9 giờ sáng. Anh đã mất cả buổi chiều mà chưa bắt đầu phân tích được gì. Trên bàn, ly cà phê thứ ba đã nguội ngắt.

Anh nhắn tin cho Trang — cô bạn cùng khóa MBA, giờ làm DA tại một công ty fintech: "Trang ơi, file 3 triệu dòng, Excel chết. Có cách nào không?"

Trang trả lời đúng 4 chữ: "Dùng Pandas đi."

Hùng biết Python cơ bản — anh vừa học xong tuần trước: biến, vòng lặp, hàm, đọc file. Nhưng Pandas thì anh chỉ nghe tên chứ chưa bao giờ dùng. Trong đầu anh, Pandas là thứ gì đó "dành cho dân lập trình".

Trang gửi cho Hùng đúng 3 dòng code:

python
import pandas as pd
df = pd.read_csv("giao_dich_2025.csv")
print(df.shape)

"Chạy thử đi. File 3 triệu dòng."

Hùng copy, paste, nhấn Run. 3 giây. Terminal hiện: (3200000, 15) — 3,2 triệu dòng, 15 cột. Không crash. Không đơ. Ba. Giây.

Hùng ngồi im vài giây, cảm giác giống như lần đầu tiên học được phím tắt Ctrl+C — thế giới bỗng khác đi.

Phần 1: DataFrame — Bảng tính thông minh tự biết đọc hiểu dữ liệu

Trang giải thích cho Hùng qua video call tối hôm đó. Cô nói: "Mày hình dung DataFrame giống bảng tính Excel, nhưng thông minh hơn. Nó tự biết cột nào là số, cột nào là chữ, cột nào là ngày tháng. Mày không cần format bằng tay."

Hùng bắt đầu khám phá. Anh gõ df.head() — 5 dòng đầu tiên hiện ra gọn gàng, có tên cột, có index. Gõ df.info() — Pandas liệt kê từng cột: cột so_tien là float64, cột ngay_giao_dich là object (cần chuyển sang datetime), cột ma_khach_hang là string. Excel không bao giờ nói cho Hùng biết những điều này — anh phải tự mở từng cột ra kiểm tra.

python
# Xem tổng quan dữ liệu
print(df.info())
print(df.describe())

# Lọc giao dịch trên 50 triệu
df_lon = df[df["so_tien"] > 50_000_000]
print(f"Có {len(df_lon)} giao dịch trên 50 triệu")

Điều khiến Hùng ngạc nhiên nhất: tốc độ. Lọc 3,2 triệu dòng theo điều kiện — chưa đến 1 giây. Ở Excel, filter 800.000 dòng đã mất 30 giây.

DataFrame vs Excel Sheet

DataFrame giống như bảng tính Excel đã được "nâng cấp não". Nó tự nhận diện kiểu dữ liệu, cho phép lọc bằng một dòng code thay vì kéo chuột, và quan trọng nhất — nó không crash khi dữ liệu lớn. Nếu Excel là xe máy, DataFrame là ô tô — cùng đi từ A đến B, nhưng khi đường dài và hàng nặng, bạn biết nên chọn gì.

Hùng học thêm về lociloc — hai cách truy cập dữ liệu mà Excel không có tương đương trực tiếp. loc truy cập theo nhãn (tên cột, điều kiện), iloc truy cập theo vị trí (số thứ tự). Giống như trong thư viện: loc là tìm sách theo tên, iloc là tìm sách theo số kệ.

python
# loc: lọc theo điều kiện — giống filter Excel nhưng nhanh hơn 100 lần
df.loc[df["loai_giao_dich"] == "rut_tien", ["ma_khach_hang", "so_tien"]]

# iloc: lấy 10 dòng đầu, 3 cột đầu — giống chọn vùng trong Excel
df.iloc[:10, :3]

Trang kể: "Trong quy trình OSEMN — Obtain, Scrub, Explore, Model, iNterpret — bước đầu tiên là nạp dữ liệu vào. Pandas chính là công cụ cho bước Obtain. Mày vừa hoàn thành bước 1 trong 3 giây, trong khi Excel không qua nổi bước đó."

Hùng gật đầu. Lần đầu tiên anh hiểu vì sao người ta nói Excel có giới hạn — không phải Excel dở, mà là dữ liệu đã lớn hơn khả năng Excel chịu được.

Phần 2: Dọn dẹp dữ liệu — Dọn nhà trước khi mời khách

Hùng hào hứng muốn nhảy thẳng vào phân tích, nhưng Trang ngăn lại: "Khoan. Mày phải dọn dữ liệu trước. Dữ liệu bẩn mà phân tích thì kết quả cũng bẩn. Giống như mời khách đến nhà mà không dọn — khách ngồi vào ghế dính bụi, ấn tượng hỏng hết."

Hùng gõ df.isnull().sum() — và giật mình. Cột so_tien12.000 giá trị NaN — tức 12.000 giao dịch không ghi số tiền. Cột chi_nhanh thiếu 8.500 giá trị. Cột ngay_giao_dich thiếu 200 giá trị.

Missing Values = Ổ gà trên đường

Hình dung dữ liệu là con đường bạn đang lái xe. Missing values (NaN) chính là những ổ gà. Ít ổ gà thì bạn tránh được. Nhưng nếu cả đoạn đường đầy ổ gà, bạn phải quyết định: lấp lại (fill), đi đường khác (drop), hay chấp nhận xóc (giữ nguyên và ghi chú). Không có cách nào "đúng" cho mọi trường hợp — bạn phải hiểu ngữ cảnh.

Trang hướng dẫn Hùng xử lý từng loại:

python
# Kiểm tra missing values
print(df.isnull().sum())

# Xóa dòng thiếu ngày giao dịch (chỉ 200 dòng — bỏ được)
df = df.dropna(subset=["ngay_giao_dich"])

# Điền số tiền bị thiếu bằng median (an toàn hơn mean vì không bị ảnh hưởng bởi outlier)
df["so_tien"] = df["so_tien"].fillna(df["so_tien"].median())

# Xóa dòng trùng lặp
print(f"Trước: {len(df)} dòng")
df = df.drop_duplicates()
print(f"Sau: {len(df)} dòng")

Kết quả: 45.000 dòng trùng lặp bị loại bỏ. Hùng nhớ lại — ở Excel, anh từng dùng Conditional Formatting để tô màu dòng trùng rồi xóa bằng tay. Mất 2 tiếng cho 200.000 dòng. Pandas làm trong 0.5 giây cho 3,2 triệu dòng.

Bước "Scrub" trong OSEMN — bước mà ai cũng ngại nhưng chiếm tới 60-80% thời gian của một DA — giờ đây trở nên... gần như tự động. Hùng bắt đầu hiểu vì sao nguyên tắc "Tidy Data" lại quan trọng: mỗi biến một cột, mỗi quan sát một dòng, mỗi loại dữ liệu một bảng. Khi dữ liệu đã "tidy", mọi thao tác sau đó đều nhanh và chính xác hơn.

Hùng còn phát hiện ra .apply() — hàm cho phép áp dụng một logic tùy chỉnh lên toàn bộ cột. Anh cần phân loại giao dịch theo mức độ rủi ro: dưới 10 triệu là "thấp", 10-100 triệu là "trung bình", trên 100 triệu là "cao".

Ở Excel, Hùng sẽ viết IF lồng nhau: =IF(A2>100000000,"cao",IF(A2>10000000,"trung bình","thấp")) rồi kéo xuống 3 triệu dòng — Excel sẽ đơ ít nhất 5 phút. Với Pandas:

python
def phan_loai_rui_ro(so_tien):
    if so_tien > 100_000_000:
        return "cao"
    elif so_tien > 10_000_000:
        return "trung_binh"
    else:
        return "thap"

df["muc_rui_ro"] = df["so_tien"].apply(phan_loai_rui_ro)
print(df["muc_rui_ro"].value_counts())

2 giây. Xong. Hùng bật cười — cái mà anh sợ nhất ở Excel lại là cái dễ nhất trong Pandas.

Phần 3: Ghép dữ liệu — Khi hai cuốn sổ trở thành một

Đến đây, Hùng đã có bảng giao dịch sạch. Nhưng báo cáo yêu cầu thêm thông tin khách hàng: tên, tuổi, hạn mức tín dụng, chi nhánh quản lý. Thông tin này nằm ở file kháckhach_hang.csv với 450.000 dòng.

Ở Excel, Hùng sẽ dùng VLOOKUP. Với 800.000 dòng, VLOOKUP mất khoảng 30 phút — mỗi ô phải tìm kiếm trong 450.000 dòng bảng tham chiếu. Với 3 triệu dòng? Hùng không dám nghĩ.

Trang nói: "Dùng merge. Giống như mày có hai cuốn sổ liên lạc — một cuốn ghi số điện thoại, một cuốn ghi địa chỉ. Merge là ghép hai cuốn thành một dựa trên tên người. Nhanh hơn VLOOKUP vì Pandas dùng thuật toán hash — giống như đánh index trong SQL ấy."

python
# Đọc file khách hàng
df_kh = pd.read_csv("khach_hang.csv")

# Merge — giống VLOOKUP nhưng nhanh gấp 600 lần
df_full = df.merge(df_kh, on="ma_khach_hang", how="left")
print(f"Bảng gộp: {df_full.shape}")

4 giây. Hùng nhớ lại deadline sáng mai 9 giờ. Giờ mới 9 giờ tối. Anh đã có bảng dữ liệu đầy đủ — sạch, gộp, sẵn sàng phân tích. Ở bất kỳ ngày nào trước đây, đến bước này anh đã mất ít nhất một ngày rưỡi chỉ để mở file, dọn dữ liệu, và VLOOKUP.

Trang hướng dẫn thêm concat — dùng khi cần xếp chồng dữ liệu cùng cấu trúc, ví dụ ghép giao dịch tháng 1 với tháng 2:

python
# Concat — xếp chồng dữ liệu cùng cấu trúc
df_q1 = pd.read_csv("giao_dich_q1.csv")
df_q2 = pd.read_csv("giao_dich_q2.csv")
df_full_year = pd.concat([df_q1, df_q2], ignore_index=True)

"Merge là ghép ngang — thêm cột. Concat là ghép dọc — thêm dòng. Nhớ hai cái này là đủ xử lý 90% nhu cầu ghép dữ liệu," Trang tóm gọn.

Đến 10 giờ tối, Hùng đã hoàn thành toàn bộ phân tích. Anh xuất kết quả ra file Excel để gửi sếp (vâng, sếp vẫn thích đọc Excel) bằng một dòng: df_full.to_excel("bao_cao_rui_ro.xlsx", index=False). Tổng thời gian từ lúc bắt đầu đến lúc xong: 2 tiếng — bao gồm cả thời gian học Pandas từ đầu.

So với cách cũ: 2 ngày. Và lần sau — khi code đã viết sẵn — chỉ cần chạy lại, thay tên file. 30 giây.

Kết luận

Hùng không bỏ Excel. Anh vẫn dùng Excel để xem nhanh file nhỏ, trình bày cho sếp, hay ghi chú vài con số. Nhưng kể từ đêm hôm đó, mỗi khi dữ liệu vượt quá 100.000 dòng, mỗi khi cần dọn dẹp, ghép bảng, hay lặp lại quy trình — Hùng mở Python và gọi Pandas.

Automation over manual — đó là nguyên tắc Hùng viết lên sticky note dán cạnh màn hình. Không phải vì làm tay là sai. Mà vì thời gian của bạn đáng giá hơn việc ngồi chờ Excel xoay vòng loading.

Nếu bạn đang ở vị trí của Hùng — giỏi Excel nhưng bắt đầu cảm thấy bị giới hạn — thì Pandas không phải "thay thế" Excel. Nó là bước tiến hóa tiếp theo. Và bước đầu tiên chỉ cần 3 dòng code: import pandas as pd.

Điểm chính cần nhớ

  • DataFrame là bảng tính thông minh — tự nhận diện kiểu dữ liệu, xử lý hàng triệu dòng không crash, và cho phép lọc/tính toán bằng một dòng code.
  • Missing values (NaN) là "ổ gà" trong dữ liệu — cần phát hiện (isnull), rồi quyết định xóa (dropna) hoặc điền (fillna) dựa trên ngữ cảnh.
  • Data cleaning chiếm 60-80% thời gian DA — Pandas tự động hóa bước này với drop_duplicates, fillna, apply, giúp giảm từ hàng giờ xuống vài giây.
  • Merge (ghép ngang) và concat (ghép dọc) thay thế VLOOKUP — nhanh hơn hàng trăm lần khi dữ liệu lớn, và không bao giờ crash.
  • OSEMN framework (Obtain → Scrub → Explore → Model → iNterpret) giúp bạn đi đúng trình tự — Pandas mạnh nhất ở bước Obtain và Scrub.
  • Tidy Data — mỗi biến một cột, mỗi quan sát một dòng — là nền tảng để mọi thao tác phân tích sau đó trở nên dễ dàng.
  • Automation over manual — viết code một lần, chạy lại mãi mãi. Thời gian của bạn đáng giá hơn việc kéo chuột lặp lại.