跳到主要內容

Day 16 NumPy 運算與索引

Day 16 NumPy 運算與索引

引言

昨天認識了 ndarray 與基本運算,今天要把 NumPy 真正威力強大的部分學起來:索引、切片、廣播與統計函式。這幾個機制讓我們能用極短的程式碼完成大量資料的篩選、轉換與彙整,是資料科學家每天都在用的核心技能。學會之後,從此處理幾萬甚至幾百萬筆資料都不再痛苦,可以說是從「寫 Python」升級到「用 Python 做資料工作」的轉捩點。在真實的資料科學工作裡,NumPy 的角色雖然會逐漸被 Pandas 與 PyTorch 取代,但底層運算邏輯完全相同,所以這幾天打好的基礎會一直派上用場。

這幾個觀念也會一路用到後續的 Pandas 與 PyTorch:Pandas 的 DataFrame 篩選語法借鏡自 NumPy 的布林索引,PyTorch 的張量運算更直接延伸 NumPy 的廣播規則。先把基礎打穩,後面就會順很多。建議在進入今天的內容前,確認昨天安裝的 NumPy 還能正常匯入,並熟悉昨天的 ndarray 建立方式。今天的範例都不大,可以放心全部跑過一遍,確認輸出與預期一致。

索引與切片:取出你想要的部分

NumPy 的索引寫法和 Python 串列很像:中括號內放索引值,從 0 開始。多維陣列則用逗號分隔,例如 x[row, col]。切片用冒號寫成 x[start:stop:step],可以省略任何一段。掌握這些基本寫法之後,就能用一致的方式處理向量、矩陣甚至更高維度的張量。例如影像資料常用 (高度, 寬度, 通道) 三維陣列,這時用 x[:, :, 0] 就能取出第一個通道的所有像素。

import numpy as np

x = np.arange(1, 13).reshape(3, 4)
print(x)
# 輸出:
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]

print(x[0])         # 第一列:[1 2 3 4]
print(x[0, 0])      # 第一列第一個:1
print(x[-1, -1])    # 最後一列最後一個:12
print(x[1, :])      # 第二列整列
print(x[:, 1])      # 第二欄整欄
print(x[:2, :2])    # 左上 2x2 子矩陣

切片取出的是「檢視(view)」,修改切片會連動到原陣列。如果想拿到獨立副本,要用 x[:, 1].copy()。這個觀念在處理大型資料時很重要,能避免不必要的記憶體複製,同時也提醒我們修改資料時要格外小心。Python 串列的切片會自動產生新串列,但 NumPy 為了效能預設走 view 路線,這是新手常踩的雷,寫大型程式時要特別注意。當你不確定手上的陣列是 view 還是 copy,可以呼叫 x.base,如果回傳不是 None 就代表它是 view。

布林索引:用條件篩選資料

布林索引是 NumPy 最常用的篩選方式:用一個布林陣列當作索引,只有 True 的位置會被保留。這比寫一堆 if 條件或迴圈簡潔太多,特別適合做資料清洗。配合 NumPy 提供的逐元素比較,整個篩選邏輯可以一行寫完。例如把 NaN 改成 0、把大於某門檻的值過濾掉、或把符合條件的位置標記起來,都能用布林索引一行搞定。

import numpy as np

scores = np.array([85, 42, 73, 90, 58, 67])
mask = scores >= 60
print(mask)             # 輸出:[ True False  True  True False  True]
print(scores[mask])     # 輸出:[85 73 90 67]
print(scores[scores >= 60])  # 等同上一行

# 多條件:用 & (且)、| (或)
good = scores[(scores >= 60) & (scores < 90)]
print(good)             # 輸出:[85 73 67]

# 直接修改符合條件的元素
scores[scores < 60] = 60
print(scores)           # 輸出:[85 60 73 90 60 67]

注意多條件的寫法:每個條件要加括號,並用 & 與 | 而不是 and、or,因為後者是純 Python 的邏輯運算,沒辦法用在陣列上。這個寫法也是 Pandas 篩選 DataFrame 的基礎,會一路用到後面。實務上做資料清理時,最常見的動作就是把離群值或缺失值「抓出來」,布林索引正是這件事的核心工具。np.isnan() 也是常用的布林函式,搭配 ~ 可以反向取出「非缺失值」的元素。

廣播:不同形狀的陣列一起運算

廣播(broadcasting)讓形狀不完全相同的陣列也能做逐元素運算。例如把一個 (3, 4) 的矩陣加上 (4,) 的向量,NumPy 會自動把向量「廣播」成 (3, 4),整個計算一行就完成,不必手動做 tile 或 reshape。這個機制是 NumPy 寫起來又短又快的關鍵之一,理解之後許多看似複雜的運算都能化為直覺的陣列寫法。

import numpy as np

matrix = np.arange(12).reshape(3, 4)
print(matrix)
# 輸出:
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

bias = np.array([10, 20, 30, 40])
print(matrix + bias)
# 輸出:
# [[10 21 32 43]
#  [14 25 36 47]
#  [18 29 40 48]]

# 欄方向的廣播
col_bias = np.array([[100], [200], [300]])
print(matrix + col_bias)

廣播的規則有兩條:維度數比較少的那個陣列,會在最左邊補 1;接著比較每個維度的大小,如果某一維不相等,必須其中一個是 1,否則會報錯。把規則記起來,未來除錯時可以省下不少時間。常見的應用包括「把每筆資料減去平均值做標準化」、「把特徵乘上縮放係數」、「加上偏置項」等,這些都是機器學習前處理天天會做的事。如果遇到形狀不相容的錯誤,先 print 兩邊的 shape,再試著手動 reshape 看看哪裡可以對齊。

統計與數學函式:沿著軸做彙總

NumPy 提供豐富的統計函式:sum()、mean()、min()、max()、std() 等。它們都能指定 axis,沿著某一維做彙總。例如對二維矩陣,axis=0 是「對每一欄做彙總」,axis=1 是「對每一列做彙總」。掌握 axis 的方向之後,從平均值到標準差都能用一行解決。keepdims 參數能讓結果保留原來的維度,方便後續做廣播運算,這在做神經網路時特別好用。

import numpy as np

x = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(x.sum())        # 全部加總:45
print(x.mean(axis=0)) # 每欄平均:[4 5 6]
print(x.mean(axis=1)) # 每列平均:[2 5 8]

# 累積、找最大、找位置
print(np.cumsum(x))      # 累積和
print(x.argmax())        # 最大值索引(攤平後)
print(x.argmax(axis=0))  # 每欄最大值索引

# 線性代數基礎
A = np.array([[2, 1], [1, 3]])
print(np.linalg.inv(A))   # 反矩陣
print(np.linalg.eigvals(A))  # 特徵值

axis 的方向很容易搞混,可以記一個小口訣:axis=0 是「沿著第一個維度(列)走訪,最後壓縮掉」,所以結果是「每欄一個數」。在後面做機器學習時,會大量用 axis 來區分「對樣本平均」或「對特徵平均」,務必熟悉。np.linalg 模組還提供了矩陣乘法、分解、求特徵值等線性代數運算,這些在後續的線性代數章節會再次出現。除此之外,np.median、np.percentile 也是常用工具,做資料分佈分析時幾乎一定會用到。

結語

今天把 NumPy 的核心機制走完一輪:索引與切片讓我們精準取出想要的元素,布林索引用條件快速篩選,廣播讓不同形狀的陣列能一起運算,統計函式則把資料快速彙總成結論。這幾個觀念的組合,能讓原本需要幾十行程式的工作縮短成兩三行,是資料處理的重要利器。建議自己挑一份小資料(例如成績單、銷售紀錄)練習今天的工具,從中體會「NumPy 寫起來跟 Excel 函式差不多,但能處理更大資料」這件事。如果你對廣播還不太熟練,可以試著把一個一維向量同時加到二維矩陣的每一列、每一欄,這對理解軸的方向非常有幫助。學會這些之後,接下來的 Pandas 章節會非常順手,因為它的核心觀念幾乎是 NumPy 的延伸。

明天,我們會進入 Pandas,看看它如何把 NumPy 的陣列包裝成有欄位、有索引的 DataFrame,並用更直覺的方式處理 CSV 與表格資料。Pandas 在資料科學的日常工作中使用頻率非常高,學會之後處理各種試算表資料都會更得心應手,等於補齊了從 NumPy 純陣列到真實世界表格之間的最後一塊拼圖。

留言

這個網誌中的熱門文章

Day 2 變數與資料型別

Day 2 變數與資料型別 引言 寫程式的過程中,變數與資料型別是處理資料的基礎。變數是存放資料的容器,資料型別則決定這筆資料有哪些特性、可以進行哪些操作。學會定義變數、認識各種資料型別,是學好 Python 的關鍵一步。 這篇文章會帶你了解 Python 中變數的觀念、如何定義變數,以及常見的資料型別,包括整數、浮點數、字串、布林值,還有串列、元組、字典與集合等容器型別。我們也會介紹變數的命名規則與撰寫風格建議,以及如何用 type() 檢查資料型別。 什麼是變數?如何在 Python 中定義變數 變數是在程式執行時用來存放資料的名稱。透過定義變數,我們可以給一筆資料一個名字,並在程式的其他地方用這個名字取用該筆資料。在 Python 中,變數不需要事先宣告型別,因為 Python 是動態型別語言,變數的型別由指定給它的值決定。 定義變數的基本語法 在 Python 中定義變數非常簡單,只要用賦值符號 = 把值指定給變數即可。例如: x = 5 # 定義變數 x,並把整數 5 賦值給它 name = "Alice" # 定義變數 name,並把字串 "Alice" 賦值給它 在這裡,x 是一個變數,被賦予整數 5;name 是另一個變數,被賦予字串 "Alice"。 變數的更新與覆寫 變數的值可以修改,也就是說,我們可以在程式的不同地方給同一個變數新的值。例如: x = 10 # x 最初被賦予 10 x = 15 # x 的值現在被更新為 15 這樣就能依照需求,在程式執行過程中靈活調整變數的值。 Python 的動態型別系統 Python 和某些靜態型別語言不同,定義變數時不需要宣告型別。賦值時,Python 會根據值自動判斷變數的型別。例如: x = 5 # x 是整數 x = 3.14 # x 變成浮點數 x = "Hi" # x 變成字串 同一個變數在程式執行過程中可以存放不同型別的值,這是 Python 的彈性之一。 常見資料型別 在 Python 中,資料型別決定我們可以對變數進行哪些操作...

Day 1 Python 簡介與環境設定

Day 1 Python 簡介與環境設定 引言 在現在的科技環境裡,程式設計已經是一項重要技能。無論你是對資料科學有興趣、想成為開發者,或是想踏入人工智慧(AI)領域,學會寫程式都能明顯提升你的競爭力。在眾多程式語言中,Python 因為語法簡單、功能強大、應用範圍廣泛,成為許多人進入程式世界的第一選擇。這篇文章會帶你認識 Python 的背景與優勢,並一步步教你在不同系統上安裝與設定 Python 開發環境,最後寫出第一支 Python 程式。 為什麼選擇 Python? Python 是一種高階程式語言,由 Guido van Rossum 在 1991 年發布。Python 的設計哲學強調程式碼的可讀性,並用縮排來定義程式區塊,這點和許多使用大括號的語言不同。簡潔的語法讓它成為初學者的理想選擇;就算是經驗豐富的開發者,也能用它完成複雜的專案。 Python 的優勢如下: 簡單易學 :Python 的語法清楚、結構簡潔,初學者很快就能上手。和其他語言相比,學習曲線相對平緩,不需要先弄懂一堆複雜觀念,就能開始寫程式。 應用範圍廣泛 :從資料科學、網頁開發、人工智慧、機器學習、自動化測試到網路爬蟲,Python 都有大量開源函式庫與工具支援,而且在這些領域都扮演關鍵角色。 豐富的函式庫與框架 :Python 的函式庫生態系非常龐大。做資料分析有 NumPy、Pandas;開發網站有 Django、Flask;做深度學習有 TensorFlow、PyTorch。各種需求幾乎都能找到對應的套件,讓開發更有效率。 跨平台支援 :Python 支援 Windows、macOS、Linux 等作業系統,程式通常不需要太多修改就能跨平台執行,讓開發與部署更有彈性。 活躍的社群 :Python 擁有龐大的開發者社群。學習或開發上遇到問題,幾乎都能在社群與論壇(例如 Stack Overflow)找到答案,對初學者來說是很強的後盾,也能減少卡關時的挫折感。 Python 的應用領域 Python 的流行與強大功能,讓許多領域都開始大量使用它。以下是幾個常見的應用方向: 資料科學 :隨著大數據與人工智慧興起,資料科學大量使用 Python。NumPy、Pandas 與 Matplotlib 等工具能處理和分析龐...

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門 隨著人工智慧(AI)與深度學習(Deep Learning)快速發展,越來越多人對這些技術產生興趣。不論你是想踏入 AI 領域的初學者,還是已經有程式基礎的開發者,學好 Python 與深度學習框架(例如 PyTorch),都能為你打開更多可能。 為什麼選擇 Python? Python 已經是資料科學與人工智慧領域的首選語言。它的語法簡潔、容易上手,而且擁有龐大的生態系與大量開源函式庫。無論是資料處理、資料視覺化,還是建立機器學習與深度學習模型,Python 都能勝任。對想進入 AI 或資料科學領域的人來說,它幾乎是必備工具。 PyTorch 是什麼? PyTorch 是由 Meta(原 Facebook)AI 研究團隊開發的開源深度學習框架,以易用、靈活和動態計算圖著稱,是許多 AI 研究人員與開發者的首選。相較於其他框架,PyTorch 的寫法更貼近原生 Python,對初學者相對友善。無論是簡單的實驗,還是複雜的深度學習模型,PyTorch 都能提供強大的支援。 這個系列能帶給你什麼? 這個系列會從 Python 的基礎開始,帶你一步一步學習,最後能自己用 PyTorch 建立深度學習模型。即使你完全沒有寫過程式,也能跟著文章的節奏累積技能,理解 AI 與深度學習的核心觀念。 本系列涵蓋的主題 Python 基礎:從變數、條件判斷到函式與模組。 資料處理工具:用 NumPy 與 Pandas 有效率地操作資料。 資料視覺化:用 Matplotlib 與 Seaborn 把資料畫成圖表。 深度學習的數學基礎:線性代數、微積分與機率。 PyTorch 入門:理解張量、模型建構與 GPU 加速。 基礎深度學習模型:CNN 與 RNN 的實作應用。 深度學習專案實戰:從資料前處理到模型部署的端到端流程。 誰適合這個系列? 程式初學者 :如果你對 AI 充滿好奇,卻還沒寫過程式,系列的第一部分會帶你快速上手 Python,並幫助你理解深度學習的基本觀念。 資料科學愛好者 :如果你已經熟悉一些資料處理方法,進階部分會教你如何用 PyTorch 建構深度學習模型。 開發者與研究人員 :想更深入了...