Đối soát KPI giữa file nguồn và dashboard bằng AI với pandas
Quy trình đối soát KPI có thể lặp lại: chuẩn hóa grain, join an toàn bằng pandas, phát hiện khóa thiếu hoặc dư, kiểm tra chênh lệch và dùng AI để hỗ trợ diễn giải dựa trên bằng chứng.
Một KPI trên dashboard lệch với file nguồn chưa chắc là lỗi tính toán. Nguyên nhân có thể nằm ở phạm vi ngày, bộ lọc nghiệp vụ, mã danh mục không đồng nhất, dữ liệu bị nhân dòng khi join — hoặc các khóa rỗng đã vô tình ghép với nhau.
Thay vì dò từng ô Excel rồi đối chiếu thủ công với SQL hoặc DAX, hãy biến câu hỏi “vì sao số không khớp?” thành một bảng chênh lệch có khóa, nguồn gốc và quy trình kiểm tra rõ ràng.
Với pandas, merge() giúp tìm cả bản ghi thiếu, bản ghi dư và giá trị lệch. AI có thể hỗ trợ rà câu hỏi cần kiểm tra và viết biên bản, nhưng không thay bạn xác nhận định nghĩa KPI hay logic dữ liệu.
Bắt đầu từ grain, không phải từ câu lệnh join
Trước khi viết merge, hãy xác định grain — cấp độ chi tiết của một dòng dữ liệu.
Ví dụ, một KPI có thể được tổng hợp theo:
ngay + kenh;
ngay + khuvuc + kenh;
hoặc từng madon.
Chỉ nên so sánh trực tiếp hai bảng khi chúng cùng grain. Nếu dashboard đang ở cấp ngày và kênh, còn file nguồn ở cấp đơn hàng, cần tổng hợp file nguồn về cùng cấp trước.
Bảng đối soát tối thiểu có thể có dạng:
| ngay | kenh | kpinguon | kpidashboard |
|---|---|---:|---:|
| <ngày> | A | 5 | 5 |
| <ngày> | B | 3 | 4 |
| <ngày> | C | 2 | |
| <ngày> | D | | 1 |
Trước khi kết luận có chênh lệch, hãy xác nhận hai bên cùng:
phạm vi ngày và múi giờ;
bộ lọc trạng thái, khu vực hoặc kênh;
quy tắc mapping danh mục;
cách xử lý giá trị thiếu;
cấp độ tổng hợp.
> Lưu ý: Khi không chỉ định khóa, DataFrame.merge() sẽ dùng các tên cột xuất hiện ở cả hai DataFrame làm khóa join. Với đối soát KPI, nên chỉ định rõ on, hoặc lefton và righton, để tránh join nhầm trên các cột trùng tên.
Dùng merge() để thấy khóa thiếu, khóa dư và KPI lệch
DataFrame.merge() thực hiện phép join theo kiểu cơ sở dữ liệu. Trong bài toán đối soát, how="outer" thường phù hợp vì giữ hợp các khóa từ cả file nguồn và dashboard.
Kết hợp indicator, pandas thêm một cột cho biết mỗi dòng xuất hiện từ đâu:
both: khóa có ở cả hai bảng;
leftonly: chỉ có ở bảng bên trái;
rightonly: chỉ có ở bảng bên phải.
Giả sử hai DataFrame đã cùng grain và dùng khóa ngay, kenh:
python
doisoat = dfnguon.merge(
dfdashboard,
how="outer",
on=["ngay", "kenh"],
suffixes=("nguon", "dashboard"),
indicator="nguondong",
validate="onetoone"
)
Đọc kết quả theo ba nhóm:
nguondong != "both": khóa chỉ có ở một phía, tức có khả năng thiếu hoặc dư bản ghi.
nguondong == "both" nhưng KPI khác nhau: cùng khóa, khác giá trị.
Các dòng có khóa rỗng: cần kiểm tra riêng trước khi diễn giải.
Đặt hậu tố "nguon" và "dashboard" giúp phân biệt các cột trùng tên rõ hơn so với hậu tố mặc định "x" và "y".
Chặn lỗi nhân dòng bằng validate
Một join sai có thể làm KPI tăng lên mà không báo lỗi rõ ràng. Chẳng hạn, nếu một khóa xuất hiện nhiều lần ở cả hai bảng, phép join nhiều-nhiều có thể tạo thêm các tổ hợp dòng.
Tham số validate cho phép pandas kiểm tra kỳ vọng về quan hệ khóa:
python
validate="onetoone"
Giá trị này yêu cầu khóa join là duy nhất ở cả hai DataFrame. Nếu một bên có khóa lặp, pandas sẽ báo lỗi thay vì tiếp tục tạo kết quả join không đúng với giả định một-một.
Các lựa chọn khác gồm:
onetomany hoặc 1:m: khóa duy nhất ở bảng bên trái;
manytoone hoặc m:1: khóa duy nhất ở bảng bên phải;
manytomany hoặc m:m: cho phép nhiều-nhiều nhưng không thực hiện kiểm tra.
Đừng dùng manytomany chỉ để câu lệnh chạy được. Nếu đây không phải quan hệ dữ liệu được thiết kế từ đầu, cần quay lại kiểm tra grain hoặc bước tổng hợp.
Cẩn thận với khóa NULL
Tài liệu pandas lưu ý một điểm khác với SQL thông thường: nếu khóa join ở cả hai phía cùng là giá trị rỗng (NULL/NaN), merge() có thể ghép các dòng đó với nhau.
Điều này có thể tạo ra kết quả không mong muốn trong đối soát KPI. Một kenh rỗng ở file nguồn không tự động tương đương với một kenh rỗng trong dashboard.
Hãy tách và rà riêng các dòng thiếu khóa trước khi join hoặc trước khi kết luận:
python
cotkhoa = ["ngay", "kenh"]
nguonthieukhoa = dfnguon[dfnguon[cotkhoa].isna().any(axis=1)]
dashboardthieukhoa = dfdashboard[dfdashboard[cotkhoa].isna().any(axis=1)]
Nếu tên khóa khác nhau giữa hai bảng, dùng lefton và righton để thể hiện mapping một cách minh bạch:
python
doisoat = dfnguon.merge(
dfdashboard,
how="outer",
lefton=["ngay", "makenhnguon"],
righton=["ngay", "channeldashboard"],
suffixes=("nguon", "dashboard"),
indicator="nguondong",
validate="onetoone"
)
Đây là lúc cần xác nhận: hai trường có tên gần giống nhau có thực sự cùng ý nghĩa nghiệp vụ hay không?
Dùng AI để hỗ trợ điều tra, không để “phán” nguyên nhân
Sau khi có bảng doisoat, AI hữu ích nhất như một trợ lý phân tích:
gợi ý thứ tự kiểm tra SQL, DAX hoặc pipeline;
tách bạch giả thuyết và bằng chứng;
cấu trúc biên bản gửi business;
nhắc các câu hỏi về filter, mapping và grain.
Chỉ nên cung cấp schema, định nghĩa KPI, dữ liệu mẫu đã ẩn danh và bảng tổng hợp chênh lệch. Không đưa dữ liệu khách hàng, dữ liệu cá nhân, mã đơn thật hoặc toàn bộ file nguồn vào công cụ AI công khai.
Prompt mẫu:
text
Bạn là trợ lý kiểm tra chất lượng dữ liệu.
KPI cần đối soát: <tên KPI>
Grain kỳ vọng: <khóa 1> + <khóa 2>
Logic nguồn: <mô tả SQL hoặc quy tắc nghiệp vụ>
Logic dashboard: <mô tả filter, measure và thời gian>
Schema bảng đối soát: <danh sách cột>
Các nhóm phát hiện:
leftonly: <mô tả đã ẩn danh>
rightonly: <mô tả đã ẩn danh>
both nhưng lệch KPI: <mô tả đã ẩn danh>
Hãy:
Nêu giả thuyết nguyên nhân và phân biệt với bằng chứng.
Đề xuất thứ tự kiểm tra SQL/DAX.
Soạn biên bản ngắn gồm phạm vi, phát hiện, nguyên nhân đã xác minh,
nguyên nhân chưa xác minh và hành động tiếp theo.
Không tự tạo tên cột hoặc khẳng định nguyên nhân khi chưa có bằng chứng.
Một phản hồi AI tốt nên dùng các cụm như “cần kiểm tra” hoặc “có thể do”, thay vì tự kết luận dashboard hoặc file nguồn sai.
Khóa kết quả bằng kiểm thử lặp lại
Sau khi sửa logic, hãy lưu một DataFrame kỳ vọng cho dữ liệu mẫu. pandas.testing.assertframeequal() dùng để kiểm tra hai DataFrame có bằng nhau hay không và báo khác biệt khi có.
python
from pandas.testing import assertframeequal
assertframeequal(
ketquathucte,
ketquakyvong,
checkdtype=False
)
Mặc định, hàm kiểm tra cả kiểu dữ liệu. checkdtype=False chỉ phù hợp khi bạn chủ đích bỏ qua khác biệt kiểu dữ liệu, chẳng hạn một cột là số nguyên ở một bảng và số thực ở bảng còn lại. Tùy chọn này không bỏ qua khác biệt về giá trị.
Nếu thứ tự dòng và cột không quan trọng, có thể dùng:
python
assertframeequal(
ketquathucte,
ketquakyvong,
checklike=True
)
Với checklike=True, pandas có thể bỏ qua thứ tự index và cột, nhưng nhãn vẫn phải đi cùng đúng dữ liệu.
Checklist trước khi gửi kết luận
[ ] Xác nhận cùng phạm vi ngày, múi giờ và bộ lọc nghiệp vụ.
[ ] Chuẩn hóa hai bảng về cùng grain.
[ ] Chỉ định rõ khóa join bằng on hoặc lefton/righton.
[ ] Dùng how="outer" và indicator để thấy khóa thiếu hoặc dư.
[ ] Dùng validate để kiểm tra quan hệ khóa.
[ ] Rà riêng các khóa NULL/NaN.
[ ] Đối chiếu cả tổng KPI lẫn từng dòng chênh với SQL hoặc DAX.
[ ] Lưu code, dữ liệu mẫu đã ẩn danh và biên bản đối soát để chạy lại.
Một dashboard đáng tin không chỉ hiển thị một con số hợp lý. Nó cần một đường kiểm tra có thể lặp lại để analyst trả lời rõ ràng: số này đến từ đâu, lệch ở đâu và cần kiểm tra tiếp điều gì.