Tối ưu hóa Bộ nhớ DataFrame Triệt để bằng Downcasting & Categorical Dtype
Khi nạp các tệp CSV dung lượng lớn (hàng triệu bản ghi) vào bộ nhớ, pandas mặc định phân bổ int64 (8 bytes) cho số nguyên, float64 (8 bytes) cho số thực và object (con trỏ Python t…
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: memory usage deep, to numeric downcast, category conversion.
Nội dung đề bài
Mục tiêu kiến thức
- Đo lường chính xác mức tiêu thụ bộ nhớ RAM thực tế của
pandas.DataFramebằngmemory_usage(deep=True). - Ép kiểu giảm cấp (Downcasting) các cột số nguyên (
int64→int8,int16,int32) và số thực (float64→float32). - Nhận diện và chuyển đổi các cột chuỗi ký tự (
object) có độ đa dạng thấp (low cardinality) sang kiểucategory. - Lập báo cáo thống kê tỷ lệ phần trăm bộ nhớ tiết kiệm được.
Mô tả bài toán
Khi nạp các tệp CSV dung lượng lớn (hàng triệu bản ghi) vào bộ nhớ, pandas mặc định phân bổ int64 (8 bytes) cho số nguyên, float64 (8 bytes) cho số thực và object (con trỏ Python tốn kém) cho chuỗi. Điều này khiến máy chủ phân tích dễ rơi vào tình trạng quá tải bộ nhớ (Out-Of-Memory - OOM).
Hãy viết hàm: optimize_dataframe_memory(df: pd.DataFrame, category_threshold: float = 0.5) -> tuple[pd.DataFrame, dict]
Yêu cầu thực hiện:
- Kiểm tra đầu vào:
- Nếu
dfrỗng (len(df) == 0), trả về(df.copy(), {"initial_bytes": 0, "optimized_bytes": 0, "savings_pct": 0.0, "dtypes": {}}). category_thresholdphải nằm trong khoảng (0.0, 1.0].- Đo lường dung lượng ban đầu:
- Tính tổng dung lượng RAM thực tế:
initial_bytes = int(df.memory_usage(deep=True).sum()). - Thực hiện Tối ưu hóa trên bản sao:
- Tạo bản sao
opt_df = df.copy(). - Duyệt qua từng cột:
- Cột số nguyên (
integer): Sử dụngpd.to_numeric(opt_df[col], downcast='integer'). - Cột số thực (
float): Sử dụngpd.to_numeric(opt_df[col], downcast='float')để chuyển vềfloat32. - Cột chuỗi (
objecthoặcstring): - Tính tỷ lệ giá trị duy nhất: ratio = len(opt_df[col].unique())len(opt_df[col]).
- Nếu ratio < categorythreshold, chuyển đổi cột sang kiểu:
opt_df[col] = opt_df[col].astype('category'). - Đo lường dung lượng sau tối ưu & Báo cáo:
optimized_bytes = int(opt_df.memory_usage(deep=True).sum()).- Tính tỷ lệ phần trăm tiết kiệm:
savings_pct = round(initial_bytes - optimized_bytesinitial_bytes × 100, 2).
- Tạo bản đồ kiểu dữ liệu:
dtypes = {col: str(opt_df[col].dtype) for col in opt_df.columns}. - Đầu ra:
- Trả về tuple gồm:
(opt_df, {"initial_bytes": initial_bytes, "optimized_bytes": optimized_bytes, "savings_pct": savings_pct, "dtypes": dtypes}).
Input
- Các tham số truyền vào hàm/lớp optimize_dataframe_memory 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 optimize_dataframe_memory 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 ≤ 105.
- Không làm thay đổi DataFrame
dfgốc.
Ví dụ 1
Input
optimize_dataframe_memory(data={'small_int': [10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 10, 20, 30, 40, 50], 'float_col': [1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5, 1.5, 2.5, 3.5, 4.5, 5.5], 'status': ['active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive', 'active', 'inactive']}, category_threshold=0.5)Output
{'small_int': 'int8', 'float_col': 'float32', 'status': 'category'}Giả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
optimize_dataframe_memory(data={'unique_id': ['ID_0', 'ID_1', 'ID_2', 'ID_3', 'ID_4', 'ID_5', 'ID_6', 'ID_7', 'ID_8', 'ID_9']}, category_threshold=0.5)Output
{'unique_id': 'object'}Giả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.
