NUMPY
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.

Fancy Indexing trong NumPy

Trong các bài trước, chúng ta đã làm quen với một số phương thức để truy cập một phần của mảng như array slicing (vd: arr[:5]), masks (vd: arr[arr > 5]). Trong bài này, chúng ta sẽ tìm hiểu thêm về một cách thức truy cập khác được gọi là Fancy Indexing.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Nó cũng giống như các cách truy cập khác nhưng với tham số truyền vào là các mảng chỉ số, điều này sẽ khiến cho ta làm việc với các mảng dữ liệu lớn trở nên dễ dàng hơn.

1. Giới thiệu về Fancy Indexing

Cơ chế của Fancy Indexing nhìn chung khá đơn giản: chúng ta truyền vào một mảng chứa các vị trí của các phần tử cần lấy.

Ví dụ:

Bài viết này được đăng tại [free tuts .net]

In[1]
import numpy as np
arr = np.random.randint(100, size=10)
print(arr)
Out[1]
[61 42 66 51 41  9 53 14 63 64]

Giả sử chúng ta muốn lấy 3 phần tử ở 3 vị trí khác nhau, thông thường thì ta sẽ làm thế này:

In[2]
sub_arr = [arr[2], arr[5], arr[8]]
print(sub_arr)
Out[2]
[66, 9, 63]

Với Fancy Indexing, ta có thể truyền mảng chứa vị trí các phần tử (mảng chỉ mục) và nhận giá trị tương đương trên:

In[3]
ind_arr = [2, 5, 8]
sub_arr = arr[ind_arr]
print(sub_arr)
Out[3]
[66  9 63]

Một điều quan trọng trong Fancy Indexing chính là mảng trả về sẽ có shape tương ứng với shape của mảng chỉ mục chứ không phải là mảng ban đầu:

In[4]
index_arr = np.array([[1, 2],
                      [8, 9]])
sub_arr = arr[index_arr]
print(sub_arr)
Out[4]
[[42 66]
 [63 64]]

Fancy Indexing cũng hoạt động tương tự với mảng nhiều chiều:

In[5]
arr = np.arange(16).reshape(4, 4)
print("arr = ", arr)

# Mảng row (hàng) và cột (col) chứa vị trí của các phần tử cần trích xuất
# Các phần tử gồm arr[0, 1], arr[1, 2] và arr[2, 3]
row = [0, 1, 2]
col = [1, 2, 3]

sub_arr = arr[row, col] 

print("sub_arr = ", sub_arr)
Out[5]
arr =  [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
sub_arr =  [ 1  6 11]

Trong Fancy Indexing, điều mà bạn luôn cần nhớ đó chính là mảng trả về sẽ luôn có shape tương ứng với shape của mảng chỉ mục chứ không phải là mảng ban đầu.

2. Combined Indexing (Chỉ mục kết hợp)

Fancy Indexing còn có một tính năng rất mạnh đó là nó có thể kết hợp với những kiểu truy cập mảng mà chúng ta đã học, khiến cho ta có thể thao tác nhiều phép toán phức tạp chỉ trong một dòng code. Chúng ta sẽ đến với từng trường hợp cụ thể

Fancy Indexing và chỉ mục đơn giản

Ta có thể kết hợp kiểu chỉ mục truyền thống mà ta thường dùng để lấy 1 phần tử và kết hợp với fancy indexing như sau:

In[6]
arr = np.arange(16).reshape(4, 4)
print("arr = ", arr)

#Lấy các phần tử arr[3, 1], arr[3, 2] và arr[3, 3]
sub_arr = arr[3, [1, 2, 3]]
print("sub_arr = ", sub_arr)
Out[6]
arr =  [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

sub_arr =  [13 14 15]

Fancy Indexing và Array Slicing

Ta có thể kết hợp giữa Fancy Indexing và Array Slicing (đã nói ở bài 2) như sau:

In[7]
print("arr = ", arr)

# Lấy tất cả các phần tử nằm tại hàng >= 1 và các cột = 1, 2, 3 tương ứng
sub_arr = arr[1:, [1, 2, 3]]
print("sub_arr = ", sub_arr)
Out[7]
arr =  [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
sub_arr =  [[ 5  6  7]
 [ 9 10 11]
 [13 14 15]]

Hoặc phức tạp hơn với mảng 3 chiều:

In[8]
arr = np.arange(18).reshape(3, 2, 3)
print("arr = ", arr)

print("sub_arr = ", arr[0, 1:, [0, 1]])
Out[8]
arr =  [[[ 0  1  2]
  [ 3  4  5]]

 [[ 6  7  8]
  [ 9 10 11]]

 [[12 13 14]
  [15 16 17]]]

sub_arr =  [[3]
 [4]]

Fancy Indexing và Masks

Và cuối cùng, ta có thể kết hợp giữa Fancy Indexing và Masks:

In[8]
arr = np.arange(16).reshape(4, 4)

print("arr = ", arr)

masks = arr[0, :] % 2 == 0
print("masks =", masks)

arr[:, masks]
Out[9]
arr =  [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
masks = [ True False  True False]

array([[ 0,  2],
       [ 4,  6],
       [ 8, 10],
       [12, 14]])

Ứng dụng Fancy Indexing trong chia tập dữ liệu

Chia tập dữ liệu là một trong những công việc khá phổ biến trong machine learning, trong đó chúng ta sẽ chia tập dữ liệu của chúng ta thành 2 phần: train và test nếu bạn chưa biết gì thì cũng đừng lo vì đây chỉ là một ví dụ của mình minh hoạ cho ứng dụng của Fancy Indexing. Giả sử mình sẽ tạo 1 tập dữ liệu mẫu và dùng matplotlib để biểu thị như sau:

In[10]
import matplotlib.pyplot as plt
import seaborn; seaborn.set() # Thư viện chia cột đơn vị cho matplotlib

# Tạo mảng 2 chiều giá trị từ 1 -> 200
X = np.arange(200).reshape(100, 2)

# Thêm nhiễu cho mảng
noise = np.random.uniform(1, 30, X.shape)
X = X + noise

plt.scatter(X[:, 0], X[:, 1])

1 png

Bây giờ chúng ta sẽ lấy ngẫu nhiên các phần tử trong mảng với tỉ lệ là 80/20 (80% cho train, 20% cho test, với số lượng 200 phần tử thì ta sẽ lấy ngẫu nhiên 40 phần tử trong mảng X):

In[11]
random_indices = np.random.choice(X.shape[0], 40, replace=False)
print("Vị trí các phần tử ngẫu nhiên: ", random_indices)
plt.figure(figsize=(10, 10))
# Fancy indexing
selection = X[random_indices]

# Hiển thị dữ liệu lên biểu đồ phân tán, với các phần tử bị làm mờ đi
plt.scatter(X[:, 0], X[:, 1], alpha=0.3)

# Tô tròn các giá trị được chọn ngẫu nhiên bằng fancy indexing
plt.scatter(selection[:, 0], selection[:, 1], s=200, facecolors='none', edgecolors='r');
Out[11]
Vị trí các phần tử ngẫu nhiên:  [12  6 85 20 56 70 96 72 88 60 27 83 98 64  2 74 95 38 58 29 79 21 81 76
  7 94 57 52 23 91  4 66 68 50 87 84 39  3 78 16]

2 png

3. Thay đổi giá trị với Fancy Indexing

Tương tự với việc truy cập vào các mảng con, Fancy Indexing cũng có thể dùng để thay đổi giá trị tại các điểm, ví dụ:

In[12]
x = np.array([1, 3, 5, 7, 9])
print("X = ", x)

i = np.array([0, 2, 4])
x[i] = 35

print("X = ", x)
Out[12]
X =  [1 3 5 7 9]
X =  [35  3 35  7 35]

Lưu ý là bạn cần quan tâm đến lựa chọn đúng shape của mảng chỉ mục, nếu lựa chọn sai sẽ dễ dẫn đến nhiều kết quả không mong muốn, chẳng hạn:

In[13]
x = np.zeros(10)
print("x = ", x)
i = [[0, 0]]

x[i] = [2, 3]

print("x = ", x)
Out[13]
x =  [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
x =  [3. 0. 0. 0. 0. 0. 0. 0. 0. 0.]

Chúng ta có thể thấy mảng x sau khi được thay đổi không chứa phần tử nào có giá trị bằng 2, lý do chính là vì mảng chỉ mục i. Khi thực hiện phép toán, đầu tiên nó sẽ được gán x[0] = 2, sau đó là x[0] = 3, vì vậy tất nhiên nó chỉ có phần tử = 3 mà thôi.

4. Tổng kết

Qua bài này ta đã tìm hiểu được về Fancy Indexing trong NumPy là gì và cách ứng dụng nó. Đây là một tính năng rất hữu ích giúp rút gọn code của bạn đi rất nhiều. Trong bài tới ta sẽ tìm hiểu về bài cuối cùng trong chương NumPy là Dữ liệu có cấu trúc trong NumPy nhé. Hẹn gặp các bạn ở bài tới.

Cùng chuyên mục:

Cách thêm Progress Bar trong Python với chỉ một dòng Code

Cách thêm Progress Bar trong Python với chỉ một dòng Code

Toán tử Walrus Operator- Tính năng mới trong Python 3.8

Toán tử Walrus Operator- Tính năng mới trong Python 3.8

Cách nạp dữ liệu Machine Learning từ File trong Python

Cách nạp dữ liệu Machine Learning từ File trong Python

Hướng dẫn sử dụng Google Sheets API với Python

Hướng dẫn sử dụng Google Sheets API với Python

Xây dựng  web Python tự động hóa Twitter | Flask, Heroku, Twitter API & Google Sheets API

Xây dựng web Python tự động hóa Twitter | Flask, Heroku, Twitter API & Google Sheets API

Xây dựng Web Machine Learning đẹp mắt với Streamlit và Scikit-learn trong Python

Xây dựng Web Machine Learning đẹp mắt với Streamlit và Scikit-learn trong Python

Hướng dẫn tạo Chatbot đơn giản bằng PyTorch

Hướng dẫn tạo Chatbot đơn giản bằng PyTorch

11 mẹo và thủ thuật để viết Code Python hiệu quả hơn

11 mẹo và thủ thuật để viết Code Python hiệu quả hơn

Hướng dẫn làm ứng dụng TODO với Flask dành cho người mới bắt đầu trong Python

Hướng dẫn làm ứng dụng TODO với Flask dành cho người mới bắt đầu trong Python

Hướng dẫn viết Snake Game bằng Python

Hướng dẫn viết Snake Game bằng Python

Cách sử dụng chế độ interactive trong Python

Cách sử dụng chế độ interactive trong Python

Cách sử dụng Python Debugger với hàm breakpoint()

Cách sử dụng Python Debugger với hàm breakpoint()

Xây dựng ứng dụng Web Style Transfer với PyTorch và Streamlit

Xây dựng ứng dụng Web Style Transfer với PyTorch và Streamlit

Cách cài đặt Jupyter Notebook trong môi trường Conda và thêm Kernel

Cách cài đặt Jupyter Notebook trong môi trường Conda và thêm Kernel

Hướng dẫn xây dựng ứng dụng dự đoán giá cổ phiếu bằng Python

Hướng dẫn xây dựng ứng dụng dự đoán giá cổ phiếu bằng Python

Hướng dẫn tạo ứng dụng AI hội thoại với NVIDIA Jarvis trong Python

Hướng dẫn tạo ứng dụng AI hội thoại với NVIDIA Jarvis trong Python

Hỗ trợ Async trong Django 3.1

Hỗ trợ Async trong Django 3.1

8 mẹo tái cấu trúc Python giúp mã sạch hơn và Pythonic

8 mẹo tái cấu trúc Python giúp mã sạch hơn và Pythonic

Ý nghĩa của if __name__ ==

Ý nghĩa của if __name__ == "__main__" trong Python

Cách xóa phần tử trong danh sách Python

Cách xóa phần tử trong danh sách Python

Top