數聚點

數聚點

Share this post

數聚點
數聚點
約維安計畫:NumPy
高級約維安

約維安計畫:NumPy

第三十三週

Yao-Jen Kuo's avatar
Yao-Jen Kuo
May 15, 2023
∙ Paid
2

Share this post

數聚點
數聚點
約維安計畫:NumPy
Share
來源:https://github.com/numpy/numpy/tree/main/branding/logo

什麼是 NumPy

NumPy 是 Numeric Python(or Numerical Python)的簡稱,是 Python 最重要的資料科學模組之一。NumPy 創造了 ndarray 的資料結構類別以及大量的通用函數與聚合函數,讓 Python 使用者能夠對數列進行快速的數值計算、對數列使用統計函數、進行線性代數運算以及操作隨機的模擬任務等。NumPy 的前身為兩個模組,都是在 1990 年代中期所誕生的 Numeric 與 Numarray 模組,NumPy 於 2005 年集兩者之大成問世。對 NumPy 模組的發展歷史有興趣的讀者可以進一步參考 Array Programming with NumPy1 以及 NumPy - Wikipedia2。

安裝與載入 NumPy

NumPy 的安裝可以透過 pip 或者 conda,如果讀者的 Python 是從 Python.org 下載的就直接透過 pip 安裝,假如是約維安計畫的成員,Python 應該是 Miniconda 版本,那麼建議可以透過 conda 安裝3。

$ pip install numpy==MAJOR.MINOR.PATCH
$ conda install numpy==MAJOR.MINOR.PATCH

如果希望從既有的 NumPy 版本更新升級,可以在 install 指令之後加上 -U 或 --update-deps 參數。

$ pip install -U numpy==MAJOR.MINOR.PATCH
$ conda install -c conda-forge --update-deps numpy==MAJOR.MINOR.PATCH

官方文件建議載入模組的所有功能並且縮寫為 np。

import numpy as np

利用兩個模組內建屬性檢視 NumPy 的安裝版本與路徑。

print(np.__version__)
print(np.__file__)

怎樣學好 NumPy

學好 NumPy 的關鍵是理解其核心功能以及主要應用場景:

  • 如何使用 ndarray 來進行數值操作。

  • 如何使用 NumPy 定義的函數對 ndarray 進行數值運算。

  • 如何應用 ndarray 於向量、矩陣以及張量的操作及運算。

  • ndarray 是其他資料科學模組 Pandas、Matplotlib 與 Scikit-Learn 的基石。

如何創造 ndarray

常見兩種創造 ndarray 的方式有:從既有的 list 創造或者利用函數創造。

# Create ndarray from a list
prime_list = [2, 3, 5, 7, 11]
prime_array = np.array(prime_list)
print(prime_array)
print(type(prime_array))

利用 NumPy 定義的函數可以創造出內容元素相同、數列型態以及具備特定分配的 ndarray。

# Create ndarray with identical elements
print(np.zeros(5, dtype=int))
print(np.ones(5, dtype=float))
print(np.full(5, 6))
# Create ndarray as a sequence
print(np.arange(1, 11, 2))
print(np.linspace(1, 9, 5, dtype=int))
# Create ndarray with a specific distribution
m = 10000
uniform_array = np.random.random(m)
normal_array = np.random.normal(0, 1, m)
randint_array = np.random.randint(1, 7, size=m)
print(uniform_array)
print(normal_array)
print(randint_array)

常用的 ndarray 屬性

常用的 ndarray 屬性有四個,分別是:

  1. ndarray.ndim 維度數。

  2. ndarray.shape 外型。

  3. ndarray.size 元素個數。

  4. ndarray.dtype 資料類別。

print(prime_array.ndim)
print(prime_array.shape)
print(prime_array.size)
print(prime_array.dtype)

從 ndarray 中擷取元素、片段的方式

利用與 list 相同的 indexing/slicing 語法。

print(prime_array[0]) # indexing
print(prime_array[0:3:1]) # slicing

利用 ndarray 的特性,在中括號使用多個索引取得指定位置的元素。

matrix = np.array([[5, 5],
                   [6, 6],
                   [55, 66]])
print(matrix[2, 1])

利用 ndarray 的特性,能夠以 Fancy indexing 或 Boolean indexing 的方式取得指定位置、符合指定條件的元素。Fancy indexing(華麗索引?)指的是以一個 list 決定要取得哪些位置的元素,Boolean indexing 指的是以一個外型相同、充滿布林值的 ndarray 來取得對應位置為 True 的元素。

# Fancy indexing
print(prime_array[[0, 1, 4]])
# Boolean indexing
print(prime_array % 2 == 1)
print(prime_array[prime_array % 2 == 1])

常用的 ndarray 操作

我們常對 ndarray 進行的操作有調整外型、合併以及分割。使用 ndarray 的 reshape() 方法調整成指定外型,在其他維度已經決定時可以方便地指定 -1 給最後一個維度;使用 ndarray 的 ravel() 方法打平成一維。

array_range = np.arange(1, 13)
print(array_range) # (12,)
print(array_range.reshape(3, 4))  # (3, 4)
print(array_range.reshape(3, -1)) # (3, 4)
print(array_range.reshape(-1, 4)) # (3, 4)
print(array_range.reshape(3, 4).ravel()) # (12,)

合併操作能夠透過 np.concatenate() 函數達成,預設為垂直方向的合併(增加列數),指定參數 axis=1 則能夠調整為水平方向的合併(增加欄位)。

array_a = np.arange(1, 5).reshape(2, 2)
array_b = np.arange(5, 9).reshape(2, 2)
print(np.concatenate((array_a, array_b)))
print(np.concatenate((array_a, array_b), axis=1))

分割操作能夠透過 np.split() 函數達成,預設為垂直方向的分割,指定參數 axis=1 則能夠調整為水平方向的分割。

array_range = np.arange(20).reshape(-1, 2)
upper_array, lower_array = np.split(array_range, 2)
left_array, right_array = np.split(array_range, 2, axis=1)
print(upper_array)
print(lower_array)
print(left_array)
print(right_array)

NumPy 的數值運算函數

NumPy 提供非常豐富、能夠針對 ndarray 進行運算的通用函數、聚合函數。通用函數是具備向量化(Vectorized)特性的函數,接受固定數量、外型的輸入並對應相同數量、外型的輸出。

array_range = np.arange(10)
print(np.power(array_range, 2))
print(np.exp(array_range))

如果需要自行定義能夠對 ndarray 運算應用的通用函數,可以使用 np.vectorize() 函數將只能作用於純量的函數轉換為能作用於 ndarray 的通用函數。

def is_prime(x):
    number_of_divisors = 0
    for integer in range(1, x + 1):
        if x % integer == 0:
            number_of_divisors += 1
    return number_of_divisors == 2
vectorized_is_prime = np.vectorize(is_prime)
vectorized_is_prime(np.arange(10))

聚合函數則是能夠將多個資料值輸入摘要為單一值輸出的函數,在使用 NumPy 的聚合函數時有兩個值得注意的特性:可以沿指定的軸(axis)進行聚合、針對含有 np.nan(Not a Number)的 ndarray 有相對應名稱的聚合函數可以運算。

# Aggregate along specific axis
array_range = np.arange(1, 16, dtype=float).reshape(3, 5)
print(np.sum(array_range))
print(np.sum(array_range, axis=0))
print(np.sum(array_range, axis=1))
# Similar function names for array with np.nan
array_range[2, 4] = np.nan
print(array_range)
print(np.sum(array_range))
print(np.nansum(array_range))

入門 NumPy 之後,我們就能夠在下次的電子報中透過 ndarray 認識線性代數最重要的內容:矩陣運算。

在認識了 NumPy 的核心功能以及主要應用場景之後,第三十三週約維安計畫:NumPy 來到尾聲,希望您也和我一樣期待下一篇文章。

對於這篇文章有什麼想法呢?喜歡😻、留言🙋‍♂️或者分享🙌

約維安計畫學員專區

This post is for paid subscribers

Already a paid subscriber? Sign in
© 2025 DATAINPOINT, INC.
Privacy ∙ Terms ∙ Collection notice
Start writingGet the app
Substack is the home for great culture

Share