Thiết kế Pipeline Kiểm tra Tính hợp lệ & Làm sạch Dữ liệu Khai báo
Trong các hệ thống Data Lakehouse hiện đại, dữ liệu thô (Raw Data) từ nhiều nguồn thứ ba gửi về thường chứa lỗi: thiếu trường, sai định dạng email/SĐT, số âm vô lý, hoặc trùng lặp…
Tiến độ của tôi ở bài này
Điểm được lưu vào tài khoản sau khi chấm bài.
Đang tải điểm của bạn…
Kiến thức và chủ đề
Kiến thức tiên quyết: dataframe iteration, regex validation, type casting, duplicate detection.
Nội dung đề bài
Mục tiêu kiến thức
- Xây dựng động cơ kiểm soát chất lượng dữ liệu (Data Quality & Schema Validation Engine) theo hướng khai báo (Declarative).
- Thực thi các quy tắc kiểm thử nghiêm ngặt: Kiểm tra sự tồn tại của cột, giá trị rỗng (
nullable), kiểm tra kiểu (int,float,string), giới hạn miền giá trị (min,max), và biểu thức chính quy (regex). - Phát hiện và loại bỏ các bản ghi trùng lặp khóa chính (
dedup_keys), chỉ giữ lại bản ghi hợp lệ xuất hiện đầu tiên. - Phân tách luồng dữ liệu thành hai bảng: Bảng dữ liệu sạch đã ép kiểu chuẩn (
valid_df) và Bảng dữ liệu lỗi kèm danh sách lý do vi phạm (invalid_df).
Mô tả bài toán
Trong các hệ thống Data Lakehouse hiện đại, dữ liệu thô (Raw Data) từ nhiều nguồn thứ ba gửi về thường chứa lỗi: thiếu trường, sai định dạng email/SĐT, số âm vô lý, hoặc trùng lặp mã đơn hàng. Để đảm bảo dữ liệu đưa vào kho không bị ô nhiễm, cần có một pipeline kiểm duyệt tự động.
Hãy viết hàm: validate_and_clean_data(df: pd.DataFrame, schema: dict) -> tuple[pd.DataFrame, pd.DataFrame]
Cấu trúc đối tượng schema:
schema = {
"columns": {
"col_name": {
"type": "int" | "float" | "string",
"nullable": bool,
"min": float | int, # Tùy chọn (chỉ áp dụng cho int/float)
"max": float | int, # Tùy chọn (chỉ áp dụng cho int/float)
"regex": str # Tùy chọn (chỉ áp dụng cho string)
}
},
"dedup_keys": list[str] # Tùy chọn danh sách cột khóa duy nhất
}Quy tắc kiểm tra từng dòng theo thứ tự ưu tiên:
- Kiểm tra cột bắt buộc:
- Nếu một cột khai báo trong
schema["columns"]hoàn toàn không tồn tại trongdf.columns, TOÀN BỘ các dòng củadfđều bị coi là lỗi với mã lý do:f"MISSING_COLUMN_{col}". - Kiểm tra Giá trị Rỗng (
nullable): - Nếu ô dữ liệu là rỗng (
pd.isna(val)) mà cột đó cónullable=False: thêm lý dof"NULL_NOT_ALLOWED_{col}". - Kiểm tra Kiểu & Giới hạn (với ô không rỗng):
- Thử ép kiểu:
- Với
type == 'int': Thử chuyển sang số nguyên (chuỗi biểu diễn số nguyên hợp lệ hoặc số thực có phần thập phân bằng 0). Nếu thất bại, ghi nhậnf"INVALID_TYPE_{col}". - Với
type == 'float': Thử chuyển sang số thựcfloat(val). Nếu thất bại, ghi nhậnf"INVALID_TYPE_{col}". - Với
type == 'string': Giá trị phải là chuỗi ký tự (hoặc ép sang chuỗi). - Kiểm tra miền giá trị (nếu ép kiểu thành công cho
int/float): - Nếu có khai báo
minvàval < min: ghi nhậnf"OUT_OF_RANGE_MIN_{col}". - Nếu có khai báo
maxvàval > max: ghi nhậnf"OUT_OF_RANGE_MAX_{col}". - Kiểm tra định dạng Regex (cho
string): - Nếu có khai báo
regexvàre.match(regex, str(val))không khớp: ghi nhậnf"PATTERN_MISMATCH_{col}". - Kiểm tra Trùng lặp Khóa (
dedup_keys): - Chỉ áp dụng kiểm tra trùng lặp cho các dòng không vi phạm bất kỳ quy tắc nào ở trên.
- Nếu giá trị tổ hợp các cột trong
dedup_keysđã từng xuất hiện ở một dòng hợp lệ trước đó, dòng hiện tại bị đánh dấu lỗi với lý do"DUPLICATE_KEY". - Đầu ra:
valid_df: DataFrame gồm các dòng hợp lệ, các cột được ép kiểu chuẩn mực (int64,float64,object), reset indexdrop=True.invalid_df: DataFrame gồm các dòng vi phạm, giữ nguyên giá trị ban đầu, thêm cột mớierror_reasons(dạnglist[str]), reset indexdrop=True.- Trả về
(valid_df, invalid_df).
Input
- Các tham số truyền vào hàm/lớp validate_and_clean_data hoặc dữ liệu đầu vào theo định dạng mô tả.
Output
- Kết quả trả về của hàm/lớp validate_and_clean_data hoặc dữ liệu in ra màn hình theo đúng đặc tả.
Ràng buộc
- Số dòng dữ liệu: 0 ≤ N ≤ 104.
- Schema luôn có khóa
"columns"hợp lệ.
Ví dụ 1
Input
validate_and_clean_data(data=[{'user_id': 1, 'email': 'alice@domain.com', 'age': 25, 'score': 95.5}, {'user_id': 2, 'email': 'invalid_email_format', 'age': 30, 'score': 80.0}, {'user_id': 3, 'email': 'charlie@domain.com', 'age': 150, 'score': 75.0}], schema={'columns': {'user_id': {'type': 'int', 'nullable': False}, 'email': {'type': 'string', 'regex': '^[\\w\\.-]+@[\\w\\.-]+\\.\\w+$', 'nullable': False}, 'age': {'type': 'int', 'min': 18, 'max': 120, 'nullable': True}, 'score': {'type': 'float', 'min': 0.0, 'max': 100.0, 'nullable': True}}, 'dedup_keys': ['user_id']})Output
1Giải thích
Hàm được gọi với các tham số mẫu trên và trả về kết quả chính xác theo yêu cầu.
Ví dụ 2
Input
validate_and_clean_data(data=[{'uid': 101, 'name': 'first_entry'}, {'uid': 101, 'name': 'duplicate_entry'}], schema={'columns': {'uid': {'type': 'int', 'nullable': False}, 'name': {'type': 'string', 'nullable': False}}, 'dedup_keys': ['uid']})Output
1Giải thích
Hàm được gọi với bộ tham số thứ hai và trả về kết quả tương ứng theo thiết kế.
Gợi ý và lời giải chỉ mở sau khi bạn bấm Nộp bài. Giáo viên và quản trị viên mở được ngay.
Góp ý & báo lỗi bài tập
Đề bài chưa rõ, test có vấn đề hay bạn có ý tưởng giúp bài tốt hơn? Gửi cho đội ngũ AI Empire nhé — mỗi góp ý đều được đọc.
