Chuyển đến nội dung chính

Đo hiệu năng các lựa chọn thay thế pandas hiệu suất cao

Khám phá kết quả đo hiệu năng mới nhất của các lựa chọn thay thế mạnh mẽ cho pandas trong Python: Polars, Vaex và Datatable. Tìm hiểu hiệu năng của chúng trong việc tải dữ liệu, nhóm, sắp xếp và hơn thế nữa.
Đã cập nhật 5 thg 10, 2026  · 13 phút đọc

Khám phá cùng AI

ChatGPTClaudePerplexity

Giới thiệu

Pandas là một công cụ cực kỳ mạnh mẽ trong hệ sinh thái khoa học dữ liệu của Python, cung cấp nhiều khả năng thao tác và làm sạch dữ liệu. Tuy nhiên, dù rất phù hợp cho các tập dữ liệu kích thước trung bình, pandas có thể gặp vấn đề về hiệu năng khi xử lý các tập dữ liệu lớn, từ đó nảy sinh nhu cầu về các giải pháp thay thế có hiệu suất cao.

Bài viết toàn diện này giới thiệu một số lựa chọn thay thế và so sánh chúng thông qua các phép đo hiệu năng theo thời gian tải dữ liệu, thời gian thực thi, mức sử dụng bộ nhớ, khả năng mở rộng và mức độ dễ sử dụng.

Lưu ý: Kết quả đo hiệu năng có thể khác biệt đáng kể tùy theo cấu hình phần cứng của bạn.

Tìm hiểu về các phép đo hiệu năng

Benchmark là điểm tham chiếu để so sánh phần mềm hoặc phần cứng nhằm đánh giá hiệu năng. Tham chiếu này đặc biệt quan trọng trong tối ưu hóa hiệu năng phần mềm vì cho phép đo lường hiệu quả của các phương pháp, thuật toán hoặc công cụ khác nhau. Trong bối cảnh này, các chỉ số chính để đo hiệu năng các thư viện thao tác dữ liệu gồm có thời gian thực thi, mức sử dụng bộ nhớ, khả năng mở rộng và mức độ dễ sử dụng.

Giới thiệu các lựa chọn thay thế hiệu suất cao

Các công cụ thay thế chính trong Python là Polars, Vaex và Datatable. Trước khi đi vào phân tích so sánh, hãy điểm qua nhanh từng công cụ.

Polars

Polars có thể được mô tả bằng ba đặc điểm chính. Thứ nhất, nó cung cấp API Python toàn diện với nhiều hàm để xử lý DataFrame. Thứ hai, nó có thể phục vụ hai mục đích — vừa dùng như một thư viện DataFrame, vừa làm động cơ truy vấn nền tảng cho mô hình dữ liệu. Cuối cùng, nhờ tích hợp Arrow2 an toàn theo đặc tả Apache Arrow, Polars trở thành công cụ cực kỳ hiệu quả để xử lý lượng dữ liệu lớn.

Bạn có thể xem bài hướng dẫn giới thiệu Polars của chúng tôi, cũng như so sánh giữa pandas 2.0 và Polars.

Vaex

Vaex dành cho DataFrame lười thực thi (lazy) và out-of-core (tương tự Pandas) để trực quan hóa và khám phá các tập dữ liệu dạng bảng lớn. Nó có thể rất hiệu quả vì trì hoãn thao tác cho đến khi cần thiết (đánh giá lười), giúp giảm sử dụng bộ nhớ và thời gian.

Datatable

Datatable có thể được dùng để xử lý dữ liệu lớn (lên đến 100GB) trên một máy đơn ở tốc độ tối đa có thể. Một tính năng quan trọng của Datatable là khả năng tương tác với Pandas/NumPy/thuần Python, cho phép người dùng dễ dàng chuyển đổi sang khung xử lý dữ liệu khác.

Để tìm hiểu thêm về pandas, hướng dẫn DataFrame với pandas trong Python của chúng tôi là điểm khởi đầu tuyệt vời.

Ngoài ra, Pandas Cheat Sheet cho Khoa học Dữ liệu bằng Python cung cấp hướng dẫn nhanh về những điều cơ bản của thư viện phân tích dữ liệu Python, kèm theo mẫu mã.

Thiết lập môi trường đo hiệu năng

Phần này trình bày việc tạo dữ liệu dùng để đo hiệu năng và cài đặt toàn bộ các thư viện liên quan trong phân tích.

Dữ liệu đo hiệu năng

Tập dữ liệu dùng để đo hiệu năng có kích thước 5,7 GB, đủ lớn để thực hiện so sánh hợp lý. Mỗi hàng đã được nhân bản 100000 lần, tạo thành 76.800.000 hàng. Dữ liệu tiểu đường là bản gốc được sử dụng và có sẵn miễn phí trên Kaggle.

Notebook đo hiệu năng cuối cùng có sẵn trên GitHub.

import pandas as pd

data_URL = "https://raw.githubusercontent.com/keitazoumana/Experimentation-Data/main/diabetes.csv"

original_data = pd.read_csv(data_URL)

# Duplicate each row 100000 times
benchmarking_df = original_data.loc[original_data.index.repeat(100000)]

# Save the result as a CSV file for future use.
file_name = "benchmarking_data.csv"

benchmarking_df.to_csv(file_name, index=False)

Cài đặt các thư viện

Giờ đây, chúng ta có thể tiến hành cài đặt tất cả thư viện tham gia vào phân tích đo hiệu năng.

Trong môi trường Jupyter notebook, toàn bộ việc cài đặt được thực hiện bằng lệnh pip install như sau:

%%bash
pip3 -q install -U polars
pip3 -q install vaex
pip -q install datatable

Sau khi chạy thành công khối mã trên, chúng ta có thể import bằng câu lệnh import:

import pandas as pd
from time import time
import polars as pl
import vaex as vx
import datatable as dt

Ngoài ra, chúng ta sử dụng thư viện plotly cho mục đích trực quan hóa.

import plotly.express as px

Giờ thì mọi thứ đã sẵn sàng để bắt đầu phân tích đo hiệu năng.

Đo hiệu năng theo thời gian thực thi

Thời gian thực thi sẽ được đánh giá cho các thao tác sau: tải dữ liệu, chuyển đổi/xuất dữ liệu, tổng hợp dữ liệu và lọc dữ liệu. Một hàm hỗ trợ được triển khai cho mỗi tác vụ và sẽ trả về một dictionary với hai khóa chính: tên thư viện và thời gian thực thi.

Sau đó, hàm vẽ chỉ số được dùng để biểu diễn kết quả dưới dạng đồ thị bằng thư viện Plotly Express. Hàm có hai tham số: danh sách tất cả dictionary từ các hàm hỗ trợ trước đó và tiêu đề của biểu đồ tương ứng.

def plot_metrics(list_exec_time, graph_title):

	df = pd.DataFrame(list_exec_time)

	fig = px.bar(df, x='library', y= 'execution_time', title=graph_title)
    
	fig.show()

Tải dữ liệu

Hàm hỗ trợ read_csv_with_time có hai tham số chính: tên tệp cần đọc và tên thư viện.

def read_csv_with_time(library_name, file_name):

	final_time = 0

	start_time = time.time()

	if library_name.lower() == 'polars':
    	df = pl.read_csv(file_name)

	elif library_name.lower() == 'pandas':
    	df = pd.read_csv(file_name)

	elif library_name.lower() == 'vaex':
    	df = vx.read_csv(file_name)

	elif library_name.lower() == 'datatable':
    	df = dt.fread(file_name)

	else:
    	raise ValueError("Invalid library name. Must be 'polars', 'pandas', 'vaex', or 'datatable'")

	end_time = time.time()

	final_time = end_time - start_time

	return {"library": library_name, "execution_time": final_time}

Hàm có thể được áp dụng với từng thư viện, bắt đầu từ pandas.

pandas_time, pandas_df = read_csv_with_time('pandas', file_name)
polars_time, polars_df = read_csv_with_time('polars', file_name)
vaex_time, vaex_df = read_csv_with_time('vaex', file_name)
datatable_time, dt_df = read_csv_with_time('datatable', file_name)

Các dictionary kết quả có thể được gộp thành một danh sách và vẽ bằng biểu thức sau.

exec_times = [pandas_time, polars_time,
           vaex_time, datatable_time]

def plot_metrics(list_exec_time, graph_title):

 [print(exec_time) for exec_time in list_exec_time]
 df = pd.DataFrame(exec_times)

 # Plot bar plot using Plotly Express
 fig = px.bar(df, x='library', y='execution_time', title=graph_title)
 fig.show()

plot_metrics(exec_times, "Read Execution Time Comparison")
{'library': 'pandas', 'execution_time': 35.07908916473389}
{'library': 'polars', 'execution_time': 6.041005373001099}
{'library': 'vaex', 'execution_time': 36.431522607803345}
{'library': 'datatable', 'execution_time': 4.4584901332855225}

Dạng dictionary của thời gian thực thi cho việc tải dữ liệu

Dạng đồ thị của thời gian thực thi cho việc tải dữ liệu

Dựa trên đồ thị, có thể kết luận rằng Polars:

  • Polars chậm hơn Datatable 1,35 lần
  • Pandas chậm hơn DataTable 7,87 lần.
  • Vaex chậm hơn DataTable xấp xỉ 8,17 lần.

Nhóm dữ liệu

Tương tự, group_data_with_time chịu trách nhiệm theo dõi thời gian thực thi cho việc nhóm cột được truyền vào tham số. Trong trường hợp này, chúng ta sử dụng cột Pregnancies.

from time import time

def group_data_with_time(library_name, df, column_name='Pregnancies'):

 start_time = time()

 if library_name.lower() == 'polars':
     df_grouped = df.group_by(column_name).first()

 elif library_name.lower() == 'vaex':
     df_grouped = df.groupby(column_name, agg='first')

 elif library_name.lower() == 'pandas':
     df_grouped = df.groupby(column_name).first()

 elif library_name.lower() == 'datatable':
     df_grouped = df[:, dt.first(dt.f[:]), dt.by(column_name)]

 else:
     raise ValueError("Invalid library name. Must be 'polars', 'vaex', or 'datatable'")

 end_time = time()

 final_time = end_time - start_time

 return {"library": library_name, "execution_time": final_time}
pandas_time = group_data_with_time('pandas', pandas_df)
polars_time = group_data_with_time('polars', polars_df)
vaex_time = group_data_with_time('vaex', vaex_df)
datatable_time = group_data_with_time('datatable', dt_df)
exec_times = [pandas_time, polars_time,
           vaex_time, datatable_time]
plot_metrics(exec_times, "Grouping Execution Time Comparison")
{'library': 'pandas', 'execution_time': 2.382519245147705}
{'library': 'pandas', 'execution_time'': 1.0898876190185547}
{'library': 'pandas', 'execution_time': 0.8506548404693604}
{'library': 'pandas', 'execution_time': 0.34698963165283203}

Dạng đồ thị của thời gian thực thi cho việc nhóm dữ liệu

Đối với tác vụ nhóm dữ liệu (đã cập nhật), so sánh thư viện nhanh nhất là DataTable với các thư viện còn lại:

Có thể thấy DataTable là nhanh nhất trong số các thư viện được đánh giá.

  • Vaex chậm hơn DataTable 2,45 lần.
  • Polars chậm hơn DataTable 3,14 lần.
  • Pandas chậm hơn DataTable 6,87 lần.

Phân tích này cho thấy hiệu quả vượt trội của DataTable cho các tác vụ nhóm dữ liệu, với Vaex có hiệu năng tương đối gần. Polars và Pandas có thời gian thực thi tương tự nhau, đều chậm đáng kể so với DataTable.

Sắp xếp cột

Với cùng cách tiếp cận, hàm sắp xếp cột sẽ sắp xếp cột được chỉ định bằng từng thư viện.

def sort_data_with_time(library_name, df, column_name='Pregnancies'):
    
	start_time = time()

	if library_name.lower() == 'polars':
    	df_sorted = df.sort(column_name)
	elif library_name.lower() == 'vaex':
    	df_sorted = df.sort(column_name)

	elif library_name.lower() == 'datatable':
    	df_sorted = df.sort(column_name)
   	 
	elif library_name.lower() == 'pandas':
    	df_sorted = pd.DataFrame(df).sort_values(column_name)
	else:
    	raise ValueError("Invalid library name. Must be 'polars', 'vaex', 'datatable', or 'pandas'")

	end_time = time()

	final_time = end_time - start_time

	return {"library": library_name, "execution_time": final_time}
pandas_time = sort_data_with_time('pandas', pandas_df)
polars_time = sort_data_with_time('polars', polars_df)
vaex_time = sort_data_with_time('vaex', vaex_df)
datatable_time = sort_data_with_time('datatable', dt_df)
{'library': 'pandas', 'execution_time': 6.735127687454224}
{'library': 'polars', 'execution_time': 4.119458436965942}
{'library': 'vaex', 'execution_time': 1.0371737480163574}
{'library': 'datatable', 'execution_time': 0.3971593379974365}

Dạng dictionary của thời gian thực thi cho việc sắp xếp dữ liệu

Dạng đồ thị của thời gian thực thi cho việc sắp xếp dữ liệu

Đối với tác vụ sắp xếp dữ liệu, DataTable là nhanh nhất trong số các thư viện được đánh giá.

  • Vaex chậm hơn DataTable 2,61 lần.
  • Polars chậm hơn DataTable 10,37 lần.
  • Pandas chậm hơn DataTable 16,96 lần.

Phân tích này cho thấy hiệu năng vượt trội của DataTable trong xử lý tác vụ sắp xếp dữ liệu, vượt xa Vaex, Polars và Pandas, với Vaex là gần nhất nhưng vẫn chậm hơn hơn gấp đôi.

Chuyển đổi/xuất dữ liệu

Với chuyển đổi/xuất dữ liệu, ý tưởng là chuyển đổi dữ liệu gốc sang một định dạng khác, cụ thể trong trường hợp này là mảng numpy.

def offload_data_with_time(library_name, df):
    
	start_time = time()

	if library_name.lower() == 'polars':
    	array = df.to_numpy()
   	 
	elif library_name.lower() == 'vaex':
    	array = df.to_pandas_df().values

	elif library_name.lower() == 'datatable':
    	array = df.to_numpy()
   	 
	elif library_name.lower() == 'pandas':
    	array = pd.DataFrame(df).values
	else:
    	raise ValueError("Invalid library name. Must be 'polars', 'vaex', 'datatable', or 'pandas'")

	end_time = time()

	final_time = end_time - start_time

	return {"library": library_name, "execution_time": final_time}
exec_times = [pandas_time, polars_time,
           vaex_time, datatable_time]

plot_metrics(exec_times, "Data offloading Execution Time Comparison")
{'library': 'pandas', 'execution_time': 1.8406445980072021}
{'library': 'polars', 'execution_time': 3.238591432571411}
{'library': 'vaex', 'execution_time': 6.945307970046997}
{'library': 'datatable', 'execution_time': 2.634136438369751}

Dạng dictionary của thời gian thực thi cho việc chuyển đổi/xuất dữ liệu

Dạng đồ thị của thời gian thực thi cho việc chuyển đổi/xuất dữ liệu

Chuyển đổi/xuất dữ liệu là vòng cuối cùng trong phần đo thời gian thực thi.

Lần này, Vaex có thời gian thực thi cao nhất. So sánh pandas với các thư viện này, có thể thấy thời gian thực thi của nó xấp xỉ:

  • DataTable chậm hơn Pandas 1,43 lần.
  • Polars chậm hơn Pandas 1,76 lần.
  • Vaex chậm hơn Pandas 3,77 lần.

Đo hiệu năng về mức sử dụng bộ nhớ

Thời gian thực thi không phải là tiêu chí duy nhất khi so sánh các thư viện. Biết cách chúng quản lý bộ nhớ hiệu quả ra sao cũng rất quan trọng. Phần này trình bày hai thước đo sử dụng bộ nhớ bằng thư viện tracemalloc:

  • Mức sử dụng bộ nhớ hiện tại. Tổng lượng bộ nhớ được sử dụng trong quá trình thực thi với một thư viện cụ thể. Tương ứng với phần RAM đang bị chiếm dụng tại thời điểm đó.
  • Mức sử dụng bộ nhớ đỉnh. Tương ứng với lượng bộ nhớ tối đa mà chương trình sử dụng. Lưu ý rằng bộ nhớ đỉnh luôn cao hơn bộ nhớ hiện tại.

Các trực quan hóa này giúp hiểu chương trình nào sử dụng nhiều bộ nhớ, dễ dẫn đến lỗi hết bộ nhớ, đặc biệt khi làm việc với tập dữ liệu lớn.

Bên cạnh tracemalloc, thư viện os cũng được yêu cầu.

import tracemalloc as tm
import os

Trước khi bắt đầu, chúng ta tạo một danh sách trống để lưu kết quả của từng giá trị sử dụng bộ nhớ.

list_memory_usage = []

Với mỗi thư viện, việc ước lượng sử dụng bộ nhớ được thực hiện theo cú pháp tổng quát dưới đây tương ứng với thực thi bằng thư viện Vaex. Ngoài ra, phần này chỉ tập trung vào mức sử dụng bộ nhớ cho tác vụ chuyển đổi/xuất dữ liệu.

tm.start()
vaex_time = offload_data_with_time('vaex', vaex_df)
memory_usage = tm.get_traced_memory()
tm.stop()

list_memory_usage.append({
	'library': 'vaex',
	'memory_usage': memory_usage
})

Cú pháp tương tự cho các thư viện còn lại, và chúng ta có các lệnh sau, lần lượt cho Polars, pandas và Datatable:

tm.start()
polars_time = offload_data_with_time('polars', polars_df)
memory_usage = tm.get_traced_memory()

tm.stop()

list_memory_usage.append({
	'library': 'polars',
	'memory_usage': memory_usage
})
tm.start()
offload_data_with_time('pandas', pandas_df)

# Get the memory usage
memory_usage = tm.get_traced_memory()

tm.stop()

list_memory_usage.append({
	'library': 'pandas',
	'memory_usage': memory_usage
})
tm.start()
datatable_time = offload_data_with_time('datatable', datatable_df)
memory_usage = tm.get_traced_memory()

tm.stop()

list_memory_usage.append({
	'library': 'datatable',
	'memory_usage': memory_usage
})

Sau khi thực thi toàn bộ mã trên, chúng ta có thể vẽ đồ thị bằng hàm hỗ trợ dưới đây:

def plot_memory_usage(list_memory_usage, graph_title='Memory Usage by Library'):

	df = pd.DataFrame(list_memory_usage)

	# separate the memory usage tuple into two columns: current_memory and peak_memory
	df[['current_memory', 'peak_memory']] = pd.DataFrame(df['memory_usage'].tolist(), index=df.index)

	# now we no longer need the memory_usage column
	df = df.drop(columns='memory_usage')

	# melt the DataFrame to make it suitable for grouped bar chart
	df_melted = df.melt(id_vars='library', var_name='memory_type', value_name='memory')

	# create the grouped bar chart
	fig = px.bar(df_melted, x='library', y='memory', color='memory_type', barmode='group',
             	labels={'memory':'Memory Usage (bytes)', 'library':'Library', 'memory_type':'Memory Type'},
             	title=graph_title)
    
	fig.update_layout(yaxis_type="log")
	fig.show()

Có thể nhận thấy rằng:

  • Pandas dùng bộ nhớ hiện tại nhiều hơn Polars khoảng 1100 lần, nhiều hơn Vaex 7,4 lần và nhiều hơn Datatable 29,4 lần.
  • Về mức sử dụng bộ nhớ đỉnh, cả pandas và Vaex đều dùng nhiều hơn Polars khoảng 963 nghìn lần và nhiều hơn Datatable 131 nghìn lần.

Phân tích sâu hơn, như so sánh tốc độ Dask so với pandas, có thể mang lại cái nhìn tổng quan rộng hơn.

Bảng so sánh các lựa chọn thay thế cho Pandas

Bên dưới, chúng tôi tổng hợp phát hiện vào một bảng so sánh, thể hiện khác biệt giữa Polars, Vaex và Datatables:

Tiêu chí đo hiệu năng

Polars

Vaex

Datatable

Thời gian tải dữ liệu

Nhanh hơn Vaex, chậm hơn Datatable

Chậm hơn cả Polars và Datatable

Nhanh nhất trong ba

Thời gian nhóm dữ liệu

Chậm nhất trong ba

Nhanh hơn Polars, chậm hơn Datatable

Nhanh nhất trong ba

Thời gian sắp xếp dữ liệu

Nhanh hơn Vaex, chậm hơn Datatable

Chậm hơn cả Polars và Datatable

Nhanh nhất trong ba

Thời gian chuyển đổi/xuất dữ liệu

Nhanh hơn Vaex, chậm hơn Datatable

Chậm nhất trong ba

Nhanh hơn Polars, chậm hơn Vaex

Mức sử dụng bộ nhớ hiện tại

Dùng ít bộ nhớ nhất

Dùng nhiều bộ nhớ hơn Polars nhưng ít hơn Datatable

Dùng nhiều bộ nhớ nhất trong ba

Mức sử dụng bộ nhớ đỉnh

Dùng ít bộ nhớ nhất

Dùng nhiều bộ nhớ hơn Polars nhưng ít hơn Datatable

Dùng nhiều bộ nhớ nhất trong ba

Khả năng mở rộng

Mở rộng theo kích thước dữ liệu

Mở rộng theo kích thước dữ liệu, nhưng có thể dùng nhiều bộ nhớ hơn khi dữ liệu tăng

Mở rộng rất tốt theo kích thước dữ liệu

Mức độ dễ sử dụng

Có API Python đầy đủ và tương thích với Apache Arrow

Sử dụng đánh giá lười và tương thích với Pandas

Cung cấp khả năng tương tác với Pandas/NumPy/thuần Python

Kết luận

Cần cân nhắc nhiều yếu tố khi phân tích khả năng mở rộng và mức độ dễ tích hợp. Đo hiệu năng của chúng tôi cho thấy mặc dù pandas lâu đời, thân thiện với người dùng và có đường cong học tập dốc, nhưng nó không xử lý hiệu quả các tập dữ liệu lớn.

Tuy nhiên, có nhiều cách có thể áp dụng để tăng tốc pandas, và High-Performance Data Manipulation in Python: Pandas 2.0 vs Polars của chúng tôi có thể giúp bạn.

Hiệu năng của Vaex thay đổi tùy theo tác vụ. Vì vậy, việc chọn lựa thay thế cho Pandas phụ thuộc vào nhu cầu cụ thể của người dùng, kích thước tập dữ liệu và khả năng chinh phục đường cong học tập cũng như tích hợp.


Zoumana Keita 's photo
Author
Zoumana Keita
LinkedIn
Twitter

Nhà khoa học dữ liệu đa tài, yêu thích chia sẻ kiến thức và đóng góp cho cộng đồng, Zoumana là người sáng tạo nội dung trên YouTube và là cây bút công nghệ hàng đầu trên Medium. Anh yêu thích thuyết trình, lập trình và giảng dạy. Zoumana có hai bằng thạc sĩ: một về khoa học máy tính chuyên sâu Học máy tại Paris, Pháp, và một về Khoa học dữ liệu tại Texas Tech University, Hoa Kỳ. Anh bắt đầu sự nghiệp với vai trò Nhà phát triển phần mềm tại Groupe OPEN ở Pháp, sau đó chuyển sang IBM làm Tư vấn Học máy, nơi anh phát triển các giải pháp AI đầu-cuối cho các công ty bảo hiểm. Zoumana gia nhập Axionable, startup Trí tuệ nhân tạo Bền vững đầu tiên có trụ sở tại Paris và Montreal. Tại đây, anh làm Nhà khoa học dữ liệu và triển khai các sản phẩm AI, chủ yếu là các bài toán NLP, cho khách hàng tại Pháp, Montreal, Singapore và Thụy Sĩ. Ngoài ra, 5% thời gian của anh được dành cho Nghiên cứu và Phát triển. Hiện tại, anh làm việc với vai trò Nhà khoa học dữ liệu cao cấp tại IFC - Nhóm Ngân hàng Thế giới.

Chủ đề
Python
Liên quan

blog

Claude Opus 4.6: Tính năng, Điểm chuẩn, Bài kiểm tra thực hành và hơn thế nữa

Mô hình mới nhất của Anthropic dẫn đầu ở mã hóa tác tử và lập luận phức tạp. Thêm vào đó, nó có cửa sổ ngữ cảnh 1M.
Matt Crabtree's photo

Matt Crabtree

10 phút

Xem ThêmXem Thêm