Dữ liệu trùng lặp (Duplicates) là hiện tượng một bản ghi xuất hiện nhiều lần trong tập dữ liệu với thông tin hoàn toàn giống nhau trên tất cả các cột, hoặc giống nhau ở các thuộc tính định danh quan trọng.
Trước khi thực hiện bất kỳ thao tác xóa nào, nhà phân tích dữ liệu cần phân định rạch ròi hai loại trùng lặp có bản chất hoàn toàn khác nhau để tránh làm mất mát thông tin:
Trùng lặp cơ học/hệ thống (Lỗi dữ liệu): Đây là những nhiễu kỹ thuật phát sinh ngoài ý muốn. Nguyên nhân phổ biến có thể do lỗi gộp dữ liệu (merge) từ nhiều nguồn, lỗi nhập liệu nhiều lần, hoặc trong thương mại điện tử là do nghẽn mạng (Network Timeout) khiến khách hàng nhấp đúp (double-click) vào nút thanh toán. Việc tồn tại các bản ghi này sẽ làm sai lệch các thống kê tổng hợp (như thổi phồng doanh thu) và gây hiện tượng "học vẹt" (overfitting) cho các mô hình Học máy.
Trùng lặp hợp lệ (Hành vi thực tế): Xảy ra khi dữ liệu lặp lại một cách hợp lý theo logic kinh doanh. Ví dụ, trong tập dữ liệu tàu Titanic, nhiều hành khách trong cùng một gia đình có thể dùng chung một mã vé (Ticket) - đây là trùng lặp hợp lệ. Chỉ khi nào mã định danh cá nhân (PassengerId) bị trùng thì đó mới chắc chắn là lỗi hệ thống.
Tư duy chuẩn mực trong Data Science là không bao giờ xóa dữ liệu ngay lập tức khi vừa phát hiện trùng lặp. Thay vào đó, cần thực hiện thao tác "Đánh dấu" để kiểm tra chéo (Audit) và tìm hiểu nguyên nhân gốc rễ.
Thư viện Pandas cung cấp hàm df.duplicated() để quét và trả về giá trị True cho các dòng bị trùng lặp. Bằng cách sử dụng tham số keep=False, ta có thể hiển thị tất cả các bản ghi (bao gồm cả bản gốc và bản sao) để đối chiếu trực quan.
Tùy vào tình huống, Pandas hỗ trợ nhiều kỹ thuật xử lý khác nhau:
Xóa trùng lặp hoàn toàn: Dùng hàm df.drop_duplicates(). Mặc định với tham số keep='first', Pandas sẽ giữ lại dòng đầu tiên và xóa các bản sao phía sau.
Giữ bản cập nhật mới nhất: Nếu dữ liệu được sắp xếp theo thời gian và dòng xuất hiện sau là bản cập nhật mới nhất, ta dùng tham số keep='last' để giữ lại quan sát cuối cùng.
Xóa dựa trên một số cột (Subset): Khi dữ liệu chỉ cần duy nhất trên một trường định danh (như Mã khách hàng hay Mã hóa đơn), ta dùng subset=['Cột_Khóa'] để thanh lọc.
Gộp dữ liệu (Combine): Trong trường hợp các dòng trùng lặp mã định danh nhưng lại chứa các thông tin bổ sung khác nhau (do thu thập từ nhiều nguồn), thay vì xóa, ta có thể dùng groupby().agg() để gộp các giá trị lại (ví dụ: lấy trung bình chi tiêu, gộp chuỗi sở thích).
Để minh họa cho quy trình trên, chúng ta sử dụng PaySim Dataset – một bộ dữ liệu mô phỏng các giao dịch tài chính trên thiết bị di động (Mobile Money) với quy mô hơn 6,3 triệu bản ghi, được thiết kế chuyên biệt cho bài toán phát hiện gian lận (Fraud Detection).
Trong bối cảnh hệ thống thanh toán, nếu một giao dịch chuyển tiền (TRANSFER) hoặc rút tiền (CASH_OUT) bị lỗi mạng và ghi nhận lặp lại 2-3 lần, mô hình học máy có thể đánh giá sai quy mô của dòng tiền gian lận.
Dưới đây là đoạn mã mô phỏng một trích đoạn dữ liệu PaySim chứa lỗi hệ thống. Bạn có thể sao chép và chạy trực tiếp đoạn code này trên Google Colab để quan sát luồng xử lý:
import pandas as pd
# 1. TẠO TRÍCH ĐOẠN DỮ LIỆU PAYSIM MÔ PHỎNG LỖI TRÙNG LẶP
data_paysim = {
'step': [1, 2, 3, 4, 5], # 1 step = 1 giờ
'type': ['TRANSFER', 'TRANSFER', 'CASH_OUT', 'PAYMENT', 'PAYMENT'],
'amount': [181.0, 181.0, 181.0, 116.68, 116.68],
'nameOrig': ['C1305486145', 'C1305486145', 'C840083671', 'C712410124', 'C712410124'],
'isFraud': [0, 0, 1, 0, 0] # 1: Gian lận, 0: Hợp lệ
}
df_paysim = pd.DataFrame(data_paysim)
# 2. KIỂM TRA SỐ LƯỢNG TRÙNG LẶP
print("--- BƯỚC 1: KIỂM TRA SỐ LƯỢNG TRÙNG LẶP ---")
dup_count = df_paysim.duplicated().sum()
print(f"Tổng số giao dịch bị trùng lặp hệ thống: {dup_count}\n")
# 3. TƯ DUY AUDIT: ĐÁNH DẤU VÀ KIỂM TRA CHÉO
print("--- BƯỚC 2: KIỂM TRA CHI TIẾT CÁC DÒNG TRÙNG LẶP ---")
# Tham số keep=False hiển thị cả bản gốc và bản sao để đối chiếu
df_paysim['is_duplicate'] = df_paysim.duplicated(keep=False)
print(df_paysim[df_paysim['is_duplicate'] == True])
print("\n")
# 4. LÀM SẠCH: KHỬ TRÙNG LẶP (DEDUPLICATION)
print("--- BƯỚC 3: KẾT QUẢ SAU KHI LÀM SẠCH ---")
# Bỏ cột audit và xóa dòng trùng lặp, giữ lại giao dịch đầu tiên
df_clean = df_paysim.drop(columns=['is_duplicate']).drop_duplicates(keep='first')
print(f"Số giao dịch ban đầu: {len(df_paysim)}")
print(f"Số giao dịch hợp lệ sau làm sạch: {len(df_clean)}")
print("\nDữ liệu tinh khiết:")
print(df_clean)
💡 Insights và Ý nghĩa quản trị: Việc khử trùng lặp trong dữ liệu tài chính không chỉ để "làm nhẹ" máy chủ mà mang ý nghĩa sống còn về mặt nghiệp vụ. Trong bộ dữ liệu PaySim, tỷ lệ gian lận thực tế chỉ chiếm chưa tới 0,6% tổng số giao dịch. Nếu để lọt các giao dịch gian lận bị nhân bản do lỗi kỹ thuật, mô hình học máy sẽ gặp hiện tượng "quá khớp" (Overfitting) – học thuộc lòng một vài mẫu gian lận lặp đi lặp lại thay vì học quy luật tổng quát. Xử lý triệt để Duplicate Values là bức tường lửa bảo vệ tính toàn vẹn của mô hình cảnh báo sớm, giúp các định chế tài chính định lượng chính xác thiệt hại và tránh khóa nhầm tài khoản của khách hàng do các cảnh báo rủi ro ảo.