Khi làm việc với file Excel có kích thước lớn, việc sử dụng phương pháp tải toàn bộ file vào bộ nhớ có thể gây ra vấn đề về hiệu suất. Dưới đây là một số cách tiếp cận và thư viện hiệu quả:
import pandas as pd
import openpyxl
from openpyxl import load_workbook
import xlrd
import csv
import os
def read_excel_in_chunks(file_path, sheet_name, chunksize=10000):
"""Đọc file Excel lớn theo từng phần nhỏ để tiết kiệm bộ nhớ"""
for chunk in pd.read_excel(file_path, sheet_name=sheet_name, chunksize=chunksize):
# Xử lý từng phần dữ liệu
process_data_chunk(chunk)
def process_data_chunk(data_chunk):
"""Xử lý từng phần dữ liệu"""
# Thực hiện các thao tác trên phần dữ liệu
# Ví dụ: tính toán, lọc, chuyển đổi
print(f"Đang xử lý chunk có {len(data_chunk)} dòng")
# Thêm code xử lý của bạn ở đây
def convert_excel_to_csv(excel_file, output_folder):
"""Chuyển đổi Excel sang CSV để xử lý hiệu quả hơn"""
xls = pd.ExcelFile(excel_file)
os.makedirs(output_folder, exist_ok=True)
for sheet_name in xls.sheet_names:
df = pd.read_excel(excel_file, sheet_name=sheet_name)
csv_file = os.path.join(output_folder, f"{sheet_name}.csv")
df.to_csv(csv_file, index=False)
print(f"Đã chuyển sheet '{sheet_name}' sang file CSV")
def process_specific_columns(file_path, sheet_name, columns):
"""Chỉ đọc một số cột cần thiết để tiết kiệm bộ nhớ"""
df = pd.read_excel(file_path, sheet_name=sheet_name, usecols=columns)
print(f"Đã đọc {len(df)} dòng với các cột: {columns}")
return df
def optimize_dtypes(df):
"""Tối ưu hóa kiểu dữ liệu để giảm mức sử dụng bộ nhớ"""
# Chuyển đổi các cột số nguyên
int_columns = df.select_dtypes(include=['int64']).columns
for col in int_columns:
df[col] = pd.to_numeric(df[col], downcast='integer')
# Chuyển đổi các cột số thực
float_columns = df.select_dtypes(include=['float64']).columns
for col in float_columns:
df[col] = pd.to_numeric(df[col], downcast='float')
# Chuyển đổi cột object thành category nếu số giá trị độc nhất ít
obj_columns = df.select_dtypes(include=['object']).columns
for col in obj_columns:
if df[col].nunique() < len(df[col]) * 0.5: # Nếu có ít hơn 50% giá trị độc nhất
df[col] = df[col].astype('category')
return df
def parallel_process_excel(file_path, sheet_name, num_processes=4):
"""Xử lý song song với multiprocessing"""
from multiprocessing import Pool
import numpy as np
# Đọc số lượng dòng trong file
wb = load_workbook(filename=file_path, read_only=True)
ws = wb[sheet_name]
total_rows = ws.max_row
wb.close()
# Chia thành các phần để xử lý song song
chunk_size = total_rows // num_processes
chunks = [(i*chunk_size, (i+1)*chunk_size if i < num_processes-1 else total_rows)
for i in range(num_processes)]
# Hàm xử lý từng phần
def process_chunk(args):
start_row, end_row = args
# Chỉ đọc các dòng từ start_row đến end_row
df = pd.read_excel(file_path, sheet_name=sheet_name,
skiprows=range(1, start_row+1),
nrows=end_row-start_row)
# Thêm xử lý của bạn ở đây
return df.sum().sum() # Ví dụ về kết quả trả về
# Xử lý song song
with Pool(processes=num_processes) as pool:
results = pool.map(process_chunk, chunks)
return results
if __name__ == "__main__":
file_path = "large_excel_file.xlsx"
sheet_name = "Sheet1"
# Ví dụ sử dụng:
# read_excel_in_chunks(file_path, sheet_name)
# convert_excel_to_csv(file_path, "output_csv")
# df = process_specific_columns(file_path, sheet_name, ["A", "C", "D"])
# df = optimize_dtypes(df)
# results = parallel_process_excel(file_path, sheet_name)
import polars as pl
# Đọc Excel với Polars
df = pl.read_excel(file_path, sheet_name=sheet_name)
# Hoặc đọc CSV (nếu đã chuyển đổi)
df = pl.read_csv("large_file.csv")
# Xử lý dữ liệu với Polars nhanh hơn pandas
result = df.filter(pl.col("value") > 1000).groupby("category").agg(pl.sum("amount"))
import dask.dataframe as dd
# Chuyển đổi Excel sang CSV trước
# Sau đó đọc với Dask
ddf = dd.read_csv("output_csv/*.csv")
# Xử lý dữ liệu phân tán
result = ddf.groupby('column').mean().compute()
from openpyxl import load_workbook
def process_excel_streaming(file_path, sheet_name):
"""Xử lý Excel bằng cách streaming từng dòng"""
wb = load_workbook(filename=file_path, read_only=True)
ws = wb[sheet_name]
results = []
row_count = 0
# Đọc từng dòng một
for row in ws.rows:
row_data = [cell.value for cell in row]
# Xử lý dữ liệu từng dòng
# ...
row_count += 1
if row_count % 10000 == 0:
print(f"Đã xử lý {row_count} dòng")
wb.close()
return results
- Chuyển đổi thành CSV: Excel -> CSV -> Xử lý -> Kết quả
- Chỉ đọc các cột cần thiết
- Xử lý theo batch/chunk thay vì đọc toàn bộ file
- Tối ưu hóa kiểu dữ liệu để giảm bộ nhớ
- Sử dụng các thư viện xử lý dữ liệu hiệu suất cao như Polars, PyArrow
- Áp dụng xử lý song song khi có thể
- Sử dụng máy tính có RAM lớn hơn nếu cần