Polars là một thư viện xử lý dữ liệu nhanh và hiệu quả trong Python được viết bằng ngôn ngữ Rust mới ra mắt gần đây. Với tính năng tăng tốc đáng kể so với thư viện pandas chúng ta đã biết, Polars cho phép xử lý các tập dữ liệu lớn mà không gặp phải vấn đề hiệu năng & tốc độ chậm. Trong bài hướng dẫn này, chúng ta sẽ khám phá cách sử dụng Polars để xử lý dữ liệu nhanh chóng và dễ dàng thông qua các ví dụ nhé.
Giới thiệu
Polars là một thư viện xử lý dữ liệu mã nguồn mở trong Python, được thiết kế để xử lý các tập dữ liệu lớn với tốc độ và hiệu suất cao hơn so với thư viện pandas.
Polars cung cấp các tính năng tương tự như pandas, bao gồm: tạo DataFrame, chọn, lọc, sắp xếp, nhóm dữ liệu, tính toán số liệu thống kê và nhiều hơn nữa.
Bên cạnh đó, Polars cung cấp nhiều tính năng mới, bao gồm giải quyết vấn đề về hiệu suất của pandas, các thuật toán giúp xử lý nhanh chóng và xử lý thời gian chuẩn xác hơn.
Vì vậy, sử dụng Polars sẽ giúp cho việc phân tích và xử lý dữ liệu trở nên nhanh chóng và dễ dàng hơn.
Các tính năng của Polars:
- Tốc độ xử lý dữ liệu nhanh: Polars cung cấp hiệu suất xử lý dữ liệu cao hơn so với thư viện pandas thông thường, cho phép xử lý tập dữ liệu lớn mà không gây ra gián đoạn hoặc chậm lại.
- Đa luồng và xử lý song song: Polars có khả năng xử lý đồng thời nhiều tác vụ để tăng tốc độ xử lý và giảm thời gian chờ đợi.
- Hỗ trợ kiểu dữ liệu linh hoạt: Polars hỗ trợ nhiều kiểu dữ liệu như chuỗi, số nguyên, số thực và các kiểu dữ liệu khác, giúp cho việc xử lý dữ liệu linh hoạt và dễ dàng hơn.
- Xử lý thời gian chính xác: Polars có khả năng xử lý thời gian với độ chính xác cao hơn so với pandas, bao gồm hỗ trợ nhiều định dạng thời gian, tính toán các khoảng thời gian, chuyển đổi giữa các định dạng thời gian và nhiều hơn nữa.
- Tính năng xử lý dữ liệu phức tạp: Polars cung cấp nhiều tính năng mới, bao gồm giải quyết vấn đề về hiệu suất của pandas, các thuật toán ghép nối nhanh chóng và xử lý thời gian chuẩn xác hơn.
- Hỗ trợ truy vấn dữ liệu: Polars cung cấp nhiều tính năng để truy xuất và truy vấn dữ liệu nhanh chóng và dễ dàng, bao gồm các hàm
select
,filter
,groupby
,join
,sort
,agg
vàpivot
.
Cài đặt thư viện Polars
Để cài đặt thư viện Polars, ta có thể sử dụng trình quản lý gói pip trong Python. Các bước để cài đặt Polars như sau:
- Mở terminal của Python.
- Sử dụng lệnh sau để cài đặt Polars:
pip install polars
- Đợi cho quá trình cài đặt hoàn tất.
- Kiểm tra xem Polars đã được cài đặt thành công hay chưa bằng cách nhập lệnh sau vào terminal Python:
import polars as pl
Nếu không có thông báo lỗi nào xuất hiện, tức là Polars đã được cài đặt thành công và ta có thể bắt đầu sử dụng thư viện để xử lý dữ liệu. Trường hợp bạn cài chưa thành công, sẽ có thông báo lỗi ModuleNotFoundError như dưới đây.
>>> import polars as pl Traceback (most recent call last): File "<stdin>", line 1, in <module> ModuleNotFoundError: No module named 'polars'
Bên cạnh đó, bạn cũng có thể cài đặt Polars qua conda (conda install -c conda-forge polars
).
Khởi tạo DataFrame
Tương tự như Pandas, Polars cũng cho phép bạn khởi tạo 1 df theo nhiều cách khác nhau.
Khởi tạo từ Python list
Để tạo DataFrame từ list, ta có thể sử dụng hàm pl.DataFrame()
. Ví dụ, để tạo một DataFrame với 2 cột “name” và “age”, ta có thể làm như sau:
import polars as pl # Tạo list data data = [['Alice', 25], ['Bob', 30], ['Charlie', 35]] # Tạo DataFrame từ list data df = pl.DataFrame(data, schema=['name', 'age']) # In ra DataFrame print(df)
Output:
shape: (3, 2) ┌─────────┬─────┐ │ name ┆ age │ │ --- ┆ --- │ │ str ┆ i64 │ ╞═════════╪═════╡ │ Alice ┆ 25 │ │ Bob ┆ 30 │ │ Charlie ┆ 35 │ └─────────┴─────┘
Khởi tạo từ Python dictionary
Để tạo DataFrame từ dictionary, ta cũng sử dụng hàm pl.DataFrame(), nhưng với đối số đầu vào là dictionary. Ví dụ, để tạo một DataFrame với 2 cột “name” và “age”, ta có thể làm như sau:
import polars as pl # Tạo dictionary data data = {'name': ['Alice', 'Bob', 'Charlie'], 'age': [25, 30, 35]} # Tạo DataFrame từ dictionary data df = pl.DataFrame(data) # In ra DataFrame print(df)
Khởi tạo bằng cách đọc từ file
Polars hỗ trợ đọc dữ liệu từ nhiều định dạng khác nhau, bao gồm:
- CSV (Comma Separated Values) Định dạng CSV là một định dạng file chuẩn cho các tập tin chứa dữ liệu được phân tách bằng dấu phẩy. Ví dụ, ta có thể đọc dữ liệu từ file “data.csv” bằng cách sử dụng hàm
pl.read_csv()
:
import polars as pl # Đọc dữ liệu từ file CSV và chuyển thành DataFrame df = pl.read_csv("data.csv") # In ra DataFrame print(df)
- Parquet Parquet là một định dạng file hiệu quả cho việc lưu trữ và truy xuất dữ liệu trong các ứng dụng Big Data. Nó hỗ trợ việc lưu trữ dữ liệu cấu trúc hoặc phi cấu trúc và cho phép truy xuất dữ liệu phân tán. Ví dụ, ta có thể đọc dữ liệu từ file “data.parquet” bằng cách sử dụng hàm
pl.read_parquet()
:
import polars as pl # Đọc dữ liệu từ file Parquet và chuyển thành DataFrame df = pl.read_parquet("data.parquet") # In ra DataFrame print(df)
- Arrow Arrow là một định dạng dữ liệu chuẩn cho việc truyền tải dữ liệu giữa các ứng dụng khác nhau. Nó hỗ trợ nhiều ngôn ngữ lập trình như Python, R, Java… Ví dụ, ta có thể đọc dữ liệu từ file “data.arrow” bằng cách sử dụng hàm
pl.read_arrow()
:
import polars as pl # Đọc dữ liệu từ file Arrow và chuyển thành DataFrame df = pl.read_arrow("data.arrow") # In ra DataFrame print(df)
- ORC (Optimized Row Columnar) ORC là một định dạng file hiệu quả cho việc lưu trữ và truy xuất dữ liệu trong các ứng dụng Big Data. Nó hỗ trợ việc lưu trữ dữ liệu cấu trúc hoặc phi cấu trúc và cho phép truy xuất dữ liệu phân tán. Ví dụ, ta có thể đọc dữ liệu từ file “data.orc” bằng cách sử dụng hàm
pl.read_orc()
:
import polars as pl # Đọc dữ liệu từ file ORC và chuyển thành DataFrame df = pl.read_orc("data.orc") # In ra DataFrame print(df)
- Avro Avro là một định dạng dữ liệu được thiết kế để hỗ trợ việc truyền tải dữ liệu giữa các ứng dụng khác nhau, phù hợp cho việc lưu trữ các bản ghi có cấu trúc. Ví dụ, ta có thể đọc dữ liệu từ file “data.avro” bằng cách sử dụng hàm
pl.read_avro()
:
import polars as pl # Đọc dữ liệu từ file Avro và chuyển thành DataFrame df = pl.read_avro("data.avro") # In ra DataFrame print(df)
Thao tác với DataFrame
Dưới đây là mô tả một số thao tác cơ bản với DataFrame sử dụng Polars.
Lấy thông tin cấu trúc DataFrame
Để lấy thông tin cấu trúc của DataFrame, ta có thể sử dụng phương thức schema()
của đối tượng DataFrame. Phương thức này trả về một đối tượng Schema, chứa thông tin về các cột của DataFrame, bao gồm tên, kiểu dữ liệu và giá trị mặc định (nếu có).
import polars as pl # Tạo DataFrame df = pl.DataFrame({ 'name': ['Alice', 'Bob', 'Charlie'], 'age': [25, 30, 35], 'city': ['New York', 'Paris', 'London'] }) # Lấy thông tin cấu trúc schema = df.schema() # In ra thông tin cấu trúc print(schema)
Kết quả:
shape: (rows: 3, cols: 3) ┌─────────┬───────┬──────────┐ │ column │ type │ nullable │ │ --- │ --- │ --- │ │ str │ str │ true │ │ age │ i64 │ true │ │ city │ str │ true │ └─────────┴───────┴──────────┘
Lọc dữ liệu
Để lọc dữ liệu trong DataFrame, ta có thể sử dụng phương thức filter()
của đối tượng DataFrame. Phương thức này nhận vào một biểu thức logic và trả về một DataFrame mới chỉ chứa các dòng thỏa mãn biểu thức đó.
Ví dụ:
import polars as pl # Tạo DataFrame df = pl.DataFrame({ 'name': ['Alice', 'Bob', 'Charlie'], 'age': [25, 30, 35], 'city': ['New York', 'Paris', 'London'] }) # Lọc dữ liệu filtered = df.filter(pl.col('age') > 25) # In ra kết quả print(filtered)
Kết quả:
shape: (3, 2) ┌─────────┬─────┐ │ name ┆ age │ │ --- ┆ --- │ │ str ┆ i64 │ ╞═════════╪═════╡ │ Alice ┆ 25 │ │ Bob ┆ 30 │ │ Charlie ┆ 35 │ └─────────┴─────┘
Thêm cột mới
Để thêm cột mới vào DataFrame, ta có thể sử dụng phương thức with_column()
của đối tượng DataFrame. Phương thức này nhận vào tên cột mới và giá trị của cột đó (thường là một biểu thức sử dụng các cột hiện có của DataFrame) và trả về một DataFrame mới với cột mới đã được thêm vào.
import polars as pl # Tạo DataFrame df = pl.DataFrame({ 'name': ['Alice', 'Bob', 'Charlie'], 'age': [25, 30, 35], 'city': ['New York', 'Paris', 'London'] }) # Thêm cột mới df_new = df.with_column('age_plus_10', pl.col('age') + 10) # In ra kết quả print(df_new)
Xoá cột
Để xóa một cột trong DataFrame sử dụng polars, ta có thể sử dụng phương thức DataFrame.drop()
.
Ví dụ xoá cột age:
import polars as pl df = pl.DataFrame({ 'name': ['Alice', 'Bob', 'Charlie'], 'age': [25, 30, 35], 'city': ['New York', 'Paris', 'London'] }) df = df.drop('age') print(df)
Nếu muốn xoá nhiều cột, truyền vào 1 list các cột là được, ví dụ: df.drop(['name', 'age'])
.
Sắp xếp dữ liệu
Để sắp xếp dữ liệu trong DataFrame sử dụng polars, ta có thể sử dụng phương thức DataFrame.sort()
. Cú pháp:
DataFrame.sort(by_column: Union[str, List[str]], reverse: bool = False) -> polars.DataFrame
Trong đó:
by_column
: Tên của cột hoặc danh sách các tên cột theo đó ta muốn sắp xếp dữ liệu. Nếu truyền vào danh sách các tên cột thì việc sắp xếp sẽ được ưu tiên theo thứ tự các tên cột có ở đầu danh sách.reverse
: Giá trị boolean quyết định việc sắp xếp theo chiều giảm dần hay tăng dần. Mặc định làFalse
.
Ví dụ: Sắp xếp DataFrame “df” theo cột “age”
import polars as pl df = pl.DataFrame({ 'name': ['Alice', 'Bob', 'Charlie'], 'age': [30, 25, 35], 'city': ['New York', 'Paris', 'London'] }) sorted_df = df.sort('age') print(sorted_df)
Nếu muốn thêm cột cần sắp xếp, hãy truyền vào 1 list theo thứ tự ưu tiên. Ví dụ dưới đây
sorted_df = df.sort(['age', 'city'])
sẽ sắp xếp theo tuổi, sau đó sắp xếp theo thành phố.
Câu lệnh groupby
Trong Polars, groupby
và aggregate
là hai hàm rất quan trọng được sử dụng để tóm tắt các dữ liệu trong một DataFrame.
Groupby
cho phép chúng ta nhóm các hàng của DataFrame theo các cột cụ thể. Ví dụ, nếu chúng ta có một DataFrame với các cột ‘Tên’, ‘Năm sinh’ và ‘Địa chỉ’, chúng ta có thể sử dụng groupby
để nhóm các hàng theo địa chỉ, sau đó tính trung bình của các giá trị trong mỗi nhóm.
Ví dụ về cách sử dụng groupby
:
import polars as pl df = pl.DataFrame({ 'address': ['Ha Noi', 'Ha Noi', 'Hai Phong', 'Hai Phong'], 'age': [20, 30, 25, 40], 'height': [160, 170, 180, 175] }) grouped = df.groupby('address') mean_df = grouped.mean() print(mean_df)
Kết quả sẽ là một DataFrame mới với hai cột: ‘age’ và ‘height’, được tính trung bình cho mỗi địa chỉ (address).
shape: (2, 3) ┌───────────┬──────┬────────┐ │ address ┆ age ┆ height │ │ --- ┆ --- ┆ --- │ │ str ┆ f64 ┆ f64 │ ╞═══════════╪══════╪════════╡ │ Ha Noi ┆ 25.0 ┆ 165.0 │ │ Hai Phong ┆ 32.5 ┆ 177.5 │ └───────────┴──────┴────────┘
Xem thêm: Phân loại văn bản tiếng Việt sử dụng machine learning
Kiểu dữ liệu trong Polars
Các kiểu dữ liệu bao gồm:
- Int8: Số nguyên có dấu 8 bit.
- Int16: Số nguyên có dấu 16 bit.
- Int32: Số nguyên có dấu 32 bit.
- Int64: Số nguyên có dấu 64 bit.
- UInt8: Số nguyên không dấu 8 bit.
- UInt16: Số nguyên không dấu 16 bit.
- UInt32: Số nguyên không dấu 32 bit.
- UInt64: Số nguyên không dấu 64-bit.
- Float32: Dấu phẩy động 32 bit.
- Float64: Dấu chấm động 64-bit.
- Boolean: Kiểu Boolean.
- Utf8: Dữ liệu chuỗi
- Binary: Lưu trữ dữ liệu dưới dạng byte.
- List: Một mảng danh sách chứa một mảng con chứa các giá trị danh sách và một mảng offset.
- Struct: Một mảng cấu trúc được biểu diễn dưới dạng Vec<Series> và rất hữu ích để đóng gói nhiều giá trị/không đồng nhất trong một cột.
- Object: Một loại dữ liệu được hỗ trợ hạn chế có thể là bất kỳ giá trị nào.
Date: Biểu diễn ngày, được biểu thị bên trong dưới dạng ngày kể từ kỷ nguyên UNIX được mã hóa bởi số nguyên có dấu ký 32 bit.
Datetime: Biểu diễn ngày giờ, được biểu diễn bên trong dưới dạng micro giây kể từ kỷ nguyên UNIX được mã hóa bởi số nguyên có dấu ký 64 bit.
Duration: Một loại timedelta, được biểu diễn bên trong dưới dạng micro giây. Được tạo khi trừ Date/Datetime.
Time: Biểu diễn thời gian, biểu diễn bên trong dưới dạng nano giây kể từ midnight.
Xử lý dữ liệu bị thiếu
Trong quá trình xử lý dữ liệu, chúng ta thường gặp phải các giá trị null hoặc thiếu trong dữ liệu, gây khó khăn cho quá trình tính toán và phân tích. Trong bài viết này, chúng ta sẽ tìm hiểu cách xử lý giá trị null trong Polars.
Kiểm tra giá trị NULL
import polars as pl # Tạo một dataframe với giá trị null df = pl.DataFrame({ 'A': [1, 2, None, 4], 'B': ['a', None, 'b', 'c'] }) # Kiểm tra giá trị null is_null = df.null_count() print(is_null)
Kết quả:
shape: (1, 2) ┌─────┬─────┐ │ A ┆ B │ │ --- ┆ --- │ │ u32 ┆ u32 │ ╞═════╪═════╡ │ 1 ┆ 1 │ └─────┴─────┘
Bổ sung dữ liệu bị thiếu
Điền một giá trị cụ thể, ví dụ điền giá trị 2 cho các ô null trong cột A
import polars as pl # Tạo một dataframe với giá trị null df = pl.DataFrame({ 'A': [1, 2, None, 4], 'B': ['a', None, 'b', 'c'] }) # Kiểm tra giá trị null is_null = df.null_count() print(is_null) # Điền giá trị 2 cho các giá trị null ở cột A fill_literal_df = ( df.with_columns( pl.col('A').fill_null( pl.lit(2), ), ), ) print(fill_literal_df)
Kết quả:
shape: (1, 2) ┌─────┬─────┐ │ A ┆ B │ │ --- ┆ --- │ │ u32 ┆ u32 │ ╞═════╪═════╡ │ 1 ┆ 1 │ └─────┴─────┘ (shape: (4, 2) ┌─────┬──────┐ │ A ┆ B │ │ --- ┆ --- │ │ i64 ┆ str │ ╞═════╪══════╡ │ 1 ┆ a │ │ 2 ┆ null │ │ 2 ┆ b │ │ 4 ┆ c │ └─────┴──────┘,)
Bạn cũng có thể bổ sung các ô thiếu giá trị theo một số chiến lược
import polars as pl # Tạo một dataframe với giá trị null df = pl.DataFrame({ 'A': [1, 2, None, 4], 'B': ['a', None, 'b', 'c'] }) # Điền giá trị trung vị cho các giá trị null ở cột A fill_median_df = df.with_columns( pl.col("A").fill_null(pl.median("A")), ) print(fill_median_df)
Kết quả:
shape: (4, 2) ┌─────┬──────┐ │ A ┆ B │ │ --- ┆ --- │ │ f64 ┆ str │ ╞═════╪══════╡ │ 1.0 ┆ a │ │ 2.0 ┆ null │ │ 2.0 ┆ b │ │ 4.0 ┆ c │ └─────┴──────┘
Hoặc sử dụng nội suy
import polars as pl # Tạo một dataframe với giá trị null df = pl.DataFrame({ 'A': [1, 2, None, 4], 'B': ['a', None, 'b', 'c'] }) # Điền giá trị trung vị cho các giá trị null ở cột A fill_interpolation_df = df.with_columns( pl.col("A").interpolate(), ) print(fill_interpolation_df)
hoặc forward
fill_forward_df = df.with_columns( pl.col("col2").fill_null(strategy="forward"), ) print(fill_forward_df)
Xem thêm: Beam search là gì? Vai trò của beam search trong NLP
Lưu/xuất dữ liệu
Bạn có thể xuất dữ liệu ra csv file giống như hàm to_csv
của pandas. Với polars thì sẽ là write_csv
import polars as pl # create a dataframe df = pl.DataFrame({ 'Name': ['Alice', 'Bob', 'Charlie'], 'Age': [25, 30, 35], 'Gender': ['Female', 'Male', 'Male'] }) # save the dataframe to a CSV file df.write_csv('my_dataframe.csv')
Ngoài CSV ra, bạn còn có thể xuất ra nhiều định dạng khác bao gồm JSON, Feather/ IPC, Parquet, Excel, …
Dưới đây là một ví dụ ghi ra file excel:
import polars as pl # create a dataframe df = pl.DataFrame({ 'Name': ['Alice', 'Bob', 'Charlie'], 'Age': [25, 30, 35], 'Gender': ['Female', 'Male', 'Male'] }) # save the dataframe to a CSV file df.write_excel('my_dataframe.xlsx')
Tài liệu tham khảo
- Polars documentation: https://pola-rs.github.io/polars-book/
- Github: https://github.com/pola-rs/polars
- Benchmark, compare with other libs: https://www.pola.rs/benchmarks.html
Để lại một bình luận