資料科學 教學 數值計算 資料處理

學習 NumPy:數據處理與分析基礎

課程目標

  • 建立 NumPy 的基本知識。
  • 學習使用 NumPy 進行高效的陣列操作。
  • 掌握 NumPy 的進階功能,如廣播、索引、數學運算、統計分析和結構化陣列。
  • 能夠運用 NumPy 解決實際資料科學問題。
  • 實作 COVID-19 數據分析與視覺化

課程大綱

  1. NumPy 簡介
    • 什麼是 NumPy?
    • NumPy 的優勢:高效的陣列運算
    • 安裝 NumPy
    • 導入 NumPy 模組
    • 查看 NumPy 版本
  2. NumPy 陣列基礎
    • NumPy 陣列 (ndarray) 的概念
    • 從 Python List 建立 NumPy 陣列
    • 建立不同維度的 NumPy 陣列
      • 一維陣列
      • 二維陣列
      • 三維陣列
    • NumPy 陣列的屬性
      • 形狀 (shape)
      • 維度 (ndim)
      • 資料型態 (dtype)
      • 大小 (size)
      • 記憶體大小 (nbytes)
    • NumPy 陣列的資料型態
    • 創建特殊陣列
      • np.zeros() 零陣列
      • np.ones() 單位陣列
      • np.arange() 等差陣列
      • np.linspace() 線性等分陣列
  3. NumPy 陣列的索引與切片
    • 存取單一元素
    • 多維陣列的索引
    • 切片操作
    • 布林索引
    • Fancy Indexing
  4. NumPy 陣列的運算
    • 基本算術運算 (+, -, *, /)
    • Universal Functions (ufuncs)
      • 平方 (square)
      • 平方根 (sqrt)
      • 指數 (exp)
      • 對數 (log)
      • 三角函數 (sin, cos, tan)
    • 聚合運算
      • 總和 (sum)
      • 平均值 (mean)
      • 中位數 (median)
      • 標準差 (std)
      • 最大值 (max)
      • 最小值 (min)
  5. NumPy 的廣播 (Broadcasting)
    • 廣播的概念與用途
    • 廣播的規則
    • 廣播的實際應用
  6. NumPy 的進階應用
    • 陣列的重塑 (reshape)
    • 陣列的合併與分割
      • 水平合併 (hstack)
      • 垂直合併 (vstack)
      • 分割 (split)
    • 條件篩選與布林邏輯
      • 使用布林運算篩選陣列元素
      • np.where() 函數
    • 排序
      • np.sort() 函數
      • np.argsort() 函數
  7. NumPy 的結構化陣列
    • 結構化陣列的概念
    • 定義結構化陣列的資料型態
    • 建立結構化陣列
    • 存取結構化陣列的欄位
    • 使用結構化陣列進行資料分析
  8. NumPy 實例演練
    • 計算移動平均
    • 數據標準化
    • 線性回歸分析
    • 圖像處理
    • COVID-19 數據分析與可視化

課程內容詳解

1. NumPy 簡介

NumPy(Numerical Python 的簡稱)是 Python 中用於科學計算的核心函式庫。它提供了一個高性能的多維陣列對象 ndarray,以及用於處理這些陣列的工具。

NumPy 的優勢:

  • 高效的陣列運算:NumPy 的底層使用 C 語言編寫,對陣列的運算速度非常快。
  • 豐富的數學函數:NumPy 提供了大量的數學函數,可以方便地進行各種數值計算。
  • 廣播 (Broadcasting) 功能:NumPy 允許不同形狀的陣列進行運算,簡化了程式碼的編寫。
  • 方便的索引和切片:NumPy 提供了靈活的索引和切片功能,可以方便地存取和操作陣列中的元素。

安裝 NumPy:

pip install numpy

導入 NumPy 模組:

import numpy as np

查看 NumPy 版本:

print("NumPy 版本:", np.__version__)

2. NumPy 陣列基礎

NumPy 陣列是 NumPy 的核心資料結構,它是一個由相同資料型態元素組成的多維網格。

從 Python List 建立 NumPy 陣列:

py_list = [1, 2, 3, 4, 5]
np_array = np.array(py_list)
print("Python List:", py_list)
print("NumPy Array:", np_array)

建立不同維度的 NumPy 陣列:

# 一維陣列
array1 = np.array([1, 2, 3, 4])
print("一維陣列:", array1)

# 二維陣列
array2 = np.array([[1, 2, 3], [4, 5, 6]])
print("二維陣列:\n", array2)

# 三維陣列
array3D = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print("三維陣列:\n", array3D)

NumPy 陣列的屬性:

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

print("陣列形狀 (shape):", array.shape)   # 輸出:(2, 3)
print("陣列維度 (ndim):", array.ndim)     # 輸出:2
print("陣列資料型態 (dtype):", array.dtype)  # 輸出:int64 (取決於系統)
print("陣列大小 (size):", array.size)     # 輸出:6
print("陣列記憶體大小 (nbytes):", array.nbytes) # 輸出:48 (6 * 8,int64 佔 8 個 byte)

NumPy 陣列的資料型態: NumPy 陣列中的元素必須具有相同的資料型態。NumPy 支援多種資料型態,例如:

  • int: 整數
  • float: 浮點數
  • bool: 布林值
  • string: 字串

創建特殊陣列:

# 創建零陣列
zeros_array = np.zeros((3, 4), dtype=int)
print("零陣列:\n", zeros_array)

# 創建單位陣列
ones_array = np.ones((3, 4), dtype=int)
print("單位陣列:\n", ones_array)

# 創建等差數列
arange_array = np.arange(0, 10, 2)  # 從 0 開始,到 10 結束(不包含 10),步長為 2
print("等差數列:", arange_array)

# 創建線性等分陣列
linspace_array = np.linspace(0, 1, 5)  # 從 0 到 1,平均分為 5 份
print("線性等分陣列:", linspace_array)

3. NumPy 陣列的索引與切片

NumPy 提供了靈活的索引和切片功能,可以方便地存取和操作陣列中的元素。

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

# 存取單一元素
print(array[0, 0])  # 輸出:1

# 切片操作
print(array[0, :])   # 輸出:[1 2 3] (第一行)
print(array[:, 1])   # 輸出:[2 5] (第二列)

# 布林索引
mask = array > 3
print(array[mask])   # 輸出:[4 5 6]

# Fancy Indexing
indices = [0, 2]
print(np.array([1, 2, 3, 4, 5])[indices])  # 輸出:[1 3]

4. NumPy 陣列的運算

NumPy 提供了大量的數學函數,可以方便地進行各種數值計算。

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

# 基本算術運算
print(array + 1)    # 輸出:[2 3 4]
print(array * 2)    # 輸出:[2 4 6]

# Universal Functions (ufuncs)
print(np.square(array))  # 輸出:[1 4 9]
print(np.sqrt(array))    # 輸出:[1.         1.41421356 1.73205081]

# 聚合運算
print(np.sum(array))     # 輸出:6
print(np.mean(array))    # 輸出:2.0

5. NumPy 的廣播 (Broadcasting)

廣播允許不同形狀的陣列進行運算。NumPy 會自動將較小的陣列“擴展”到較大的陣列形狀,以便進行逐元素運算。

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

print(a + b)
# 輸出:
# [[11 22]
#  [13 24]]

6. NumPy 的進階應用

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

# 陣列的重塑 (reshape)
new_array = array.reshape(2, 3)
print(new_array)
# 輸出:
# [[1 2 3]
#  [4 5 6]]

# 陣列的合併 (hstack)
array1 = np.array([1, 2, 3])
array2 = np.array([4, 5, 6])
merged_array = np.hstack((array1, array2))
print(merged_array)  # 輸出:[1 2 3 4 5 6]

# 條件篩選 (where)
array = np.array([1, 2, 3, 4, 5])
new_array = np.where(array > 3, array, 0)  # 大於 3 的元素保留,否則設為 0
print(new_array)  # 輸出:[0 0 0 4 5]

# 排序 (sort)
array = np.array([3, 1, 4, 1, 5, 9, 2, 6])
sorted_array = np.sort(array)
print(sorted_array)  # 輸出:[1 1 2 3 4 5 6 9]

7. NumPy 的結構化陣列

結構化陣列允許您儲存具有不同資料型態的資料。

dtype = [('name', 'U10'), ('age', 'i4'), ('height', 'f4')]
data = np.array([('Alice', 25, 160.5), ('Bob', 30, 175.2)], dtype=dtype)

print(data['name'])   # 輸出:['Alice' 'Bob']
print(data[data['age'] > 26])  # 輸出年齡大於26的

8. NumPy 實例演練

# 計算移動平均
def moving_average(arr, window_size):
    return np.convolve(arr, np.ones(window_size)/window_size, mode='valid')

data_series = np.array

([1, 2, 3, 4, 5, 6, 7, 8, 9])
result = moving_average(data_series, 3)
print(result)

COVID-19 數據分析與可視化

import numpy as np
import os
import matplotlib.pyplot as plt
from numpy import ma

# 1. 設置文件路徑
filepath = os.getcwd()
filename = os.path.join(filepath, "who_covid_19_sit_rep_time_series.csv")

# 2. 讀取數據
dates = np.genfromtxt(filename, dtype=np.unicode_, delimiter=",", max_rows=1, usecols=range(4, 18), encoding="utf-8-sig")
locations = np.genfromtxt(filename, dtype=np.unicode_, delimiter=",", skip_header=6, usecols=(0, 1), encoding="utf-8-sig")
nbcases = np.genfromtxt(filename, dtype=np.int_, delimiter=",", skip_header=6, usecols=range(4, 18), encoding="utf-8-sig")

# 3. 清除“總計”行
totals_row = 35
locations = np.delete(locations, (totals_row), axis=0)
nbcases = np.delete(nbcases, (totals_row), axis=0)

# 4. 提取中國的累積病例數據
china_mask = ((locations[:, 1] == "China") & (locations[:, 0] != "Hong Kong") & (locations[:, 0] != "Taiwan") & (locations[:, 0] != "Macau") & (locations[:, 0] != "Unspecified*"))
nbcases_ma = ma.masked_values(nbcases, -1)
china_total = nbcases_ma[china_mask].sum(axis=0)

# 5. 數據擬合與預測
t = np.arange(len(china_total))
model = np.polynomial.Polynomial.fit(t[~china_total.mask], china_total[~china_total.mask], deg=3)

# 6. 繪製數據圖表
plt.plot(t, china_total, "o-", label="Mainland China Cases")
plt.plot(t, model(t), "--", label="Cubic Estimate")
plt.plot(7, model(7), "r*", label="7 Days After Start")
plt.xticks([0, 7, 13], dates[[0, 7, 13]])
plt.xlabel("Date")
plt.ylabel("Cumulative Cases")
plt.title("COVID-19 Cumulative Cases in Mainland China")
plt.legend()
plt.grid(True)
plt.show()