Sitelet https://www.datacamp.com/vi/tutorial/python-numpy-tutorial
Chuyển đến nội dung chính

Hướng dẫn mảng Numpy trong Python

Hướng dẫn NumPy cho người mới bắt đầu, trong đó bạn sẽ học cách tạo mảng NumPy, dùng broadcasting, truy cập giá trị, thao tác mảng và nhiều hơn nữa.
Đã cập nhật 5 thg 10, 2026  · 15 phút đọc

Khám phá cùng AI

ChatGPTClaudePerplexity

NumPy cũng giống như SciPy, Scikit-Learn, pandas và các gói tương tự. Chúng là những gói Python mà bạn không thể bỏ qua khi học khoa học dữ liệu, chủ yếu vì thư viện này cung cấp cho bạn một cấu trúc dữ liệu mảng với nhiều lợi ích so với list của Python, như gọn hơn, truy cập đọc/ghi phần tử nhanh hơn, tiện hơn và hiệu quả hơn.

Hướng dẫn NumPy này sẽ tập trung chính xác vào điều đó. Nó không chỉ cho bạn thấy mảng NumPy thực sự là gì và cách cài đặt Python, mà bạn còn sẽ học cách tạo mảng (kể cả khi dữ liệu đến từ tệp), cách broadcasting hoạt động, cách tìm trợ giúp, cách thao tác mảng và cách trực quan hóa chúng.

Nếu bạn muốn biết thêm về mảng NumPy và các cấu trúc dữ liệu khác mà bạn sẽ cần trong hành trình khoa học dữ liệu, hãy xem Intro to Python for Data Science của DataCamp, trong đó có một chương về NumPy.

Python Numpy Array là gì?

Bạn đã đọc trong phần mở đầu rằng mảng NumPy hơi giống list của Python, nhưng đồng thời cũng rất khác. Với những bạn mới bắt đầu, hãy làm rõ chính xác nó là gì và nó hữu ích ra sao.

Như tên gọi, mảng NumPy là một cấu trúc dữ liệu trung tâm của thư viện numpy. Tên thư viện là viết tắt của “Numeric Python” hoặc “Numerical Python”.

Nói cách khác, NumPy là một thư viện Python cốt lõi cho tính toán khoa học trong Python. Nó chứa tập hợp công cụ và kỹ thuật có thể dùng để giải các mô hình toán học cho bài toán trong khoa học và kỹ thuật.

Một trong những công cụ đó là đối tượng mảng đa chiều hiệu năng cao — một cấu trúc dữ liệu mạnh mẽ để tính toán hiệu quả trên mảng và ma trận. Để làm việc với các mảng này, có một số lượng lớn các hàm toán học cấp cao vận hành trên những ma trận và mảng này.

Nhưng mảng là gì?

Khi bạn in ra một vài mảng, bạn có thể coi nó là một lưới chứa các giá trị cùng kiểu:

import numpy as np
# Define a 1D array
my_array = np.array([[1, 2, 3, 4],
                     [5, 6, 7, 8]],
                    dtype=np.int64)
# Define a 2D array
my_2d_array = np.array([[1, 2, 3, 4],
                        [5, 6, 7, 8]],
                       dtype=np.int64)
# Define a 3D array
my_3d_array = np.array([[[1, 2, 3, 4],
                         [5, 6, 7, 8]],
                        [[1, 2, 3, 4],
                         [9, 10, 11, 12]]],
                       dtype=np.int64)
# Print the 1D array
print("Printing my_array:")
print(my_array)
# Print the 2D array
print("Printing my_2d_array:")
print(my_2d_array)
# Print the 3D array
print("Printing my_3d_array:")
print(my_3d_array)

Bạn thấy trong ví dụ trên, dữ liệu là số nguyên. Mảng lưu giữ và biểu diễn bất kỳ dữ liệu thông thường nào theo cách có cấu trúc.

Tuy nhiên, bạn nên biết rằng ở mức cấu trúc, một mảng về cơ bản chỉ là các con trỏ. Nó là sự kết hợp của một địa chỉ bộ nhớ, một kiểu dữ liệu, một shape và strides:

  • Con trỏ dữ liệu cho biết địa chỉ bộ nhớ của byte đầu tiên trong mảng.
  • Con trỏ kiểu dữ liệu hay dtype mô tả loại phần tử có trong mảng.
  • Shape cho biết hình dạng của mảng.
  • Strides là số byte cần bỏ qua trong bộ nhớ để đến phần tử kế tiếp. Nếu strides của bạn là (10,1), bạn cần tiến 1 byte để đến cột tiếp theo và 10 byte để đến hàng tiếp theo.

Nói cách khác, một mảng chứa thông tin về dữ liệu thô, cách định vị một phần tử và cách diễn giải một phần tử.

Lý thuyết đủ rồi. Hãy tự kiểm chứng:

Bạn có thể dễ dàng kiểm tra điều này bằng cách khám phá các thuộc tính của mảng numpy:

import numpy as np
my_2d_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)

# Print out memory address
print(my_2d_array.data)

# Print out the shape of `my_array`
print(my_2d_array.shape)

# Print out the data type of `my_array`
print(my_2d_array.dtype)

# Print out the stride of `my_array`
print(my_2d_array.strides)

Bạn thấy rằng giờ bạn nhận nhiều thông tin hơn: ví dụ, kiểu dữ liệu in ra là ‘int64’ hay kiểu số nguyên có dấu 64-bit; Chi tiết hơn nhiều! Điều đó cũng có nghĩa mảng được lưu trong bộ nhớ với 64 byte (vì mỗi số nguyên chiếm 8 byte và bạn có mảng 8 số nguyên). Strides của mảng cho biết bạn phải bỏ qua 8 byte (một giá trị) để sang cột kế tiếp, nhưng 32 byte (4 giá trị) để tới cùng vị trí ở hàng kế. Vì vậy, strides cho mảng sẽ là (32,8).

Lưu ý nếu bạn đặt kiểu dữ liệu là int32, bộ đôi strides bạn nhận sẽ là (16, 4), vì bạn vẫn cần di chuyển 1 giá trị đến cột tiếp theo và 4 giá trị để đến cùng vị trí. Điểm duy nhất thay đổi là mỗi số nguyên sẽ chiếm 4 byte thay vì 8

Numpy Array Axis

Mảng bạn thấy ở trên, như tên gọi, là mảng 2 chiều: bạn có hàng và cột. Các hàng được chỉ định là “trục 0”, còn các cột là “trục 1”. Số của trục tăng tương ứng với số chiều: trong mảng 3-D, mà bạn đã thấy ví dụ ở khối mã trước, bạn sẽ có thêm “trục 2”. Lưu ý các trục này chỉ có ý nghĩa với mảng có ít nhất 2 chiều, vì không cần điều này cho mảng 1-D;

Những trục này sẽ hữu ích sau này khi bạn thao tác shape của mảng NumPy.

Cách cài đặt Numpy

Trước khi bạn có thể tự thử các mảng NumPy, trước hết hãy chắc rằng bạn đã cài đặt nó cục bộ (giả định bạn làm việc trên máy tính cá nhân). Nếu bạn đã có thư viện Python sẵn, hãy bỏ qua phần này :)

Nếu bạn vẫn cần thiết lập môi trường, hãy lưu ý có hai cách chính để cài NumPy trên máy: với sự trợ giúp của Python wheels hoặc bản phân phối Anaconda Python.

Cài đặt bằng Python Wheels

Trước hết hãy chắc rằng bạn đã cài Python. Bạn có thể xem hướng dẫn của chúng tôi về cách cài đặt Python nếu vẫn cần làm điều này :)

Nếu bạn dùng Windows, hãy chắc rằng bạn đã thêm Python vào biến môi trường PATH environment variable. Sau đó, đừng quên cài một trình quản lý gói, như pip, để bạn có thể dùng các thư viện mã nguồn mở của Python.

Lưu ý rằng các phiên bản Python 3 gần đây đi kèm pip, nên hãy kiểm tra xem bạn có nó không, và nếu có, hãy nâng cấp trước khi cài NumPy:

pip install pip --upgrade
pip --version
Tải tệp wheel NumPy phù hợp với hệ thống của bạn từ trang PyPI. Bạn có thể tìm danh sách các wheel NumPy sẵn có trên Python Package Index.
 
Sau khi tải tệp wheel NumPy, hãy điều hướng tới thư mục lưu tệp bằng Command Prompt hoặc cửa sổ terminal.
 
Cài đặt NumPy bằng lệnh sau, thay thế "numpy-<version>-<architecture>.whl" bằng tên tệp wheel NumPy bạn đã tải:
pip install numpy-<version>-<architecture>.whl
Ví dụ, nếu bạn tải NumPy phiên bản 1.20.3 cho hệ thống Windows 64-bit, lệnh sẽ là:
pip install numpy-1.20.3-cp39-cp39-win_amd64.whl
Sau khi cài xong, bạn có thể xác minh NumPy đã được cài bằng cách mở trình thông dịch Python và chạy lệnh sau:
import numpy
Nếu không có thông báo lỗi, NumPy đã sẵn sàng để sử dụng!

Cài đặt bằng bản phân phối Anaconda Python

Để có NumPy, bạn cũng có thể tải bản phân phối Anaconda Python. Cách này dễ và cho phép bạn bắt đầu nhanh! Nếu bạn chưa tải, hãy tới trang chính thức để lấy. Làm theo hướng dẫn để cài đặt và bạn đã sẵn sàng bắt đầu!

Bạn thắc mắc vì sao cách này dễ hơn?

Điều hay khi dùng bản phân phối này là bạn không cần quá lo lắng về việc cài đặt riêng lẻ NumPy hay bất kỳ gói chính nào bạn sẽ dùng cho phân tích dữ liệu, như pandas, scikit-learn, v.v.

Bởi vì, đặc biệt nếu bạn rất mới với Python, lập trình hoặc terminal, việc Anaconda đã bao gồm 100 gói phổ biến nhất cho Python, R và Scala cho khoa học dữ liệu thực sự là một sự nhẹ nhõm. Nhưng ngay cả với các nhà khoa học dữ liệu dày dạn, Anaconda vẫn là lựa chọn nên dùng nếu bạn muốn bắt đầu nhanh để giải quyết các bài toán khoa học dữ liệu.

Hơn nữa, Anaconda còn bao gồm nhiều môi trường phát triển mã nguồn mở như Jupyter và Spyder. Nếu bạn muốn bắt đầu làm việc với Jupyter Notebook sau hướng dẫn này, hãy tới hướng dẫn Jupyter notebook của chúng tôi.

Tóm lại, hãy cân nhắc tải Anaconda để bắt đầu làm việc với numpy và các gói liên quan đến khoa học dữ liệu!

Cách tạo mảng NumPy

Giờ bạn đã thiết lập xong môi trường, đến lúc làm việc thực sự. Thú thật, bạn đã thử một chút với mảng ở đoạn mã trên. Tuy nhiên, bạn vẫn chưa có thực hành thực sự vì trước tiên bạn cần cài NumPy trên máy. Bây giờ bạn đã làm xong, đến lúc xem bạn cần làm gì để chạy các khối mã trên ở máy mình.

Để tạo mảng numpy, bạn chỉ cần dùng hàm np.array(). Tất cả những gì cần làm là truyền vào một list và tùy chọn, bạn cũng có thể chỉ định kiểu dữ liệu. Nếu muốn biết thêm về các kiểu dữ liệu có thể chọn, hãy xem hướng dẫn này hoặc lướt qua tờ phao NumPy của DataCamp.

Không cần phải ghi nhớ các kiểu dữ liệu NumPy nếu bạn là người dùng mới, nhưng bạn cần biết và quan tâm đến loại dữ liệu mình đang xử lý. Kiểu dữ liệu tồn tại khi bạn cần kiểm soát nhiều hơn cách dữ liệu được lưu trữ trong bộ nhớ và trên đĩa. Đặc biệt khi làm việc với dữ liệu lớn, việc biết cách kiểm soát kiểu lưu trữ là điều tốt.

Đừng quên rằng để làm việc với hàm np.array(), bạn cần chắc thư viện numpy có trong môi trường.

Thư viện NumPy tuân theo một quy ước import: khi import thư viện, bạn cần import dưới dạng np. Làm vậy giúp các Pythonista khác hiểu mã của bạn dễ hơn.

Trong ví dụ sau, bạn sẽ tạo mảng my_array mà bạn đã dùng ở trên:

import numpy as np

# Make the array `my_array`
my_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)

# Print `my_array`
print(my_array)

Nếu bạn muốn biết thêm về cách tạo list, hãy xem hướng dẫn câu hỏi về list trong Python của chúng tôi.

Tuy nhiên, đôi khi bạn không biết sẽ đưa dữ liệu nào vào mảng, hoặc bạn muốn nhập dữ liệu vào mảng numpy từ nguồn khác. Khi đó, bạn sẽ dùng các “giá trị giữ chỗ” ban đầu hoặc các hàm để nạp dữ liệu từ văn bản vào mảng.

Các phần sau sẽ chỉ bạn cách làm điều này.

Cách tạo mảng NumPy “rỗng”

Khi nói họ tạo mảng “rỗng”, mọi người thường muốn dùng các giá trị giữ chỗ ban đầu, mà bạn có thể điền sau. Bạn có thể khởi tạo mảng toàn số 1 hoặc số 0, nhưng cũng có thể tạo mảng được điền bằng các giá trị cách đều, giá trị hằng hoặc giá trị ngẫu nhiên.

Tuy vậy, bạn vẫn có thể tạo một mảng hoàn toàn rỗng.

May mắn là có khá nhiều hàm để tạo.

Hãy thử tất cả bên dưới!

import numpy as np

# Create an array of ones
ones_array = np.ones((3, 4))
print("Ones Array:")
print(ones_array)
print()

# Create an array of zeros
zeros_array = np.zeros((2, 3, 4), dtype=np.int16)
print("Zeros Array:")
print(zeros_array)
print()

# Create an array with random values
random_array = np.random.random((2, 2))
print("Random Array:")
print(random_array)
print()

# Create an empty array
empty_array = np.empty((3, 2))
print("Empty Array:")
print(empty_array)
print()

# Create a full array
full_array = np.full((2, 2), 7)
print("Full Array:")
print(full_array)
print()

# Create an array of evenly-spaced values
arange_array = np.arange(10, 25, 5)
print("Arange Array:")
print(arange_array)
print()

# Create an array of evenly-spaced values
np.linspace(0,2,9)

Mẹo: hãy nghịch các hàm trên để hiểu cách chúng hoạt động!

  • Với một số hàm như np.ones(), np.random.random(), np.empty(), np.full() hoặc np.zeros() điều duy nhất bạn cần làm để tạo mảng toàn số 1 hay số 0 là truyền shape của mảng muốn tạo. Như một tùy chọn cho np.ones() và np.zeros(), bạn cũng có thể chỉ định kiểu dữ liệu. Với np.full(), bạn cũng phải chỉ định giá trị hằng muốn chèn vào mảng.
  • Với np.linspace() và np.arange() bạn có thể tạo mảng các giá trị cách đều. Khác biệt giữa hai hàm này là giá trị cuối cùng trong ba đối số được truyền ở khối mã trên chỉ định hoặc là bước cho np.linspace() hoặc là số mẫu cho np.arange(). Ở cái đầu tiên, bạn muốn, chẳng hạn, một mảng 9 giá trị nằm giữa 0 và 2. Với cái sau, bạn chỉ định rằng bạn muốn một mảng bắt đầu ở 10 và theo bước 5, tạo các giá trị cho mảng bạn đang tạo.

Hãy nhớ NumPy cũng cho phép bạn tạo ma trận đơn vị bằng np.eye() và np.identity(). Ma trận đơn vị là ma trận vuông mà mọi phần tử trên đường chéo chính là số 1, còn các phần tử khác là số 0. Khi bạn nhân một ma trận với ma trận đơn vị, ma trận ban đầu không đổi.

Nói cách khác, nếu bạn nhân một ma trận với ma trận đơn vị, tích thu được sẽ lại là chính ma trận đó theo quy ước chuẩn của phép nhân ma trận.

Dù trọng tâm của hướng dẫn này không phải trình bày cách ma trận đơn vị hoạt động, chỉ cần nói rằng ma trận đơn vị hữu ích khi bạn bắt đầu tính toán ma trận: chúng có thể đơn giản hóa phương trình, khiến tính toán của bạn hiệu quả và vững chắc hơn.

Cách nạp mảng NumPy từ văn bản

Tạo mảng với sự trợ giúp của các giá trị giữ chỗ ban đầu hoặc với một số dữ liệu mẫu là cách tuyệt vời để bắt đầu với numpy. Nhưng khi muốn bắt đầu phân tích dữ liệu, bạn sẽ cần nạp dữ liệu từ các tệp văn bản.

Với những gì bạn đã thấy đến giờ, bạn sẽ chưa làm được nhiều. Hãy dùng một số hàm chuyên biệt để nạp dữ liệu từ tệp, như loadtxt() hoặc genfromtxt().

Giả sử bạn có các tệp văn bản sau với dữ liệu, bạn muốn sao chép các giá trị được chú thích trong mã dưới đây, dán vào tệp văn bản và lưu là “data.txt.” Sau đó bạn có thể dùng đoạn mã dưới đây:

# This is your data in the text file
# Value1  Value2  Value3
# 0.2536  0.1008  0.3857
# 0.4839  0.4536  0.3561
# 0.1292  0.6875  0.5929
# 0.1781  0.3049  0.8928
# 0.6253  0.3486  0.8791

# Import your data
x, y, z = np.loadtxt('data.txt',
                    skiprows=1,
                    unpack=True)

Trong mã trên, bạn dùng loadtxt() để nạp dữ liệu vào môi trường. Bạn thấy đối số đầu tiên cả hai hàm nhận là tệp văn bản data.txt. Tiếp theo, có một số đối số cụ thể: trong câu lệnh đầu, bạn bỏ qua hàng đầu tiên, và bạn trả về các cột dưới dạng các mảng riêng biệt với unpack=TRUE. Điều này nghĩa là các giá trị trong cột Value1 sẽ đưa vào x, v.v.

Lưu ý rằng nếu bạn có dữ liệu phân tách bằng dấu phẩy hoặc muốn chỉ định kiểu dữ liệu, cũng có các đối số delimiter và dtype mà bạn có thể thêm vào đối số của loadtxt().

Thật dễ và thẳng thắn, đúng không?

Hãy xem tệp dữ liệu thứ hai của bạn:

# Your data in the text file
# Value1  Value2  Value3
# 0.4839  0.4536  0.3561
# 0.1292  0.6875  MISSING
# 0.1781  0.3049  0.8928
# MISSING 0.5801  0.2038
# 0.5993  0.4357  0.7410

my_array2 = np.genfromtxt('data2.txt',
                      skip_header=1,
                      filling_values=-999)

Bạn thấy ở đây, bạn dùng genfromtxt() để nạp dữ liệu. Trong trường hợp này, bạn phải xử lý một số giá trị thiếu được chỉ báo bằng chuỗi 'MISSING'.

Vì hàm genfromtxt() chuyển đổi chuỗi ký tự trong các cột số thành nan, bạn có thể chuyển các giá trị này thành giá trị khác bằng cách chỉ định đối số filling_values. Ở đây, bạn chọn đặt các giá trị thiếu thành -999.

Nếu có trường hợp các giá trị không được genfromtxt() chuyển thành nan, luôn có đối số missing_values cho phép bạn chỉ định chính xác giá trị thiếu trong dữ liệu là gì.

Nhưng chưa hết.

Mẹo: xem trang numpy.genfromtxt này để biết các đối số khác bạn có thể thêm nhằm nhập dữ liệu thành công.

Giờ bạn có thể tự hỏi sự khác nhau thực sự giữa hai hàm này là gì.

Các ví dụ có thể đã ngầm chỉ ra điều này, nhưng nhìn chung, genfromtxt() cho bạn linh hoạt hơn một chút; Nó mạnh mẽ hơn loadtxt().

Hãy làm cho khác biệt này thực tế hơn một chút: hàm sau, loadtxt(), chỉ hoạt động khi mỗi hàng trong tệp văn bản có cùng số lượng giá trị, vì vậy khi bạn muốn xử lý giá trị thiếu dễ dàng, bạn thường thấy dùng genfromtxt() thuận tiện hơn.

Nhưng đó chắc chắn không phải lý do duy nhất.

Chỉ cần nhìn qua số lượng đối số mà genfromtxt() cung cấp sẽ cho bạn thấy có rất nhiều thứ bạn có thể chỉ định khi nhập dữ liệu, như số hàng tối đa để đọc hoặc tùy chọn tự động cắt khoảng trắng khỏi biến.

Cách lưu mảng NumPy

Khi đã làm mọi thứ bạn cần với mảng, bạn cũng có thể lưu chúng ra tệp. Nếu muốn lưu mảng vào tệp văn bản, bạn có thể dùng hàm savetxt() để làm điều này:

import numpy as np
x = np.arange(0.0,5.0,1.0)
np.savetxt('test.out', x, delimiter=',')

Hãy nhớ np.arange() tạo một mảng NumPy các giá trị cách đều. Giá trị thứ ba bạn truyền vào hàm này là bước nhảy.

Tất nhiên, có những cách khác để lưu mảng NumPy của bạn vào tệp văn bản. Hãy xem các hàm trong bảng dưới nếu bạn muốn lưu dữ liệu vào tệp nhị phân hoặc kho lưu trữ:

save() Lưu mảng vào tệp nhị phân định dạng .npy của NumPy
savez() Lưu nhiều mảng vào một kho lưu trữ .npz không nén
savez_compressed() Lưu nhiều mảng vào một kho lưu trữ .npz nén

Để biết thêm thông tin hoặc ví dụ về cách dùng các hàm trên để lưu dữ liệu, hãy xem trang tham chiếu NumPy hoặc dùng một trong các hàm trợ giúp mà NumPy cung cấp để biết thêm ngay lập tức!

Bạn không chắc các hàm trợ giúp của NumPy là gì?

Đừng lo! Bạn sẽ học thêm về chúng ở một trong các phần tiếp theo!

Cách kiểm tra mảng NumPy

Bên cạnh các thuộc tính mảng đã đề cập ở trên, cụ thể là data, shape, dtype và strides, còn có một số thuộc tính khác bạn có thể dùng để dễ dàng hiểu thêm về mảng. Những cái bạn có thể thấy hữu ích khi mới bắt đầu là:

import numpy as np

# Create a numpy array with shape (2,4) and dtype int64
my_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)

# Print the number of dimensions of `my_array`
print("Number of dimensions of my_array:")
print(my_array.ndim)
print()

# Print the number of elements in `my_array`
print("Number of elements in my_array:")
print(my_array.size)
print()

# Print information about the memory layout of `my_array`
print("Information about the memory layout of my_array:")
print(my_array.flags)
print()

# Print the length of one array element in bytes
print("Length of one array element in bytes:")
print(my_array.itemsize)
print()

# Print the total consumed bytes by `my_array`'s elements
print("Total consumed bytes by my_array's elements:")
print(my_array.nbytes)
print()

Đây gần như là tất cả các thuộc tính mà một mảng có thể có.

Đừng lo nếu bạn thấy không phải tất cả đều hữu ích lúc này. Điều này khá bình thường vì, như bạn đã đọc ở phần trước, bạn chỉ cần lo về bộ nhớ khi làm việc với tập dữ liệu lớn.

Cũng lưu ý rằng ngoài các thuộc tính, bạn còn có vài cách khác để lấy thêm thông tin và thậm chí tinh chỉnh mảng một chút:

import numpy as np
my_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)

# Print the length of `my_array`
print(len(my_array))

# Change the data type of `my_array`
my_array.astype(float)

Giờ bạn đã tạo mảng, hoặc là tự tạo bằng np.array() hay một trong các hàm giữ chỗ ban đầu, hoặc bằng cách nạp dữ liệu qua loadtxt() hay genfromtxt(), đã đến lúc đi sâu vào yếu tố then chốt thứ hai định nghĩa thư viện NumPy: tính toán khoa học.

Cách NumPy Broadcasting hoạt động

Trước khi đi sâu vào tính toán khoa học, có lẽ nên điểm qua broadcasting là gì: đó là cơ chế cho phép NumPy làm việc với các mảng có shape khác nhau khi bạn thực hiện phép toán số học.

Hình minh họa dưới đây cho thấy ví dụ broadcasting của NumPy đang hoạt động: 

NumPy Broadcasting

Nguồn

Nói thực tế hơn, bạn thường có một mảng hơi lớn và một mảng hơi nhỏ hơn. Lý tưởng là bạn muốn dùng mảng nhỏ nhiều lần để thực hiện một phép toán (như cộng, nhân, v.v.) trên mảng lớn.

Để làm điều này, bạn dùng cơ chế broadcasting.

Tuy nhiên, có một số quy tắc nếu bạn muốn dùng nó. Và, trước khi bạn thở dài, bạn sẽ thấy những “quy tắc” này rất đơn giản và khá trực quan!

  • Đầu tiên, để đảm bảo broadcasting thành công, các chiều của mảng cần tương thích. Hai chiều tương thích khi chúng bằng nhau. Hãy xét ví dụ sau:
# Import the NumPy library and give it an alias of `np`
import numpy as np

# Initialize a 3x4 array of ones and assign it to the variable `x`
x = np.ones((3,4))

# Print the shape of the array `x`
print("Shape of x:", x.shape)

# Initialize a 3x4 array of random numbers between 0 and 1 and assign it to the variable `y`
y = np.random.random((3,4))

# Print the shape of the array `y`
print("Shape of y:", y.shape)

# Add the arrays `x` and `y` element-wise and print the resulting array
z = x + y
print("Result of x + y:\n", z)

# Print the shape of the resulting array
print("Shape of x + y:", z.shape)
  • Hai chiều cũng tương thích khi một trong chúng bằng 1:
# Import the NumPy library and give it an alias of `np`
import numpy as np

# Initialize a 3x4 array of ones and assign it to the variable `x`
x = np.ones((3,4))

# Print the shape of the array `x`
print("Shape of x:", x.shape)

# Initialize a 3x4 array of random numbers between 0 and 1 and assign it to the variable `y`
y = np.random.random((3,4))

# Print the shape of the array `y`
print("Shape of y:", y.shape)

# Add the arrays `x` and `y` element-wise and print the resulting array
z = x + y
print("Result of x + y:\n", z)

# Print the shape of the resulting array
print("Shape of x + y:", z.shape)

Lưu ý nếu các chiều không tương thích, bạn sẽ nhận ValueError.

Mẹo: cũng hãy kiểm tra kích thước của mảng kết quả sau khi bạn tính toán! Bạn sẽ thấy kích thước thực ra là kích thước lớn nhất theo mỗi chiều của các mảng đầu vào.

Nói cách khác, bạn thấy rằng kết quả của x-y cho ra một mảng có shape (3,4): y có shape (4,) và x có shape (3,4). Kích thước lớn nhất theo mỗi chiều của x và y được lấy để tạo shape của mảng kết quả mới.

  • Cuối cùng, các mảng chỉ có thể được broadcast cùng nhau nếu chúng tương thích ở tất cả các chiều. Hãy xét ví dụ sau:
# Import `numpy` as `np`
import numpy as np

# Initialize `x` and `y`
x = np.ones((3,4))
y = np.random.random((5,1,4))

# Add `x` and `y`
z = x + y

Bạn thấy rằng, dù x và y có vẻ khác nhau về số chiều, hai mảng vẫn có thể cộng với nhau.

Đó là vì chúng tương thích ở tất cả các chiều:

  • Mảng x có kích thước 3 X 4,
  • Mảng y có kích thước 5 X 1 X 4

Vì bạn đã thấy ở trên rằng các chiều cũng tương thích nếu một trong chúng bằng 1, bạn thấy hai mảng này đúng là ứng viên tốt cho broadcasting!

Bạn sẽ nhận thấy ở chiều mà y có kích thước 1, và mảng kia có kích thước lớn hơn 1 (tức là 3), mảng thứ nhất cư xử như thể nó được sao chép theo chiều đó.

Lưu ý shape của mảng kết quả một lần nữa sẽ là kích thước lớn nhất theo mỗi chiều của x và y: kích thước kết quả sẽ là (5,3,4)

Tóm lại, nếu bạn muốn dùng broadcasting, bạn sẽ dựa rất nhiều vào shape và số chiều của các mảng bạn đang làm việc cùng.

Nhưng nếu các chiều không tương thích thì sao?

Nếu chúng không bằng nhau hoặc không có chiều nào bằng 1 thì sao?

Bạn sẽ phải khắc phục bằng cách thao tác mảng! Bạn sẽ thấy cách làm trong một trong các phần tiếp theo.

Toán học với mảng hoạt động như thế nào?

Bạn đã thấy broadcasting hữu ích khi thực hiện các phép toán số học. Trong phần này, bạn sẽ khám phá một số hàm bạn có thể dùng để làm toán với mảng.

Do đó, có lẽ bạn không ngạc nhiên khi bạn có thể dùng +, -, *, / hoặc % để cộng, trừ, nhân, chia hoặc tính phần dư của hai (hoặc nhiều) mảng. Tuy nhiên, phần lớn lý do NumPy hữu ích là vì nó cũng có các hàm để làm điều này. Các hàm tương đương với những phép toán vừa nêu lần lượt là np.add(), np.subtract(), np.multiply(), np.divide() và np.remainder().

Bạn cũng có thể dễ dàng mũ và lấy căn bậc hai của mảng với np.exp() và np.sqrt(), hoặc tính sin hay cos của mảng với np.sin() và np.cos(). Cuối cùng, cũng hữu ích khi nhắc rằng bạn còn có cách tính log tự nhiên với np.log() hoặc tính tích vô hướng bằng cách áp dụng dot() cho mảng.

Hãy thử tất cả trong mã dưới đây.

Một mẹo nhỏ: hãy kiểm tra trước các mảng đã được nạp cho bài tập này!

# Import `numpy` as `np`
import numpy as np
x = np.array([[1, 2, 3], [3, 4, 5]])
y = np.array([6,7,8])

# Add `x` and `y`
z = np.add(x,y)
print("Addition of x and y:\n", z)

# Subtract `x` and `y`
z = np.subtract(x,y)
print("Subtraction of y from x:\n", z)

# Multiply `x` and `y`
z = np.multiply(x,y)
print("Element-wise multiplication of x and y:\n", z)

Nhớ cách broadcasting hoạt động chứ? Hãy kiểm tra số chiều và shape của cả x và y trong IPython shell. Các quy tắc broadcasting có được tôn trọng không?

Nhưng vẫn còn nữa.

Xem danh sách nhỏ các hàm tổng hợp sau:

a.sum() Tổng toàn mảng
a.min() Giá trị nhỏ nhất toàn mảng
b.max(axis=0) Giá trị lớn nhất theo hàng của mảng
b.cumsum(axis=1) Tổng tích lũy của các phần tử
a.mean() Trung bình
b.median() Trung vị
a.corrcoef() Hệ số tương quan
np.std(b) Độ lệch chuẩn

Ngoài tất cả các hàm này, bạn cũng có thể thấy hữu ích khi biết rằng có các cơ chế cho phép so sánh phần tử mảng. Ví dụ, nếu muốn kiểm tra các phần tử của hai mảng có giống nhau không, bạn có thể dùng toán tử ==. Để kiểm tra phần tử mảng nhỏ hơn hay lớn hơn, bạn dùng toán tử < hoặc >.

Tất cả nghe khá đơn giản, đúng không?

Tuy nhiên, bạn cũng có thể so sánh toàn bộ mảng với nhau! Khi đó, bạn dùng hàm np.array_equal(). Chỉ cần truyền vào hai mảng muốn so sánh, là xong.

Lưu ý rằng ngoài so sánh, bạn cũng có thể thực hiện các phép logic trên mảng. Bạn có thể bắt đầu với np.logical_or(), np.logical_not() và np.logical_and(). Điều này về cơ bản hoạt động như các phép logic OR, NOT và AND thông thường;

Ví dụ đơn giản nhất, bạn dùng OR để xem liệu các phần tử có giống nhau (ví dụ, 1), hoặc nếu một trong hai phần tử mảng là 1. Nếu cả hai đều là 0, bạn sẽ trả về FALSE. Bạn sẽ dùng AND để xem phần tử thứ hai cũng là 1 và NOT để xem phần tử thứ hai khác 1.

Hãy thử trong khối mã dưới đây:

# Import `numpy` as `np`
import numpy as np
# Initialize arrays
a = np.array([1, 1, 0, 0], dtype=bool)
b = np.array([1, 0, 1, 0], dtype=bool)

# `a` AND `b` 
np.logical_and(a, b)

# `a` OR `b`
np.logical_or(a, b)

# `a` NOT `b`
np.logical_not(a,b)

Cách lấy tập con, cắt lát (slice) và đánh chỉ mục mảng

Ngoài các phép toán, bạn cũng có thể cân nhắc chỉ lấy một phần của mảng gốc (hoặc mảng kết quả) hay chỉ một số phần tử để dùng cho phân tích tiếp theo hoặc các phép toán khác. Khi đó, bạn sẽ cần lấy tập con, cắt lát và/hoặc đánh chỉ mục mảng.

Các thao tác này rất giống khi bạn thực hiện trên list trong Python. Nếu bạn muốn tự kiểm tra sự tương đồng hoặc muốn giải thích chi tiết hơn, bạn có thể xem hướng dẫn về list Python của DataCamp.

Nếu bạn hoàn toàn chưa biết các thao tác này hoạt động ra sao, hiện tại chỉ cần biết hai điều cơ bản:

  • Bạn dùng dấu ngoặc vuông [] làm toán tử chỉ mục, và
  • Thường bạn truyền số nguyên vào các ngoặc vuông này, nhưng bạn cũng có thể đặt dấu hai chấm : hoặc kết hợp dấu hai chấm với số nguyên để chỉ định phần tử/hàng/cột muốn chọn.

Lấy tập con (Subsetting)

Ngoài hai điểm trên, cách dễ nhất để thấy tất cả ghép lại như thế nào là xem một số ví dụ về lấy tập con:

import numpy as np

# Initialize 1D array
my_array = np.array([1,2,3,4])

# Print subsets
print(my_array[1])
import numpy as np

# Initialize 2D array
my_2d_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)

# Print subsets
print(my_2d_array[1][2])
print(my_2d_array[1,2])
import numpy as np

# Initialize 3D array
my_3d_array = np.array([[[1,2,3,4], [5,6,7,8]], [[1,2,3,4], [9,10,11,12]]], dtype=np.int64)

# Print subset
print(my_3d_array[1,1,2])

Cắt lát (Slicing)

Một thứ hơi “nâng cao” hơn subsetting, nếu bạn muốn, là slicing. Ở đây, bạn không chỉ xét các giá trị cụ thể của mảng, mà đi đến cấp độ hàng và cột. Bạn về cơ bản làm việc với “vùng” dữ liệu thay vì “vị trí” thuần túy.

Bạn có thể thấy ý nghĩa của ví von này qua các ví dụ mã sau:

import numpy as np

# Initialize 1D array
my_array = np.array([1,2,3,4])

# Print subsets
print(my_array[0:2])
import numpy as np

# Initialize 2D array
my_2d_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)

# Print subsets
print(my_2d_array[0:2,1])
import numpy as np

# Initialize 3D array
my_3d_array = np.array([[[1,2,3,4], [5,6,7,8]], [[1,2,3,4], [9,10,11,12]]], dtype=np.int64)

# Print subset
print(my_3d_array[1,...])

Bạn sẽ thấy, về bản chất, như sau:

a[start:end] # các phần tử từ start đến trước end (không gồm end!)
a[start:]    # các phần tử từ start đến hết mảng
a[:end]      # các phần tử từ đầu đến trước end (không gồm end!)

Trong mã trên, mỗi mảng được khởi tạo riêng và các tập con được in trong các khối mã riêng. my_array, my_2d_array và my_3d_array lần lượt là mảng 1D, 2D và 3D, và các tập con được in bằng cú pháp đánh chỉ mục.

Trong ví dụ đầu, chúng ta dùng slicing để chọn các phần tử ở chỉ mục 0 và 1 của my_array. Trong ví dụ thứ hai, chúng ta dùng slicing để chọn các phần tử ở hàng 0 và 1, cột 1 của my_2d_array. Trong ví dụ thứ ba, chúng ta dùng ký hiệu ... để chọn tất cả phần tử theo chiều thứ nhất và thứ hai, và phần tử thứ hai theo chiều thứ ba của my_3d_array.

Đánh chỉ mục (Indexing)

Cuối cùng, còn có indexing. Với NumPy, có indexing kiểu boolean và indexing nâng cao hay “fancy”.

(Nếu bạn thắc mắc, đây là thuật ngữ thực sự của NumPy, tôi không bịa ra cái sau đâu!)

Đầu tiên là boolean indexing. Ở đây, thay vì chọn phần tử, hàng hay cột dựa theo số chỉ mục, bạn chọn những giá trị từ mảng thỏa một điều kiện nhất định.

Việc này trong mã có thể khá dễ:

import numpy as np
my_array = np.array([1,2,3,4])
my_3d_array = np.array([[[1,2,3,4], [5,6,7,8]], [[1,2,3,4], [9,10,11,12]]], dtype=np.int64)

# Try out a simple example
print(my_array[my_array<2])

# Specify a condition
bigger_than_3 = (my_3d_array >= 3)

# Use the condition to index our 3d array
print(my_3d_array[bigger_than_3])

Lưu ý rằng để chỉ định điều kiện, bạn cũng có thể dùng các toán tử logic | (OR) và & (AND). Nếu bạn muốn viết lại điều kiện trên theo cách đó (sẽ không hiệu quả, nhưng tôi minh họa ở đây vì mục đích học tập :)), bạn sẽ có bigger_than_3 = (my_3d_array > 3) | (my_3d_array == 3).

Với các mảng đã nạp, không có quá nhiều khả năng, nhưng với các mảng chứa, ví dụ, tên hoặc thủ đô, khả năng có thể là vô tận!

Với fancy indexing, về cơ bản bạn làm như sau: bạn truyền một list hoặc mảng số nguyên để chỉ định thứ tự tập con hàng muốn chọn ra từ mảng gốc.

Nghe có hơi trừu tượng?

Đừng lo, hãy thử trong khối mã dưới đây:

import numpy as np
my_array = np.array([1,2,3,4])
my_2d_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)
my_3d_array = np.array([[[1,2,3,4], [5,6,7,8]], [[1,2,3,4], [9,10,11,12]]], dtype=np.int64)

# Select elements at (1,0), (0,1), (1,2) and (0,0)
print(my_2d_array[[1, 0, 1, 0],[0, 1, 2, 0]])

# Select a subset of the rows and columns
print(my_2d_array[[1, 0, 1, 0]][:,[0,1,2,0]])

Bây giờ, câu lệnh thứ hai có thể thoạt nhìn ít có ý nghĩa với bạn. Điều này bình thường. Sẽ hợp lý hơn nếu bạn tách nó ra:

    • Nếu bạn chỉ chạy my_2d_array[[1,0,1,0]], kết quả như sau:
array([[5, 6, 7, 8],
   [1, 2, 3, 4],
   [5, 6, 7, 8],
   [1, 2, 3, 4]])
    • Phần thứ hai, tức [:,[0,1,2,0]], cho biết bạn muốn giữ tất cả các hàng của kết quả này, nhưng muốn đổi thứ tự các cột một chút. Bạn muốn hiển thị các cột 0, 1 và 2 như hiện tại, nhưng muốn lặp lại cột 0 làm cột cuối thay vì hiển thị cột số 3. Điều này sẽ cho kết quả sau:
array([[5, 6, 7, 5],
   [1, 2, 3, 1],
   [5, 6, 7, 5],
   [1, 2, 3, 1]])

Indexing nâng cao rõ ràng không còn là bí ẩn với bạn nữa!

Cách tìm trợ giúp

Như một phần xen giữa ngắn, bạn nên biết rằng bạn luôn có thể hỏi thêm thông tin về mô-đun, hàm hoặc lớp bạn đang làm việc, đặc biệt vì NumPy có thể khá “khó nhằn” khi bạn mới bắt đầu.

Hỏi trợ giúp khá dễ.

Bạn chỉ cần dùng các hàm trợ giúp cụ thể mà numpy cung cấp để định hướng cho bạn:

  • Dùng lookfor() để tìm theo từ khóa trong docstring. Điều này đặc biệt hữu ích nếu bạn mới bắt đầu, vì “lý thuyết” đằng sau có thể phai nhạt trong trí nhớ bạn. Nhược điểm là bạn phải xem qua tất cả kết quả tìm kiếm nếu truy vấn của bạn không cụ thể, như trong ví dụ mã dưới. Điều này có thể khiến việc xem xét còn kém bao quát hơn.
  • Dùng info() để có giải thích nhanh và ví dụ mã của hàm, lớp hoặc mô-đun. Nếu bạn là người học qua thực hành, đây là cách nên đi! Nhược điểm duy nhất có lẽ là bạn cần biết thuộc tính hoặc hàm nằm trong mô-đun nào. Nếu bạn chưa hiểu ngay điều đó nghĩa là gì, hãy xem ví dụ mã dưới.

Bạn thấy đấy, cả hai hàm đều có ưu và nhược điểm, nhưng bạn sẽ tự thấy vì sao cả hai đều hữu ích: hãy tự thử trong khối mã dưới!

import numpy as np

# Look up info on `mean` with `np.lookfor()` 
print(np.lookfor("mean"))
# Get info on data types with `np.info()`
np.info(np.ndarray.dtype)

Lưu ý rằng bạn thực sự cần biết dtype là thuộc tính của ndarray. Cũng hãy chắc bạn không quên đặt np trước các mô-đun, lớp hoặc thuật ngữ bạn đang hỏi thông tin, nếu không bạn sẽ nhận thông báo lỗi như sau:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'ndarray' is not defined

Giờ bạn đã biết cách hỏi trợ giúp, đó là điều tốt. Chủ đề tiếp theo của hướng dẫn NumPy này là thao tác mảng.

Không phải bạn không thể tự vượt qua chủ đề này, hoàn toàn ngược lại!

Nhưng một số hàm có thể gây thắc mắc, vì, khác nhau giữa resize và reshape là gì?

Và khác nhau giữa xếp chồng mảng theo chiều ngang và dọc là gì?

Phần tiếp theo sẽ trả lời các câu hỏi này, nhưng nếu bạn thấy nghi ngờ, cứ thoải mái dùng các hàm trợ giúp bạn vừa thấy để nhanh chóng bắt nhịp.

Cách thao tác mảng

Thực hiện các phép toán trên mảng là một trong những việc bạn sẽ làm, nhưng có lẽ quan trọng nhất để điều này và broadcasting hoạt động là biết cách thao tác mảng.

Dưới đây là một số thao tác phổ biến nhất bạn sẽ làm.

Cách chuyển vị mảng

Chuyển vị mảng thực chất là hoán vị các chiều của nó. Hay nói cách khác, bạn đảo shape của mảng. Hãy lấy một ví dụ nhỏ để cho thấy hiệu ứng của chuyển vị:

import numpy as np
my_2d_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)

# Print `my_2d_array`
print(my_2d_array)

# Transpose `my_2d_array`
print(np.transpose(my_2d_array))

# Or use `T` to transpose `my_2d_array`
print(my_2d_array.T)

Mẹo: nếu so sánh trực quan giữa mảng và phiên bản chuyển vị chưa thật rõ, hãy kiểm tra shape của hai mảng để chắc bạn hiểu vì sao các chiều bị hoán vị.

Lưu ý có hai cách chuyển vị. Cả hai làm như nhau; Không khác biệt nhiều. Bạn cần lưu ý rằng T có vẻ là một hàm tiện lợi còn np.transpose() cho bạn linh hoạt hơn nhiều. Vì vậy, khuyến nghị dùng hàm này nếu bạn muốn thêm đối số.

Mọi chuyện đều ổn khi bạn chuyển vị các mảng lớn hơn một chiều, nhưng khi bạn chỉ có mảng 1-D thì sao? Bạn nghĩ có hiệu ứng gì không?

Hãy tự thử trong khối mã dưới. Mảng 1-D của bạn đã được nạp sẵn:

import numpy as np
my_array = np.array([1,2,3,4])

# Print `my_2d_array
print(my_array)

# Transpose `my_2d_array
print(np.transpose(my_array))

# Or use `T` to transpose `my_2d_array
print(my_array.T)

Bạn hoàn toàn đúng! Không có hiệu ứng gì khi chuyển vị mảng 1-D!

Reshape so với Resize mảng

Bạn có thể đã đọc trong phần broadcasting rằng các chiều của mảng cần tương thích nếu bạn muốn chúng là ứng viên tốt cho các phép toán. Nhưng câu hỏi bạn nên làm gì khi không phải như thế vẫn chưa được trả lời.

Đây chính là nơi bạn có câu trả lời!

Nếu các mảng không có cùng số chiều, bạn có thể resize mảng của mình. Khi đó bạn sẽ trả về một mảng mới có shape như bạn truyền vào hàm np.resize(). Nếu bạn truyền mảng gốc cùng với kích thước mới, và nếu mảng mới lớn hơn mảng ban đầu, mảng mới sẽ được điền bằng các bản sao của mảng gốc lặp lại nhiều lần theo nhu cầu.

Tuy nhiên, nếu bạn chỉ áp dụng np.resize() cho mảng và truyền shape mới vào, mảng mới sẽ được điền bằng số 0.

Hãy thử với ví dụ:

import numpy as np
x = np.ones((3,4))

# Print the shape of `x`
print(x.shape)

# Resize `x` to ((6,4))
np.resize(x, (6,4))

# Try out this as well
x.resize((6,4))

# Print out `x`
print(x)

Ngoài resize, bạn cũng có thể reshape mảng. Điều này nghĩa là bạn cho mảng một shape mới mà không thay đổi dữ liệu. Mấu chốt của reshape là đảm bảo tổng kích thước của mảng mới không đổi. Nếu bạn lấy ví dụ mảng x dùng ở trên, có kích thước 3 X 4 hay 12, bạn phải chắc mảng mới cũng có kích thước 12.

Psst… Nếu bạn muốn tính kích thước mảng bằng mã, hãy dùng thuộc tính size: x.size hoặc x.reshape((2,6)).size:

import numpy as np

# Initialize array with shape (3,4) containing all ones
x = np.ones((3,4))

# Print the shape of `x`
print("Shape of x:", x.shape)

# Resize `x` to ((6,4))
np.resize(x, (6,4))

# Try out this as well
x.resize((6,4))

# Print out `x` before and after resizing
print("Array before transposing:\n", x)
print("Shape of array before transposing:", x.shape)

# Transpose `x`
x = x.T

# Print out `x` after transposing
print("Array after transposing:\n", x)
print("Shape of array after transposing:", x.shape)

Đầu ra: 

Shape of x: (3, 4)
Array before transposing:
 [[1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]]
Shape of array before transposing: (6, 4)
Array after transposing:
 [[1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1.]]
Shape of array after transposing: (4, 6)

Nếu tất cả đều không được, bạn cũng có thể nối thêm một mảng vào mảng gốc hoặc chèn hay xóa phần tử mảng để đảm bảo các kích thước của bạn khớp với mảng còn lại mà bạn muốn dùng cho tính toán.

Một thao tác khác bạn có thể cần khi thay đổi shape là ravel(). Hàm này cho phép bạn làm phẳng mảng. Nghĩa là nếu bạn có mảng 2D, 3D hoặc n-D, bạn có thể dùng hàm này để làm phẳng tất cả thành mảng 1-D.

Khá tiện, phải không?

Cách nối (append) mảng

Khi bạn nối mảng vào mảng gốc, chúng được “dán” vào cuối mảng gốc. Nếu bạn muốn đảm bảo thứ bạn thêm vào không nằm ở cuối mảng, bạn có thể cân nhắc chèn (insert). Hãy tới phần tiếp theo nếu muốn biết thêm.

Append là việc khá dễ nhờ thư viện NumPy; Bạn có thể chỉ cần dùng np.append().

Xem cách làm trong khối mã dưới. Đừng quên bạn luôn có thể kiểm tra mảng nào đã nạp bằng cách gõ, ví dụ, my_array trong IPython shell và nhấn ENTER.

import numpy as np

my_array = np.array([1,2,3,4])

# Print `my_array` before appending
print("my_array before appending:", my_array)

# Append a 1D array to `my_array`
new_array = np.append(my_array, [7, 8, 9, 10])

# Print `new_array`
print("new_array:", new_array)

# Print `my_array` after appending
print("my_array after appending:", my_array)

Đầu ra:

my_array before appending: [1 2 3 4]
new_array: [ 1  2  3  4  7  8  9 10]
my_array after appending: [1 2 3 4]

Lưu ý my_array không đổi sau khi append vì np.append() trả về một mảng mới thay vì sửa mảng gốc tại chỗ.

Nối vào my_2d_array:

import numpy as np

my_2d_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)

# Print `my_2d_array` before appending
print("my_2d_array before appending:\n", my_2d_array)

# Append an extra column to `my_2d_array`
new_2d_array = np.append(my_2d_array, [[7], [8]], axis=1)

# Print `new_2d_array`
print("new_2d_array:\n", new_2d_array)

# Print `my_2d_array` after appending
print("my_2d_array after appending:\n", my_2d_array)

Đầu ra: 

my_2d_array before appending:
 [[1 2 3 4]
  [5 6 7 8]]
new_2d_array:
 [[1 2 3 4 7]
  [5 6 7 8 8]]
my_2d_array after appending:
 [[1 2 3 4]
  [5 6 7 8]]


Lưu ý khi bạn nối thêm một cột vào my_2d_array, bạn chỉ định axis. Hãy nhớ axis 1 chỉ cột, còn axis 0 chỉ hàng trong mảng 2-D.

Cách chèn và xóa phần tử mảng

Bên cạnh append, bạn cũng có thể chèn và xóa phần tử mảng. Như bạn có thể đoán, các hàm cho phép bạn làm các thao tác này là np.insert() và np.delete():

import numpy as np
my_array = np.array([1,2,3,4])
my_2d_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)

# Insert `5` at index 1
np.insert(my_array, 1, 5)

# Delete the value at index 1
np.delete(my_array,[1])

Cách ghép và tách mảng

Bạn cũng có thể “gộp” hay ghép các mảng. Có một loạt hàm bạn có thể dùng cho mục đích này và hầu hết được liệt kê dưới đây.

Hãy thử chúng, đồng thời nhớ kiểm tra shape của các mảng trong IPython shell. Các mảng đã nạp là x, my_array, my_resized_array và my_2d_array.

import numpy as np 
x = np.ones((4,))
my_array = np.array([1,2,3,4])
my_resized_array=np.resize(my_array,(2,4))
my_2d_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)

# Concatentate `my_array` and `x`
print(np.concatenate((my_array,x)))

# Stack arrays row-wise
print(np.vstack((my_array, my_2d_array)))

# Stack arrays row-wise
print(np.r_[my_resized_array, my_2d_array])

# Stack arrays horizontally
print(np.hstack((my_resized_array, my_2d_array)))

# Stack arrays column-wise
print(np.column_stack((my_resized_array, my_2d_array)))

# Stack arrays column-wise
print(np.c_[my_resized_array, my_2d_array])

Bạn sẽ lưu ý vài điều khi đi qua các hàm:

  • Số chiều cần giống nhau nếu bạn muốn nối hai mảng với np.concatenate(). Vì vậy, nếu bạn muốn nối một mảng với my_array, vốn là 1-D, bạn cần chắc mảng thứ hai cũng là 1-D.
  • Với np.vstack(), bạn kết hợp my_array với my_2d_array một cách dễ dàng. Bạn chỉ cần chắc rằng, vì bạn xếp chồng mảng theo hàng, số cột ở cả hai mảng giống nhau. Do đó, bạn cũng có thể thêm mảng có shape (2,4) hoặc (3,4) vào my_2d_array, miễn là số cột khớp. Nói cách khác, các mảng phải có cùng shape dọc theo mọi trục trừ trục đầu tiên. Điều tương tự cũng đúng khi bạn muốn dùng np.r[].
  • Với np.hstack(), bạn cần chắc số chiều giống nhau và số hàng ở cả hai mảng giống nhau. Điều đó nghĩa là bạn có thể xếp chồng các mảng như (2,3) hoặc (2,4) lên my_2d_array, bản thân nó có shape (2,4). Bất cứ điều gì cũng có thể miễn là số hàng khớp. Hàm này vẫn được NumPy hỗ trợ, nhưng bạn nên ưu tiên np.concatenate() hoặc np.stack().
  • Với np.column_stack(), bạn cần chắc các mảng truyền vào có cùng chiều đầu tiên. Trong trường hợp này, cả hai shape giống nhau, nhưng nếu my_resized_array là (2,1) hoặc (2,), các mảng vẫn sẽ được xếp chồng.
  • np.c_[] là một cách khác để nối. Ở đây cũng vậy, chiều đầu tiên của cả hai mảng cần khớp.

Khi bạn đã ghép mảng, có thể bạn cũng sẽ muốn tách chúng ở một thời điểm nào đó. Giống như bạn có thể xếp chồng theo chiều ngang, bạn cũng có thể làm vậy theo chiều dọc. Bạn dùng np.hsplit() và np.vsplit() tương ứng:

import numpy as np
my_array = np.array([1,2,3,4])
my_resized_array=np.resize(my_array,(2,4))
my_2d_array = np.array([[1,2,3,4], [5,6,7,8]], dtype=np.int64)
my_stacked_array = np.hstack((my_resized_array, my_2d_array))

# Split `my_stacked_array` horizontally at the 2nd index
print(np.hsplit(my_stacked_array, 2))

# Split `my_stacked_array` vertically at the 2nd index
print(np.vsplit(my_stacked_array, 2))

Điều bạn cần ghi nhớ khi dùng hai hàm split này có lẽ là shape của mảng. Lấy trường hợp trên làm ví dụ: my_stacked_array có shape (2,8). Nếu bạn muốn chọn chỉ mục tại đó tách xảy ra, bạn phải nhớ shape này.

Cách trực quan hóa mảng NumPy

Cuối cùng, một điều chắc chắn hữu ích là biết cách vẽ các mảng. Điều này đặc biệt hữu ích trong khám phá dữ liệu, nhưng cũng ở các giai đoạn sau của quy trình khoa học dữ liệu, khi bạn muốn trực quan hóa mảng của mình.

Với np.histogram()

Trái với tên gọi, hàm np.histogram() không vẽ biểu đồ histogram mà tính số lần xuất hiện của các phần tử mảng rơi vào mỗi bin; Điều này sẽ quyết định diện tích mỗi cột của histogram chiếm.

Những gì bạn truyền vào hàm np.histogram() trước tiên là dữ liệu đầu vào hay mảng bạn đang làm việc. Mảng sẽ được làm phẳng khi histogram được tính.

# Import `numpy` as `np`
import numpy as np

# Initialize your array
my_3d_array = np.array([[[1,2,3,4], [5,6,7,8]], [[1,2,3,4], [9,10,11,12]]], dtype=np.int64)

# Pass the array to `np.histogram()`
print(np.histogram(my_3d_array))

# Specify the number of bins
print(np.histogram(my_3d_array, bins=range(0,13)))

Bạn sẽ thấy kết quả là histogram được tính: mảng đầu tiên liệt kê tần suất cho tất cả phần tử của mảng, còn mảng thứ hai liệt kê các bin sẽ được dùng nếu bạn không chỉ định bin nào.

Nếu bạn chỉ định số lượng bin, kết quả tính sẽ khác: các số float sẽ biến mất và bạn sẽ thấy toàn số nguyên cho các bin.

Vẫn còn một số đối số khác bạn có thể chỉ định để ảnh hưởng đến histogram được tính. Bạn có thể tìm tất cả tại đây.

Nhưng mục đích của việc tính histogram là gì nếu bạn không thể trực quan hóa nó?

Trực quan hóa rất đơn giản với sự giúp đỡ của Matplotlib, nhưng bạn không cần np.histogram() để tính histogram. plt.hist() tự làm điều đó khi bạn truyền (dữ liệu đã làm phẳng) và các bin:

# Import numpy and matplotlib
import numpy as np
import matplotlib.pyplot as plt

# Construct the histogram with a flattened 3d array and a range of bins
plt.hist(my_3d_array.ravel(), bins=range(0,13))

# Add a title to the plot
plt.title('Frequency of My 3D Array Elements')

# Show the plot
plt.show()

Đoạn mã trên sẽ cho bạn histogram (cơ bản) sau:

Numpy Array Histogram

Sử dụng np.meshgrid()

Một cách khác để (gián tiếp) trực quan hóa mảng là dùng np.meshgrid(). Vấn đề bạn gặp với mảng là bạn cần mảng 2-D các giá trị tọa độ x và y. Với hàm trên, bạn có thể tạo một lưới hình chữ nhật từ mảng giá trị x và mảng giá trị y: hàm np.meshgrid() nhận hai mảng 1D và tạo hai ma trận 2D tương ứng với tất cả cặp (x, y) trong hai mảng. Sau đó, bạn có thể dùng các ma trận này để vẽ đủ loại đồ thị.

np.meshgrid() đặc biệt hữu ích nếu bạn muốn đánh giá các hàm trên một lưới, như mã dưới đây minh họa:

# Import NumPy and Matplotlib
import numpy as np
import matplotlib.pyplot as plt

# Create an array
points = np.arange(-5, 5, 0.01)

# Make a meshgrid
xs, ys = np.meshgrid(points, points)
z = np.sqrt(xs ** 2 + ys ** 2)

# Display the image on the axes
plt.imshow(z, cmap=plt.cm.gray)

# Draw a color bar
plt.colorbar()

# Show the plot
plt.show()

Mã trên cho kết quả sau:

Numpy Meshgrid

Vượt ra ngoài phân tích dữ liệu với NumPy

Chúc mừng bạn đã đến cuối hướng dẫn NumPy!

Bạn đã bao quát rất nhiều nội dung, vậy nên giờ bạn cần đảm bảo giữ được kiến thức đã có. Đừng quên lấy bản tóm tắt NumPy của DataCamp để hỗ trợ bạn làm điều này!

Sau tất cả lý thuyết này, cũng đến lúc thực hành thêm với các khái niệm và kỹ thuật bạn đã học trong hướng dẫn. Một cách là quay lại hướng dẫn scikit-learn và bắt đầu thử nghiệm thêm với các mảng dữ liệu dùng để xây dựng mô hình học máy.

Nếu điều này không hợp gu bạn, hãy kiểm tra lại xem bạn đã tải Anaconda chưa. Sau đó, bắt đầu với mảng NumPy trong Jupyter bằng Hướng dẫn toàn diện về Jupyter Notebook này. Cũng đừng quên xem Jupyter Notebook này, cũng hướng dẫn bạn phân tích dữ liệu trong Python với NumPy và một số thư viện khác trong môi trường khoa học dữ liệu tương tác của Jupyter Notebook.

Cuối cùng, hãy cân nhắc xem các khóa học của DataCamp về thao tác và trực quan hóa dữ liệu. Đặc biệt các khóa hợp tác gần đây của chúng tôi với Continuum Analytics chắc chắn sẽ khiến bạn hứng thú! Hãy xem các khóa Manipulating DataFrames with Pandas hoặc Pandas Foundations.

Chủ đề
Python
Khoa học Dữ liệu
Phân tích dữ liệu

Tìm hiểu thêm về Python

Khóa học

Giới thiệu về NumPy

4 giờ
62.6K
Nâng cao kỹ năng của bạn trong NumPy bằng cách học cách tạo, sắp xếp, lọc và cập nhật các mảng sử dụng dữ liệu kiểm kê cây của NYC.
Xem chi tiếtRight Arrow
Bắt Đầu Khóa Học
Xem thêmRight Arrow
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