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.

Xử lý dữ liệu trên mảng cơ bản với Numpy

Trong bài này mình sẽ trình bày cách xử lý dữ liệu trên mảng với các thao tác như truy cập vào mảng con, chia (split), biến đổi kích thước (reshape), nối (join) và sắp xếp (sorting) mảng.

1. Thuộc tính mảng NumPy

Trước khi đi đến các phần xử lý mảng, ta sẽ tìm hiểu về các thuộc tính mảng NumPy trước. Chúng ta sẽ lần lượt tạo 3 mảng:

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.
import numpy as np

a1 = np.random.randint(10, size=5) # Mảng 1 chiều
a2 = np.random.randint(10, size=(3, 4)) # Mảng 2 chiều
a3 = np.random.randint(10, size=(3, 4, 5)) # Mảng 3 chiều

Mỗi mảng sẽ có 3 thuộc tính chính:

  • ndim: số chiều của mảng
  • shape: kích thước của từng chiều
  • size: tổng kích thước của mảng (bằng số lượng phần tử trong mảng)

Chẳng hạn, ta có thể kiểm tra thuộc tính của mảng a2:

In[2]:
print("a2 ndim: ", a2.ndim)
print("a2 shape: ", a2.shape)
print("a2 size: ", a2.size)
Out[2]:
a2 ndim:  2
a2 shape:  (3, 4)
a2 size:  12

bai3 1 gif

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

Một thuộc tính khác mà ta cũng cần quan tâm đó là dtype, thuộc tính này biểu thị kiểu dữ liệu của mảng (ta đã nói về kiểu dữ liệu ở bài 02):

In[3]
print("a2 dtype: ", a2.dtype)
Out[3]:
a2 dtype:  int32

Thuộc tính cuối cùng mình muốn đề cập là itemsize (hiển thị kích thước tính bằng byte của mỗi mảng phần tử con) và nbytes (hiển thị tổng kích thước tính bằng byte của mảng), đây là thuộc tính khá hữu dụng nếu chúng ta muốn quan sát mảng đang chiếm bộ nhớ như thế nào, chẳng hạn:

print("itemsize:", a3.itemsize, " bytes")
print("nbytes:", a3.nbytes, " bytes")
Out[4]
itemsize: 4  bytes
nbytes: 240  bytes

bai3 2 gif

2. Array Indexing

Nếu như bạn đã quen thuộc với cách truy cập các phần tử của List trong Python, thì với NumPy cũng khá tương tự.

Ví dụ:

Lệnh: a1

Out[5]
array([0, 9, 1, 1, 0])
In[6]
a1[3]
Out[6]
1

Với mảng đa chiều thì cũng tương tự, bạn chỉ cần thêm dấu phẩy để ngăn cách các vị trị tương ứng:

Lệnh: a3

Out
array([[[4, 5, 7, 9, 0],
        [8, 7, 6, 6, 2],
        [3, 4, 8, 6, 2],
        [9, 3, 0, 7, 5]],

       [[8, 1, 1, 8, 8],
        [1, 4, 6, 4, 9],
        [2, 8, 3, 3, 4],
        [8, 1, 1, 4, 4]],

       [[5, 2, 5, 0, 7],
        [0, 4, 1, 5, 1],
        [4, 6, 0, 6, 6],
        [4, 6, 2, 6, 6]]])

Ta cũng có thể chỉnh sửa trực tiếp giá trị của phần tử qua index:

In[10]:
a3[0,0,0] = 0
a3
Out[10]:
array([[[0, 5, 7, 9, 0],
        [8, 7, 6, 6, 2],
        [3, 4, 8, 6, 2],
        [9, 3, 0, 7, 5]],

       [[8, 1, 1, 8, 8],
        [1, 4, 6, 4, 9],
        [2, 8, 3, 3, 4],
        [8, 1, 1, 4, 4]],

       [[5, 2, 5, 0, 7],
        [0, 4, 1, 5, 1],
        [4, 6, 0, 6, 6],
        [4, 6, 2, 6, 6]]])

Lưu ý quan trọng là như ở bài trước đã đề cập, mảng NumPy phải có chung 1 kiểu dữ liệu có định, do vậy nếu bạn thay đổi một giá trị nào không cùng kiểu dữ liệu thì NumPy sẽ báo lỗi, ví dụ:

In[11]
a3[0,0,1] = "Freetuts"
Out[11]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-11-b9e27521c930> in <module>
----> 1 a3[0,0,1] = "Freetuts"

ValueError: invalid literal for int() with base 10: 'Freetuts'

bai3 3 gif

Hoặc nếu cùng kiểu dữ liệu số thì NumPy sẽ ép giá trị vừa đặt về chung kiểu dữ liệu:

In[12]:
a3[0,0,1] = 1.2345
a3
Out[12]
array([[[0, 1, 1, 5, 5],
        [6, 1, 6, 6, 3],
        [9, 2, 6, 6, 4],
        [4, 9, 8, 6, 6]],

       [[1, 2, 7, 6, 6],
        [5, 0, 4, 4, 4],
        [2, 3, 6, 2, 7],
        [2, 2, 1, 0, 6]],

       [[0, 4, 0, 8, 5],
        [1, 5, 0, 8, 1],
        [9, 7, 8, 0, 9],
        [0, 7, 6, 4, 9]]])

bai3 4 gif

3. Array Slicing

Cũng gần giống như cách mà ta truy cập vào các phần tử trong mảng, NumPy hỗ trợ ta cách truy cập vào mảng con cắt ra từ mảng chính bằng cú pháp sau:

a[start:stop:step]

Nếu như có tham số nào trong 3 tham số trên không được điền, NumPy sẽ mặc định như sau:

  • start = 0
  • stop = kích thước của chiều
  • step = 1

Chúng ta sẽ đi vào các ví dụ cụ thể:

Mảng con 1 chiều

In[13]
x = np.arange(5)
print("x = ", x)

print("Lấy 3 phần tử đầu: ", x[:3])
print("Lấy 3 phần tử ở giữa: ", x[1:4])
print("Lấy các phần tử với bước nhảy = 2", x[::2])
print("Lấy các phần tử với bước nhảy = 2, bắt đầu tại vị trí = 1", x[1::2])

Out[13]
x =  [0 1 2 3 4]
Lấy 3 phần tử đầu:  [0 1 2]
Lấy 3 phần tử ở giữa:  [1 2 3]
Lấy các phần tử với bước nhảy = 2 [0 2 4]
Lấy các phần tử với bước nhảy = 2, bắt đầu tại vị trí = 1 [1 3]

Mảng con nhiều chiều

Mảng con nhiều chiều về cơ bản cũng giống như mảng con 1 chiều, ta xem xét các ví dụ sau:

In[14]
x2 = np.random.randint(10, size=(3, 4))
print("x2 = ", x2)

print("Lấy 2 hàng và 3 cột: ", x2[:2, :3])
print("Lấy tất cả các hàng, còn lấy các cột với bước nhảy là 2: ", x2[:, ::2])
Out[14]
x2 =  [[7 8 6 0]
 [1 5 5 1]
 [1 5 9 2]]
Lấy 2 hàng và 3 cột:  [[7 8 6]
 [1 5 5]]
Lấy tất cả các hàng, còn lấy các cột với bước nhảy là 2:  [[7 6]
 [1 5]
 [1 9]]

Truy xuất mảng cột và hàng

Có một số trường hợp ta chỉ cần lấy 1 cột hoặc một hàng, thì NumPy cũng hỗ trợ việc đó:

In[15]
print("Lấy cột đầu tiên: ", x2[:, 0])
print("Lấy hàng đầu tiên", x2[0, :])
print("Tương tự như x2[0, :]", x2[0])
Out[15]
Lấy cột đầu tiên:  [7 1 1]
Lấy hàng đầu tiên [7 8 6 0]
Tương tự như x2[0, :] [7 8 6 0]

Tạo bản copy với mảng

Một trong những tính năng quan trọng trong NumPy mà khác với List đó là nếu như ta sửa đổi giá trị trong mảng con vừa lấy ra thì nó sẽ thay đổi luôn mảng chính, ví dụ:

In[16]
x2_con = x2[:2, :2] #Lấy mảng 2x2 từ x2
print("x2_con: ", x2_con)
x2_con[1, 1] = 100 #Đặt giá trị = 100 tại vị trí [1, 1]
print("x2_con: ", x2_con)

# x2 đã thay đổi giá trị
print("x2: ", x2)
Out[16]
x2_con:  [[7 8]
 [1 5]]
x2_con:  [[  7   8]
 [  1 100]]
x2:  [[  7   8   6   0]
 [  1 100   5   1]
 [  1   5   9   2]]

Như vậy ta có thể thấy nếu thay đổi giá trị trên mảng con, mảng chính sẽ thay đổi theo. Nếu muốn tránh việc này, ta chỉ cần thêm method copy() như sau:

In[17]
x2_copy = x2[:2, :2].copy() #Thêm phương thức copy()
print("x2_copy:", x2_copy)
x2_copy[1, 1] = 9 #Thay đổi tại vị trí [1, 1]
print("x2_copy: ", x2_copy)
print("x2")
Out[17]
x2_copy: [[  7   8]
 [  1 100]]
x2_copy:  [[7 8]
 [1 9]]
x2

4. Array Reshaping

Biến đổi kích thước (reshape) là một trong những tính năng quan trọng mà ta thường sử dụng khá nhiều. Ví dụ như ta muốn biến mảng 1x9 chứa dãy số từ 1 => 9 thành mảng 3x3:

In[18]
g = np.arange(1, 10).reshape((3, 3))
print("g:", g)
Out[18]
g: [[1 2 3]
 [4 5 6]
 [7 8 9]]

Điều cần chú ý là kích thước reshape phải tương ứng với kích thước của mảng (như ví dụ trên, 1x9 = 3x3).

5. Array Concatenation & Splitting

a. Nối mảng (concatenation)

Có 4 phương thức chính hỗ trợ nối mảng trong NumPy là np.concatenate, np.vstack, np.hstack và np.dstack.

Ta sẽ xem xét các ví dụ về phương thức np.concatenate:

In[20]
x = np.array([0, 1, 2, 3])
y = np.array([3, 2, 1, 0])

print("Phương thức concatenate nhận tham số đầu tiên là một tuple hoặc mảng: ", np.concatenate([x, y]))
print("Phương thức concatenate có thể nối nhiều hơn 2 mảng một lúc: ", np.concatenate([x, y, x, y]))

x_grid = np.array([[1,2,3], 
                   [4,5,6]])
print("Sử dụng cho mảng nhiều chiều, nối 2 mảng theo trục đầu tiên (chiều dọc): ", np.concatenate([x_grid, x_grid]))
print("Hoặc nối 2 mảng theo trục thứ 2 (chiều ngang): ", np.concatenate([x_grid, x_grid], axis=1))
Out[20]
Phương thức concatenate nhận tham số đầu tiên là một tuple hoặc mảng:  [0 1 2 3 3 2 1 0]
Phương thức concatenate có thể nối nhiều hơn 2 mảng một lúc:  [0 1 2 3 3 2 1 0 0 1 2 3 3 2 1 0]
Sử dụng cho mảng nhiều chiều, nối 2 mảng theo trục đầu tiên (chiều dọc):  [[1 2 3]
 [4 5 6]
 [1 2 3]
 [4 5 6]]
Hoặc nối 2 mảng theo trục thứ 2 (chiều ngang):  [[1 2 3 1 2 3]
 [4 5 6 4 5 6]]

Chúng ta hoàn toàn có thể nối mảng chỉ cần dùng np.concatenate, tuy nhiên khi nối các mảng mà số chiều khác nhau, chỉ sử dụng np.concatenate sẽ rất phức tạp, khi đó ta nên dùng np.vstack (nối theo chiều dọc) và np.hstack (nối theo chiều ngang):

In[21]
x = np.array([1,2,3])
x_grid = np.array([[4,5,6], 
                   [7,8,9]])

print("Nối 2 mảng theo chiều dọc: ", np.vstack([x, x_grid]))

y = np.array([[99],
             [99]])
print("Nối 2 mảng theo chiều ngang: ", np.hstack([x_grid, y]))
Out[21]
Nối 2 mảng theo chiều dọc:  [[1 2 3]
 [4 5 6]
 [7 8 9]]
Nối 2 mảng theo chiều ngang:  [[ 4  5  6 99]
 [ 7  8  9 99]]

Với np.dstack, các mảng sẽ được nối với nhau theo trục thứ 3 (third axis):

In[22]
a = np.array([1,2,3])
b = np.array([2,3,4])
print(np.dstack([a,b]))

print("shape:", np.dstack([a,b]).shape)
Out[22]
[[[1 2]
  [2 3]
  [3 4]]]
shape: (1, 3, 2)

b. Chia mảng (splitting)

Ngược lại với nối là chia mảng, và cũng giống y như nối mảng, chia mảng có 4 hàm chính: np.split, np.hsplit, np.vsplit và np.dsplit với tính năng tương tự:

In[42]
x = [1,2,3,4,5,6,3,2,1]
x1, x2, x3 = np.split(x, [3, 5])
print("x1, x2, x3 = ", x1, x2, x3)

grid = np.arange(16).reshape((4, 4))
print("grid = ", grid)
tren, duoi = np.vsplit(grid, [2])
print("Trên:", tren)
print("Dưới:", duoi)
trai, phai = np.hsplit(grid, [2])
print("Trái:", trai)
print("Phải:", phai)

x = np.arange(16).reshape(2, 2, 4)
print("x = ", x)
print("Chia với theo axis = 2: ")
print(np.dsplit(x, 2))
x1, x2, x3 =  [1 2 3] [4 5] [6 3 2 1]

grid =  [[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

Trên: [[0 1 2 3]
 [4 5 6 7]]
Dưới: [[ 8  9 10 11]
 [12 13 14 15]]

Trái: [[ 0  1]
 [ 4  5]
 [ 8  9]
 [12 13]]
Phải: [[ 2  3]
 [ 6  7]
 [10 11]
 [14 15]]

x =  [[[ 0  1  2  3]
  [ 4  5  6  7]]

 [[ 8  9 10 11]
  [12 13 14 15]]]
Chia với theo axis = 2: 
[array([[[ 0,  1],
        [ 4,  5]],

       [[ 8,  9],
        [12, 13]]]), array([[[ 2,  3],
        [ 6,  7]],

       [[10, 11],
        [14, 15]]])]

6. Array Sorting

Sử dụng hàm sort()

In[48]
arr = np.array([[9, 13], 
              [5, 2]]) 

print ("Sort theo cột : \n", np.sort(arr, axis = 0))         
   
print ("\nSort theo hàng : \n", np.sort(arr, axis = 1)) 
   
print ("\nSort không theo trục : \n", np.sort(arr, axis=None)) 
Out[48]
Sort theo cột : 
 [[ 5  2]
 [ 9 13]]

Sort theo hàng : 
 [[ 9 13]
 [ 2  5]]

Sort không theo trục : 
 [ 2  5  9 13]

Sử dụng argsort()

Phương thức argsort sẽ trả về các vị trí của các phần tử được sắp xếp so với mảng ban đầu:

In[24]
arr = np.array([8, 2, 1, 7, 4, 3, 9]) 
   
print("arr = ", arr)

print("Mảng đã sắp xếp: ", np.sort(arr))
print("Vị trí tương ứng của các phần tử đã sắp xếp so với ban đầu: ", np.argsort(arr))
Out[24]
arr =  [8 2 1 7 4 3 9]
Mảng đã sắp xếp:  [1 2 3 4 7 8 9]
Vị trí tương ứng của các phần tử đã sắp xếp so với ban đầu:  [2 1 5 4 3 0 6]

7. Tổng kết

Sau khi hoàn thành bài này thì bạn đã cơ bản nắm được NumPy và hiểu được cơ chế nó hoạt động, với mỗi phần trong bài, hãy thử với nhiều ví dụ khác nhau để có thể hiểu rõ hơn nhé. Trong những bài sau, ta sẽ đi sâu vào lý do vì sao mà NumPy lại là nhân tố quan trọng nhất trong hệ sinh thái Data Science của Python. Hẹn gặp các bạn trong bài sau.

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