文章目錄
本系列文章希望能讓有興趣學習資料科學 (Data Science) 及 Python 程式語言的人,透過全新不同的方式,由淺入深獲得相關知識,除了前一篇的 Python 初體驗文章,這一篇將帶領大家在未來進入資訊科學領域前,了解如何利用 NumPy 函式庫的強大功能,理解相關基礎應用。
如果想要進一步了解 Python,可以參考《Python for Beginners》系列文章。此系列文章提供給有興趣的讀者一個淺顯易懂,圖文解說,範例練習及 Quiz 測驗的學習園地,非常適合初學者學習。接下來就讓我們 Hello NumPy!Hello World!
1. NumPy 簡介
NumPy 是 Python 在進行科學運算時,一個非常基礎的套件 (Package),同時也是非常核心的函式庫 (Library),它具有下列幾個重要特色:
- 提供非常高效能的多維陣列 (multi-dimensional array) 數學函式庫
- 可整合 C/C++ 及 Fortran 的程式碼
- 方便有用的線性代數 (Linear Algebra) 及傅立葉轉換 (Fourier Transform) 能力
- 利用 NumPy Array 替代 Python List
- 可定義任意的數據型態 (Data Type),使得能輕易及無縫的與多種資料庫整合
在邁向資料科學 (Data Science)、機器學習 (Machine Learning)、深度學習 (Deep Learning) 及人工智慧 (Artificial Intelligence) 的路上, Python 還有許許多多有趣好玩的套件(例如:Pandas、SciPy、Sympy、Matplotlib、Scikit-learn 等),這些與資料科學 (Data Science) 相關的重要套件幾乎都是架構在 Numpy 基礎上做應用,因此學會 NumPy 對後續的學習及理解將會有很大的幫助。
2. NumPy 安裝
安裝 NumPy 的唯一先決條件是 Python 本身。如果您還沒有 Python 並且想要最簡單的入門方法,我們建議您可以考慮使用 Anaconda 發行版 (Anaconda Distribution),它包括 Python、NumPy 和許多其他用於科學計算和資料科學的常用套件包。
NumPy 可以利用 CONDA 或 PIP 等套件包管理器來安裝(可參考 Anaconda 3 介紹及安裝教學)。
- CONDA
如果使用 conda,最佳實作方式是使用虛擬環境,而不是安裝在基礎環境中:
conda create -n MyEnv
conda activate MyEnv
實際安裝的指令:
conda install numpy
- PIP
如果你使用 pip,你可以使用系列方式來安裝 NumPy:
pip install numpy
在使用 pip 時,建議一樣使用虛擬環境。相關虛擬環境的詳細指南及教學可參考下面文章。
3. NumPy 基礎知識與操作
在介紹 NumPy 基礎操作前,必須先進行 import NumPy 的動作,才能使用其函式庫內的相關功能,大家可以在Python IDLE 中的 Shell 環境中試著輸入下方式子:
>>> import numpy as np
你也可以在其它環境中練習,例如 Google Colab 或 Jupyter Notebook,可參考下面文章介紹:
接下來我們將依序對一些基本及重要的功能逐一介紹。
3.1 NumPy 陣列 (NumPy Array)
學習資料科學 (Data Science) 或機器學習 (Machine Learning) 時,利用 NumPy 在陣列的操作是非常重要,其主要功能都架構在多重維度(N-dimensional array)的 ndarray 上。ndarray 是一個可以裝載相同類型資料的多維容器,維度大小及資料類型分別由 shape 及 dtype 來定義。
通常我們會稱一維陣列為向量 (vector),二維陣列為矩陣 (matrix),未來在機器學習系列文章中會再仔細介紹此一部分。而一維陣列到多維陣列的各軸向(axis)可參考下圖,對於後續學習幫助很大。
- 建立陣列及初始值
我們會先 import numpy 模組,透過傳入 Python 的 list (串列) 或 tuple (元組) 到 numpy.array() 建立陣列。
>>> import numpy as np
>>> a = np.array([1, 2, 3, 4]) #一維陣列建立
>>> b = np.array([(2.5, 1, 3, 4.5), (5, 6, 7, 8)], dtype = float) #二維陣列建立
>>> c = np.array([[(2.5, 1, 3, 4.5), (5, 6, 7, 8)], [(2.5, 1, 3, 4.5), (5, 6, 7, 8)]], dtype = float) #三維陣列建立
下面幾種方式除了可以建立陣列外,也可以同時給予初始值。
>>> np.zeros((2, 3)) # 建立一個2x3全為0的陣列
>>> np.ones((2, 3, 4)) # 建立一個2x3x4全為1的陣列
>>> np.arange(1, 10, 2) # 建立一個由1開始,不超過10,間隔值為2的均勻數值陣列
>>> np.linspace(0, 10, 5) # 建立一個0到10之間,均勻的5個數值陣列
>>> np.full((3,2), 8) # 建立一個3x2全為8的陣列
>>> np.eye(2) # 建立一個5x5的單位矩陣
>>> np.random.random((2,3)) # 建立一個2x3的隨機值矩陣
3.2 輸入/輸出 (I/O)
>>> import numpy as np
>>> original_array = np.array([1, 2, 3])
>>> np.save('my_array', original_array)
>>> np.savetxt('my_array.txt', original_array)
>>> array_from_npy = np.load('my_array.npy')
>>> print(array_from_npy)
[1 2 3]
>>> array_from_txtfile = np.loadtxt('my_array.txt')
>>> print(array_from_txtfile)
[1. 2. 3.]
3.3 資料型態 (Data Types)
NumPy 支援比 Python 更多的數字類型。可參考下圖。
其中有 5 種基本數字類型比較常用,分別是 booleans (bool)、integers (int)、unsigned integers (uint)、floating point (float) 和 complex。
>>> np.array([1.2, 3, 5.2], dtype='i')
array([1, 3, 5], dtype=int32)
>>> np.array([1, 2, 3], dtype='f')
array([1., 2., 3.], dtype=float32)
>>> x = np.float32(1)
>>> x
1.0
>>> y = np.int_([1.0, 2.3])
>>> y
array([1, 2])
3.4 陣列查察 (Inspecting Your Array)
>>> a = np.array([1, 2, 3])
>>> b = np.array([(2.5, 1, 4.5), (5, 6, 7, 8)])
>>> a.shape # Array dimensions
(3,)
>>> len(a) # Length of array
3
>>> len(b) # Length of array
2
>>> b.ndim # Number of array dimensions
1
>>> a.size # Number of array elements
3
>>> b.size # Number of array elements
2
>>> b.dtype # Data type of array elements
dtype('O')
>>> a.dtype # Data type of array elements
dtype('int32')
>>> b.dtype.name # Name of data type
'object'
>>> a.dtype.name # Name of data type
'int32'
>>> a.astype(float) # Convert an array to a different type
array([1., 2., 3.])
3.5 尋求幫助 (Asking For Help)
>>> np.info(max)
max(iterable, *[, default=obj, key=func]) -> value
max(arg1, arg2, *args, *[, key=func]) -> value
With a single iterable argument, return its biggest item. The
default keyword-only argument specifies an object to return if
the provided iterable is empty.
With two or more arguments, return the largest argument.
>>> np.info(np.ndarray.dtype)
Data-type of the array's elements.
Parameters
----------
None
Returns
-------
d : numpy dtype object
See Also
--------
numpy.dtype
Examples
--------
>>> x
array([[0, 1],
[2, 3]])
>>> x.dtype
dtype('int32')
>>> type(x.dtype)
<type 'numpy.dtype'>
3.6 陣列數學運算 (Array Mathematics)
- Arithmetic Operations
>>> a = np.array([1, 2, 3])
>>> b = np.array([2, 4, 6])
>>> np.add(a, b) # 陣列加法,也可以a + b
array([3, 6, 9])
>>> np.subtract(a, b) # 陣列減法,也可以a – b
Array([-1, -2, -3])
>>> np.multiply(a, b) # 陣列乘法,也可以a * b
Array([ 2, 8, 18])
>>> np.divide(a, b) # 陣列除法,也可以a / b
array([0.5, 0.5, 0.5])
除了四則運算之外,也可以對陣列做其他的算術運算
>>> c = np.array([1, 4, 9])
>>> np.sqrt(c)
array([1., 2., 3.])
>>> np.sin(c)
array([ 0.84147098, -0.7568025 , 0.41211849])
>>> np.cos(c)
array([ 0.54030231, -0.65364362, -0.91113026])
>>> np.log(c)
array([0. , 1.38629436, 2.19722458])
- Comparison
NumPy 也提供 Array 幾種比較方式如下:
>>> a = np.array([(1, 2, 3), (4, 5, 6)])
>>> b = np.array([(1, 3, 3), (4, 7, 6)])
>>> c = np.array([(1, 2, 3), (4, 5, 6)])
>>> a == b # Element-wise comparison
array([[ True, False, True],
[ True, False, True]])
>>> a < 3 # Element-wise comparison
array([[ True, True, False],
[False, False, False]])
>>> np.array_equal(a, b) # Array-wise comparison
False
- Aggregate Functions
利用 NumPy 的聚合函數 (Aggregate Functions) 於統計領域是很方便的,常見聚合函數有最大值(max)、最小值(min)、中位數( median)、平均數(mean)、方差、標準差(std),在 NumPy 的使用上是很常見的。
>>> a = np.array([2, 5, 7])
>>> b = np.array([(0, 1), (2, 3)])
>>> a.sum() # Array-wise sum
14
>>> a.max() # Array-wise maximum value
7
>>> a.min() # Array-wise minimum value
2
>>> b.max(axis=0) # Maximum value of an array row
array([2, 3])
>>> b.max(axis=1) # Maximum value of an array row
array([1, 3])
>>> np.median(a) # Median
5.0
>>> np.mean(a) # Mean
4.666666666666667
>>> np.std(a) # Standard deviation
2.0548046676563256
3.7 陣列複製與排序 (Copying & Sorting Arrays)
NumPy 同時提供多種陣列間的 copying 及 sorting 功能,我們就先簡介其中幾種做法。
>>> a = np.array([5, 13, -5, -2, 3, 4, 7])
>>> a.sort()
>>> a
array([-5, -2, 3, 4, 5, 7, 13])
>>> b = np.copy(a)
>>> b
array([-5, -2, 3, 4, 5, 7, 13])
3.8 子集(Subsetting)、切片(Slicing)、索引(Indexing)
藉由下列範例你將會清楚了解 Subsetting、Slicing 及 Indexing 的應用。我們先試著各建立一個一維陣列(1D array) 及二維陣列(2D array) 如下:
>>> a = np.array([1, 2, 3, 4])
>>> b = np.array([(2.5, 1, 3, 4.5), (5, 6, 7, 8)])
- Subsetting
>>> a[2]
3
>>> b[1, 3]
>>> 8.0
- Slicing
>>> a[0 : 2]
array([1, 2])
>>> b[0 : 2, 1]
array([1., 6.])
>>> b[1, 0 : 2]
array([5., 6.])
>>> b[ : 1]
array([[2.5, 1. , 3. , 4.5]])
- Boolean Indexing
>>> a[a < 4]
array([1, 2, 3])
- Fancy Indexing
>>> b[[1, 1, 0, 0], [0, 2, 1, 0]]
array([5. , 7. , 1. , 2.5])
3.9 陣列操作 (Array Manipulation)
- Transposing Array
>>> a = np.array([(1, 3, 5, 7), (2, 4, 6, 8)])
>>> a
array([[1, 3, 5, 7],
[2, 4, 6, 8]])
>>> b = np.transpose(a)
>>> b
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
>>> b.T
array([[1, 3, 5, 7],
[2, 4, 6, 8]])
- Changing Array Shape
>>> a = np.array([(1, 3, 5, 7), (2, 4, 6, 8)])
>>> a
array([[1, 3, 5, 7],
[2, 4, 6, 8]])
>>> a.shape
(2, 4)
>>> a.ravel()
array([1, 3, 5, 7, 2, 4, 6, 8])
>>> a.reshape(4, 2)
array([[1, 3],
[5, 7],
[2, 4],
[6, 8]])
- Adding/Removing Elements
>>> a = np.array([1, 2, 3, 4]) # 建立a陣列
>>> b = np.array([6, 7, 8, 9]) # 建立b陣列
>>> np.append(a, 5)
array([1, 2, 3, 4, 5])
>>> np.append(a, b)
array([1, 2, 3, 4, 6, 7, 8, 9])
>>> np.insert(a, 1, 0)
array([1, 0, 2, 3, 4])
>>> np.delete(b, [2])
array([6, 7, 9])
>>> a.resize((2,2))
>>> a
array([[1, 2],
[3, 4]])
- Combining Arrays
利用 NumPy 將 array 間做彼此合併或連結的方法很多,這裡先簡單介紹一些常用的方式。
- vstack:垂直方向合併
- hstack:水平方向合併
>>> a = np.array([(1, 2), (3, 4)])
>>> b = np.array([(5, 6), (7, 8)])
>>> np.vstack((a, b)) # 垂直方向合併
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
>>> np.hstack((a, b)) # 水平方向合併
array([[1, 2, 5, 6],
[3, 4, 7, 8]])
- concatenate (axis = 0):沿垂直方向合併
- concatenate (axis = 1):沿水平方向合併
>>> np.concatenate((a, b), axis = 0) # axis=0,沿垂直方向合併
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
>>> np.concatenate((a, b), axis = 1) # axis=1,沿水平方向合併
array([[1, 2, 5, 6],
[3, 4, 7, 8]])
- Splitting Arrays
跟Combining Arrays一樣,NumPy 提供一些在不同軸向的切割方式,如下說明:
- vsplit:垂直方向分割
- hsplit:水平方向分割
>>> a = np.array([(1, 2, 3, 4, 5, 6), (-1, -2, -3, -4, -5, -6), (2, 4, 6, 8, 10, 12)])
>>> a
array([[ 1, 2, 3, 4, 5, 6],
[-1, -2, -3, -4, -5, -6],
[ 2, 4, 6, 8, 10, 12]])
>>> np.vsplit(a, 3) # 垂直方向分割
[array([[1, 2, 3, 4, 5, 6]]), array([[-1, -2, -3, -4, -5, -6]]), array([[ 2, 4, 6, 8, 10, 12]])]
>>> np.hsplit(a, 2) # 水平方向分割
[array([[ 1, 2, 3],
[-1, -2, -3],
[ 2, 4, 6]]), array([[ 4, 5, 6],
[-4, -5, -6],
[ 8, 10, 12]])]
>>> np.split(a, 3, axis=0) # axis=0,沿垂直方向分割
[array([[1, 2, 3, 4, 5, 6]]), array([[-1, -2, -3, -4, -5, -6]]), array([[ 2, 4, 6, 8, 10, 12]])]
>>> np.split(a, 2, axis=1) # axis=1,沿水平方向分割
[array([[ 1, 2, 3],
[-1, -2, -3],
[ 2, 4, 6]]), array([[ 4, 5, 6],
[-4, -5, -6],
[ 8, 10, 12]])]
後續會再分享 NumPy 相關文章給有興趣的初學者。
讀者若想要多了解一些 Python 的基本程式語法,可以參考 Python for Beginners 系列文章,裡面有大量範例及 Quiz 練習。若是想要了解一些 AI 、機器學習及深度學習的基礎概念,可以參考這一本書【從 AI 到 生成式 AI:40 個零程式的實作體驗,培養新世代人工智慧素養】,它將帶領讀者在不會程式、不會數學也OK!的情況下,建立最完整的 AI 入門知識。
如果你喜歡這篇文章歡迎訂閱、分享(請載名出處)與追蹤,並持續關注最新文章。同時 FB 及 IG 也會不定期提供國內外教育與科技新知。