Sử dụng Boolean Arrays và Masks trong NumPy để Phân tích Dữ liệu với AI
Chào mừng các bạn đến với bài viết mới trên blog của tôi! Trong bài viết này, chúng ta sẽ khám phá cách sử dụng Boolean arrays và masks trong NumPy – một công cụ mạnh mẽ trong Python để xử lý dữ liệu, đặc biệt hữu ích trong các ứng dụng AI và khoa học dữ liệu. Chúng ta sẽ đi qua các khái niệm cơ bản, ví dụ thực tế với dữ liệu mưa ở Seattle, và cách áp dụng chúng để trả lời các câu hỏi phân tích dữ liệu một cách hiệu quả. Hãy cùng bắt đầu!
Giới thiệu về Boolean Masks trong NumPy
Trong lĩnh vực AI và khoa học dữ liệu, việc xử lý dữ liệu nhanh chóng và hiệu quả là một yêu cầu quan trọng. Một trong những kỹ thuật mạnh mẽ mà NumPy cung cấp là sử dụng Boolean masks để kiểm tra và thao tác với các giá trị trong mảng. Khi bạn muốn trích xuất, sửa đổi, đếm hoặc thao tác với dữ liệu dựa trên một tiêu chí cụ thể – ví dụ: đếm số giá trị lớn hơn một ngưỡng nào đó hoặc loại bỏ các giá trị ngoại lai – thì Boolean masking thường là cách tiếp cận hiệu quả nhất.
Ví dụ: Đếm số ngày mưa ở Seattle
Hãy tưởng tượng bạn có một tập dữ liệu về lượng mưa mỗi ngày trong một năm tại một thành phố, chẳng hạn như Seattle vào năm 2014. Chúng ta sẽ sử dụng Pandas để tải dữ liệu này và chuyển đổi thành một mảng NumPy:
import numpy as np
import pandas as pd
# Sử dụng pandas để trích xuất lượng mưa (đơn vị inch) dưới dạng mảng NumPy
rainfall = pd.read_csv('data/Seattle2014.csv')['PRCP'].values
inches = rainfall / 254.0 # Chuyển từ 1/10mm sang inches
inches.shape
Kết quả: (365,)
, cho thấy mảng chứa 365 giá trị, tương ứng với lượng mưa mỗi ngày từ ngày 1/1 đến 31/12/2014.
Để có cái nhìn tổng quan, chúng ta có thể vẽ histogram bằng Matplotlib:
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn; seaborn.set() # Thiết lập kiểu đồ thị
plt.hist(inches, 40);
Histogram này cho thấy phần lớn các ngày ở Seattle có lượng mưa gần bằng 0 trong năm 2014. Tuy nhiên, nó không trả lời được các câu hỏi chi tiết như: Có bao nhiêu ngày mưa trong năm? Lượng mưa trung bình trong những ngày mưa là bao nhiêu? Có bao nhiêu ngày có lượng mưa trên 0.5 inch?
Đào sâu vào dữ liệu
Một cách thủ công để trả lời các câu hỏi này là lặp qua dữ liệu và tăng biến đếm khi gặp giá trị trong phạm vi mong muốn. Tuy nhiên, cách này rất chậm và không hiệu quả. Thay vào đó, NumPy cung cấp các ufuncs (universal functions) để thực hiện phép so sánh theo từng phần tử, giúp chúng ta trả lời các câu hỏi này nhanh chóng thông qua masking.
Toán tử so sánh như ufuncs
NumPy không chỉ hỗ trợ các toán tử số học (+
, -
, *
, /
) mà còn triển khai các toán tử so sánh như <
(nhỏ hơn) và >
(lớn hơn) dưới dạng ufuncs. Kết quả của các toán tử này là một mảng kiểu Boolean. Dưới đây là các ví dụ:
x = np.array([1, 2, 3, 4, 5])
x < 3 # Kết quả: array([ True, True, False, False, False], dtype=bool)
x > 3 # Kết quả: array([False, False, False, True, True], dtype=bool)
x <= 3 # Kết quả: array([ True, True, True, False, False], dtype=bool)
x >= 3 # Kết quả: array([False, False, True, True, True], dtype=bool)
x != 3 # Kết quả: array([ True, True, False, True, True], dtype=bool)
x == 3 # Kết quả: array([False, False, True, False, False], dtype=bool)
Bạn cũng có thể so sánh hai mảng hoặc kết hợp các biểu thức:
(2 * x) == (x ** 2) # Kết quả: array([False, True, False, False, False], dtype=bool)
Danh sách các toán tử so sánh và ufuncs tương ứng:
Operator | Equivalent ufunc | Operator | Equivalent ufunc |
---|---|---|---|
== | np.equal | != | np.not_equal |
< | np.less | <= | np.less_equal |
> | np.greater | >= | np.greater_equal |
Ví dụ với mảng 2 chiều:
rng = np.random.RandomState(0)
x = rng.randint(10, size=(3, 4))
print(x)
# Kết quả:
# array([[5, 0, 3, 3],
# [7, 9, 3, 5],
# [2, 4, 7, 6]])
x < 6
# Kết quả:
# array([[ True, True, True, True],
# [False, False, True, True],
# [ True, True, False, False]], dtype=bool)
Làm việc với Boolean Arrays
Với một Boolean array, bạn có thể thực hiện nhiều thao tác hữu ích. Hãy tiếp tục với mảng x
:
Đếm số phần tử
Để đếm số giá trị True
, sử dụng np.count_nonzero
:
np.count_nonzero(x < 6) # Kết quả: 8
Hoặc dùng np.sum
, trong đó False = 0
và True = 1
:
np.sum(x < 6) # Kết quả: 8
Bạn cũng có thể đếm theo hàng hoặc cột:
np.sum(x < 6, axis=1) # Kết quả: array([4, 2, 2])
Kiểm tra điều kiện
Sử dụng np.any
và np.all
để kiểm tra:
np.any(x > 8) # Có giá trị nào lớn hơn 8 không? Kết quả: True
np.any(x < 0) # Có giá trị nào nhỏ hơn 0 không? Kết quả: False
np.all(x < 10) # Tất cả giá trị có nhỏ hơn 10 không? Kết quả: True
np.all(x == 6) # Tất cả giá trị có bằng 6 không? Kết quả: False
np.all(x < 8, axis=1) # Tất cả giá trị trong mỗi hàng có nhỏ hơn 8 không?
# Kết quả: array([ True, False, True], dtype=bool)
Lưu ý: Hãy dùng np.sum()
, np.any()
, np.all()
thay vì các hàm Python mặc định (sum()
, any()
, all()
) để tránh lỗi với mảng đa chiều.
Toán tử Boolean
Để kết hợp các điều kiện, NumPy sử dụng các toán tử bitwise như &
(AND), |
(OR), ^
(XOR), và ~
(NOT):
np.sum((inches > 0.5) & (inches < 1)) # Kết quả: 29 (số ngày mưa từ 0.5 đến 1 inch)
np.sum(~((inches <= 0.5) | (inches >= 1))) # Kết quả tương đương: 29
Danh sách toán tử Boolean và ufuncs tương ứng:
Operator | Equivalent ufunc | Operator | Equivalent ufunc |
---|---|---|---|
& | np.bitwise_and | | | np.bitwise_or |
^ | np.bitwise_xor | ~ | np.bitwise_not |
Áp dụng vào dữ liệu mưa:
print("Number days without rain: ", np.sum(inches == 0)) # 215
print("Number days with rain: ", np.sum(inches != 0)) # 150
print("Days with more than 0.5 inches:", np.sum(inches > 0.5)) # 37
print("Rainy days with < 0.2 inches :", np.sum((inches > 0) & (inches < 0.2))) # 75
Boolean Arrays như Masks
Một cách mạnh mẽ hơn là dùng Boolean arrays như masks để chọn các tập con dữ liệu. Với mảng x
:
x[x < 5] # Kết quả: array([0, 3, 3, 3, 2, 4])
Áp dụng vào dữ liệu mưa:
# Tạo mask cho các ngày mưa
rainy = (inches > 0)
# Tạo mask cho các ngày mùa hè (từ ngày 172 đến 261)
days = np.arange(365)
summer = (days > 172) & (days < 262)
print("Median precip on rainy days in 2014 (inches): ", np.median(inches[rainy]))
# Kết quả: 0.194881889764
print("Median precip on summer days in 2014 (inches): ", np.median(inches[summer]))
# Kết quả: 0.0
print("Maximum precip on summer days in 2014 (inches): ", np.max(inches[summer]))
# Kết quả: 0.850393700787
print("Median precip on non-summer rainy days (inches):", np.median(inches[rainy & ~summer]))
# Kết quả: 0.200787401575
Phân biệt and/or
và &/|
Một điểm dễ nhầm lẫn là sự khác biệt giữa and
/or
và &
/|
.
and
vàor
đánh giá tính đúng/sai của toàn bộ đối tượng:
bool(42 and 0) # False
bool(42 or 0) # True
&
và|
hoạt động trên từng bit:
bin(42 & 59) # '0b101010'
bin(42 | 59) # '0b111011'
Với Boolean arrays, luôn dùng &
và |
:
x = np.arange(10)
(x > 4) & (x < 8) # Kết quả: array([False, False, False, False, False, True, True, True, False, False])
Dùng and
hoặc or
sẽ gây lỗi ValueError
.
Kết luận
Bằng cách kết hợp Boolean operations, masking, và aggregations, chúng ta có thể phân tích dữ liệu một cách nhanh chóng và hiệu quả – một kỹ năng quan trọng trong AI và khoa học dữ liệu. Hy vọng bài viết này đã giúp bạn hiểu rõ hơn về cách tận dụng NumPy để xử lý dữ liệu. Hãy thử áp dụng vào dự án của bạn và chia sẻ kết quả nhé!