iT邦幫忙

2025 iThome 鐵人賽

DAY 27
0

前言:NumPy 是什麼?為什麼大家都在用?

如果你曾經用過 Python 的 list 處理大量數字,

一定會有這種感覺:

「我只是想把每個數字乘以 2,結果 for 迴圈寫了十行,還慢得要命!!」

登愣!這就是 NumPy 誕生的原因

一、 NumPy 是什麼?

NumPy,全名 Numerical Python
是一個用來「加速數值計算」的第三方套件。

它能幫我們:

  • 快速建立 多維陣列(ndarray)
  • 進行矩陣運算、統計分析
  • 取代原本 Python list 裡那些又長又慢的 for 迴圈

https://ithelp.ithome.com.tw/upload/images/20251011/20164721cI09EFaSaY.png

🔹 為什麼它這麼快?

因為底層是用 C 語言 寫的!!
而且它的陣列結構是連續記憶體,不像 Python list 那樣東一塊西一塊。
所以運算起來超順暢~幾十萬筆資料在它眼中只是小菜一碟。

🔹 Numpy在哪裡用得到?厲害在哪?

幾乎所有跟數字、資料或 AI 有關的領域都離不開它:

  • 資料分析 (Pandas):底層全靠 NumPy 陣列在跑
  • 科學運算 (SciPy):數學函式都建構在 NumPy 上
  • 機器學習 (TensorFlow / PyTorch):Tensor 就是進化版的NumPy陣列

https://ithelp.ithome.com.tw/upload/images/20251011/20164721k05yt0iT7U.png

二、一步步認識 NumPy 陣列 (ndarray)

基本建立方式

import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])
print(a)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721acRWL4sE2v.png

說明:

這裡的 a 就是 ndarray
一種比 list 更高效、更聰明的陣列型態。

你可以利用以下的語法快速查看它的屬性:

print(a.ndim)   # 維度數量
print(a.shape)  # 各維度大小
print(a.size)   # 元素總數
print(a.dtype)  # 資料型態

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/201647216Sm02SpmK9.png

補充:
list 裡的元素可以混合不同型態,
但 ndarray 所有元素都必須是相同型態,
這就是它能「又快又省」的祕密!

二、陣列建立方式大集合

想要什麼樣的陣列?NumPy 都幫你準備好了。

函式 說明
np.zeros((3,4)) 全部填 0
np.ones((2,3)) 全部填 1
np.full((2,2), 7) 全部填 7
np.eye(3) 單位矩陣
np.diag([1,2,3]) 對角線為指定值

我們來一一的介紹!

1.np.zeros(rows,cols):全零陣列

# 1. 生成全零陣列
zeros_arr = np.zeros((2, 3))  # 2x3 的全零矩陣
print("全零陣列:\n", zeros_arr)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721QFcmKziCoW.png

2.np.ones(rows,cols):全一陣列

# 2. 生成全一陣列
ones_arr = np.ones((3, 2))  # 3x2 的全一矩陣
print("全一陣列:\n", ones_arr)

輸出:

https://ithelp.ithome.com.tw/upload/images/20251011/20164721xwDbGAGfIN.png

3.np.full((rows,cols),num):生成全部為指定數字的陣列

# 3. 生成全部為指定數字的陣列
full_arr = np.full((2, 2), 7)  # 2x2,全是 7
print("\n全 7 陣列:\n", full_arr)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721NmKg1gYZqv.png

4.np.eye( ) :建立對角矩陣

#4.建立對角矩陣,對角皆1,其餘為0

indentity_matrix = np.eye(3)        
print('eye:')
print(indentity_matrix)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721vmW46421p7.png

5.np.diag( [ num,num,num]):建立對角矩陣,斜對角為指定的數字

#5.建立對角矩陣,斜對角為指定的數字
diag_matrix = np.diag([1,2,3])
print(diag_matrix)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721XqAlgTOyPx.png

三、利用NumPy自動產生數列:arange & linspace

懶得自己打數字?交給電腦生!

arange() vs linspace():一個像走路、一個像切片

這兩個函式都可以「自動產生一串數字」,但概念其實完全不一樣。
我們用生活例子來比喻:

1.np.arange(start, stop, step):像「走樓梯」

「從起點開始,每次走固定的步伐,直到終點前停下。」

  • start:起始值
  • stop:結束值(不包含)
  • step:每次間隔

範例:

import numpy as np
print(np.arange(1, 10, 2))

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721Q94cnfX8jv.png

說明:

就像「我從 1 樓開始,每次走 2 層,到 10 樓之前就停」。所以最後停在9樓。
np.arange()用的是固定步長
所以如果你給它「小數間隔」,有時會出現浮點誤差!
(例:np.arange(0, 1, 0.1),可能出現 0.30000004 之類的值 )

到這邊為止,不曉得讀者有沒有和我有一樣的感覺,
這個np.arange()感覺有點似曾相識對吧!!

沒錯!!就是我們之前學的range()
我們來介紹一下他們到底差在哪?

補充:range() vs np.arange()

看似雙胞胎,其實不同世界的人!

雖然名字很像,但 range() 是 Python 內建的,
np.arange() 則是 NumPy 家族的一員。

它們都能「產生一串連續的數字」,但背後的邏輯與用途其實完全不同。

比較項目 range() np.arange()
所屬套件 Python 內建 Numpy 模組
是否需 import 不需 需先 import numpy as np
回傳型態 <class 'range'> <class 'numpy.ndarray'>
可否用 float 步長 可以
是否可直接運算 否(需轉 list) 可直接運算
是否支援多維陣列 可 reshape 成多維
共同點 都有 start、stop、step 三參數,左閉右開 [start, stop),都能用在 for 迴圈

簡單來說:

  • range() 回傳的是「一個會產生數字的物件」(不是陣列)
  • np.arange() 則直接幫你生出一整個 Numpy 陣列

2.np.linspace(start, stop, num):像「切蛋糕」

「我知道蛋糕的頭和尾,要切成幾等份。」

  • start:起始值
  • stop:結束值(包含!)
  • num:總共要幾個點

範例:

print(np.linspace(1, 10, 5))

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721WtwZJqqgVp.png

想像你有一條 1 到 10 的數線,
你說「幫我平均切成 5 段」,NumPy 就幫你生出 5 個等距的數字(包含頭尾)。

小提醒:
linspace固定分段數,而不是固定間隔。

所以它在繪圖、取樣(像畫 sin 波、時間軸)時特別常用。

最後我做了一張slide來做個小總結:
https://ithelp.ithome.com.tw/upload/images/20251011/201647213wtrBkTfzc.png

四、陣列形狀重整 reshape / resize

當你想改變資料的「外觀」時,就用這兩個。

a = np.arange(6)

print(a)
print("==我是分隔線==")
print(a.reshape(2,3))   
print("==我是分隔線==")
print(np.resize(a, (3,2)))  

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721nwdgDl0PMz.png

五、陣列取值與修改

NumPy 支援更靈活的取值方式:

a = np.array([[1,2,3],[4,5,6],[7,8,9]])

print("取第2列第3欄的值:",a[1,2])    
print("取所有列的第2欄:",a[:,1])    
a[1,2] = 99       # 修改
print("修改過後:",a)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721MiMKMAzne0.png

同時也支援切片與倒序:

print("切片:")
print(a[0:2, 1:3])
print("==我是分隔線==")
print("倒序:")
print(a[::-1])

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721sh6Kf7dVDz.png

六、數值運算,快得不像話!!

這裡是 NumPy 的主場,不用 for 迴圈!直接算:

a = np.array([[1,2,3],[4,5,6]])
b = np.array([10,10,10])

print(a + b)
print("==我是分隔線==")
print(a - b)
print("==我是分隔線==")
print(a * b)
print("==我是分隔線==")
print(a / b)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721h5posSPb8N.png

除了用運算符號,也可以用語法:

add( ),subtract( ),multiply( ),divide( )

import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
b = np.array([10,10,10])
c = np.add(a,b)
print(c)
print()
d = np.subtract(a,b)
print(d)
print()
f = np.multiply(a,b)
print(f)
print()
g = np.divide(a,b)
print(g)
print()

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721wnZ6whybmT.png

也可以進行四捨五入的運算喔!!

x = np.array([1.5, 2.5, -0.5, 0.5])
print(np.around(x))  # 四捨五入到最近偶數
print("====我是分隔線====")
print(np.floor(x))   # 無條件捨去
print("====我是分隔線====")
print(np.ceil(x))    # 無條件進位

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721PdCFxkvTmE.png

補充:
np.around()的特性:
IEEE 754 標準下,1.5 和 2.5 都會捨入偶數的整數

總和、最大最小、平均與中位數:

a = np.array([[0,30,45],[60,75,90]])

print(np.sum(a))           # 總和
print(np.min(a))           # 最小值
print(np.max(a))           # 最大值
print(np.mean(a))          # 平均值
print(np.median(a))        # 中位數

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721h75JuU6zoE.png

牛刀小試:藥品銷售分析

import numpy as np

# 假設已知資料
prices = np.array([100, 200, 150, 80, 120])  # 每種藥品單價(元)
sold = np.array([30, 15, 40, 20, 10])        # 每種藥品當日銷售數量(盒)

# 計算每種藥品的總營收
total_revenue_per_product = prices * sold
print("每種藥品的總營收:", total_revenue_per_product)

# 輸出全部藥品的總營收
total_revenue = total_revenue_per_product.sum()
print("全部藥品的總營收:", total_revenue)

# 計算平均售價
average_price = prices.mean()
print("平均售價:", average_price)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251011/20164721FOwEzCNs80.png

七、延伸補充:為什麼 Numpy 比 list 快?

https://ithelp.ithome.com.tw/upload/images/20251011/20164721QxTwN9kAXM.png

我們可以看一下差別:假設要把數字們都平方

#與list的差別
import numpy as np

# ===== 用 list 的作法 =====
my_list = [1, 2, 3, 4, 5]
list_squared = []
for num in my_list:
    list_squared.append(num ** 2)
print("list 平方結果:", list_squared)  # [1, 4, 9, 16, 25]

# ===== 用 NumPy 的作法 =====
arr = np.array([1, 2, 3, 4, 5])
print("NumPy 平方結果:", arr ** 2)     # [ 1  4  9 16 25 ]

有發現嗎?用list還需要搭配for-loop,
但Numpy的話直接兩行結束!!!(超快速)

結語

如果你看到這裡,恭喜你!
我們今天正式踏進了數值計算的世界 🎉

老實說,第一次接觸 NumPy 的時候我也想過:
「有需要再學這個語法嗎?我乖乖用 list 搭配 for-loop 不也能跑出結果?」

但真的動手跑過一次,你就會發現 ——
這玩意兒不只是「快」,是超級快。
而且程式碼變得乾淨、聰明又漂亮,
尤其在做大型專案的時候,那個差距真的很有感!!

NumPy 就像幫你裝上了加速引擎,
讓原本吃力的數字處理變得優雅又順暢!

明天,我們要繼續深入「數據分析」的世界!
其實我猶豫了很久要在最後幾天介紹什麼主題,
但後來想到,會來看這個系列的朋友,大多都是剛入門的初學者,
所以我決定帶大家一起學一個「人人都能上手」的主題 —— 資料分析!

在大學裡、在各種領域中,
不論你讀商管、社科、甚至設計,
都會接觸到「用 Python 做資料分析」這件事~
明天,我們就要開始親手玩玩看~

那我們就明天見囉!!

(又是一篇快一萬字的文)


上一篇
【Day26】留下足跡才美麗!一次搞懂 Python 檔案處理全攻略
系列文
Python 小白的逆襲:30 天從零到能教人的精華筆記,寫給迷惘的你與當年的我自己!27
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言