甲居工作室

1. NumPy 套件 (入門)

日期:2024/04/14

1. NumPy 套件 (入門)

Python 在處理資料數據領域非常流行,有許多強大的套件和工具可供使用。
以下是 Python 資料科學中常用的一些主要庫和工具:

  • NumPy: Python語言的一個擴充程式庫。支援高階大規模的多維陣列與矩陣運算,此外也針對陣列運算提供大量的數學函式函式庫。NumPy 在底層是 C 語言在計算上會更加快素。

  • Pandas: Pandas 是用於資料操作和分析的重要庫。它提供了高性能、易於使用的資料結構(如 DataFrame 和 Series),以及各種資料操作功能,包括資料索引、過濾、合併、重塑和分組等。也有人稱它為 Python 界的 Excel。

學會資料科學資料科學家、資料分析師 、資料工程師都是可能的出路。

本章節將採用 Anaconda 及 Jupyter notebook 請各位先行安裝。
Anaconda 預設把大部分資料科學需要的工具及套件皆安裝好,不用額外安裝設定。

1.1 NumPy

NumPy 是以連續存儲的數據塊,並且它們使用固定大小的數據類型,這使得 NumPy 能夠以高效的方式進行數組操作和數學計算。此外,NumPy 使用了稱為通用函數(ufuncs)的機制,這使得它能夠對所有元素同時進行運算,而無需逐一計算。

由於這些原因,使用 NumPy 庫進行數據處理和科學計算通常比純 Python 代碼更快。特別是當處理大型數據集時,NumPy 的性能優勢更加顯著。因此,許多數據科學和機器學習項目都會使用 NumPy 來提高計算效率。

我們使用下程式做個小實驗

  1. import numpy as np
  2. import time
  3. num = 10000000
  4. my_array = np.arange(num) # NumPy 陣列,值:[0, num)
  5. my_list = list(range(num)) # Python 串列,值:[0, num)
  6. startTime = time.time()
  7. my_array2 = my_array * 2
  8. endTime = time.time()
  9. print('NumPy array multiplication time:', endTime - startTime)
  10. startTime = time.time()
  11. my_list2 = [x*2 for x in my_list]
  12. endTime = time.time()
  13. print('Python list comprehension time:', endTime - startTime)
  • NumPy array multiplication time: 0.013138055801391602
  • Python list comprehension time: 0.32367682456970215
    此例子兩者速度相差 25 倍左右!

Jupyter Notebook

  1. import numpy as np
  2. num = 10000000
  3. my_array = np.arange(num) # NumPy 陣列,值:[0, num)
  4. my_list = list(range(num)) # Python 串列,值:[0, num)
  5. %time my_array2 = my_array * 2
  6. %time my_list2 = [x*2 for x in my_list]
  • CPU times: user 3.72 ms, sys: 59.5 ms, total: 63.3 ms
  • Wall time: 63.4 ms
  • CPU times: user 290 ms, sys: 115 ms, total: 406 ms
  • Wall time: 406 ms

在 Jupyter Notebook 中,%time 是一個稱為魔法命令的功能之一,用於測試單個程式的執行時間。這個魔法命令可以用來評估程式的效率,幫助您優化程式。

  • CPU times::程式在 CPU 上所執行的時間
    • user:CPU 在執行程式的時間。
    • sys:CPU 花費在系統內核(kernel)指令上的時間,這個時間包括了 CPU 花費在系統調用、文件 IO 等系統操作上的時間。
  • Wall time: 程式執行所用的實際時間

導入 NumPy

依照慣例大家會將 numpy 改名為 np

  1. import numpy as np

創建 NumPy 數組

  1. # 創建一個一維陣列
  2. arr1d = np.array([1, 2, 3, 4, 5])
  3. print(arr1d)
  4. # 創建一個二維陣列
  5. arr2d = np.array([[1, 2, 3], [4, 5, 6]])
  6. print(arr2d)

[1 2 3 4 5]
[[1 2 3]
 [4 5 6]]

常用屬性和方法

arr2d以圖表呈現如下

123
456
  • ndim: 返回數組的維度。
  • shape: 返回數組的形狀(各維度的大小)。
  • dtype: 返回數組中元素的數據類型。
  • size: 返回數組中元素的總數。
  1. print("維度:", arr2d.ndim) # 維度: 2
  2. print("形狀:", arr2d.shape) # 形狀: (2, 3)
  3. print("數據類型:", arr2d.dtype) # 數據類型: int64
  4. print("元素總數:", arr2d.size) # 元素總數: 6

產生 ndarray

  • np.zeros(): 生成全部為 0 的數組。
  • np.ones(): 生成全部為 1 的數組。
  • np.arange(): 類似於 Python 內置的 range() 函數。
  • np.linspace(): 在指定的範圍內生成均勻間隔的數組。
  1. zeros_arr = np.zeros((2, 3)) # 生成一個 2x3 的全為 0 的數組
  2. print(zeros_arr)
  3. # [[0. 0. 0.]
  4. # [0. 0. 0.]]
  5. ones_arr = np.ones((3, 2)) # 生成一個 3x2 的全為 1 的數組
  6. print(ones_arr)
  7. # [[1. 1.]
  8. # [1. 1.]
  9. # [1. 1.]]
  10. range_arr = np.arange(1, 10, 2) # 生成一個從1到9,步長為2的數組
  11. print(range_arr)
  12. # [1 3 5 7 9]
  13. lin_arr = np.linspace(0, 1, 5) # 在0到1之間生成5個均勻分佈的數字
  14. print(lin_arr)
  15. # [0. 0.25 0.5 0.75 1. ]

新增、刪除和排序元素

  • np.append(arr, values, axis=None): 將內容添加陣列尾部。
    1. arr = np.array([2, 1, 5, 3, 7, 4, 6, 8])
    2. arr = np.append(arr, [7,8,9])
    3. print(arr)
    4. # [2 1 5 3 7 4 6 8 7 8 9]
    1. arr = np.array([[1,2,3],[4,5,6]])
    2. arr = np.append(arr, [[7,8,9]], axis=0)
    3. print(arr)
    4. # [[1 2 3]
    5. # [4 5 6]
    6. # [7 8 9]]
    1. arr = np.array([[1,2,3],[4,5,6]])
    2. arr = np.append(arr, [[7, 8, 9],[10, 11, 12]], axis=1)
    3. print(arr)
    4. # [[ 1 2 3 7 8 9]
    5. # [ 4 5 6 10 11 12]]
  • numpy.delete(arr, obj, axis=None): 刪除指定索引或切片的元素。
    1. arr = np.array([1, 2, 3, 4, 5])
    2. arr = np.delete(arr, 2) # 刪除索引為2的元素
    3. print(arr) # [1 2 4 5]
  • np.sort(): 將陣列內容從小到大排序,產生新的陣列。
    1. arr = np.array([2, 1, 5, 3, 7, 4, 6, 8])
    2. np.sort(arr)
    3. print(arr)
    4. # [1, 2, 3, 4, 5, 6, 7, 8]
  • np.concatenate(): 將兩個陣列組合。
    1. a = np.array([1, 2, 3, 4])
    2. b = np.array([5, 6, 7, 8])
    3. arr =np.concatenate((a, b))
    4. print(arr)
    5. # [1, 2, 3, 4, 5, 6, 7, 8]
    1. x = np.array([[1, 2], [3, 4]])
    2. y = np.array([[5, 6]])
    3. arr = np.concatenate((x, y), axis=0)
    4. print(arr)
    5. # [[1, 2],
    6. # [3, 4],
    7. # [5, 6]])

形狀變換

  • reshape():用於改變陣列的形狀,但它返回一個新的陣列,必須確保新形狀與原始陣列中的元素數量相同。
  1. # 創建一個一維陣列
  2. arr = np.array([1, 2, 3, 4, 5, 6])
  3. # 使用 reshape() 將其轉換為 2x3 的二維陣列
  4. arr_reshaped = arr.reshape(2, 3)
  5. print(arr)
  6. # [1 2 3 4 5 6]
  • resize():於改變陣列的形狀,但它會直接修改原始陣列。如果新形狀比原始陣列中的元素數量大,則會用 0 填充多出的部分;如果新形狀比原始陣列中的元素數量小,則會截斷陣列。
  1. # 創建一個一維陣列
  2. arr = np.array([1, 2, 3, 4, 5, 6])
  3. # 使用 resize() 將其改變形狀為 2x4 的二維陣列(修改原始陣列)
  4. arr.resize(2, 4)
  5. print(arr)
  6. # [[1 2 3 4]
  7. # [5 6 0 0]]
  • .T:矩陣轉置,將欄和列互換。
  1. # 建立一個矩陣
  2. matrix = np.array([[1, 2, 3],
  3. [4, 5, 6]])
  4. transposed_matrix = matrix.T
  5. print(transposed_matrix)
  6. # [[1 4]
  7. # [2 5]
  8. # [3 6]]

索引和切片

這邊與一般 python list 操作一致

  1. # 創建一個一維陣列
  2. arr = np.array([1, 2, 3, 4, 5])
  3. # 使用索引訪問單個元素
  4. print(arr[0]) # 1
  5. # 使用索引訪問多個元素
  6. print(arr[[3, 1, 0]]) # [4 2 1]
  7. # 使用負索引訪問最後一個元素
  8. print(arr[-1]) # 5
  9. # 使用切片訪問範圍內的元素(左閉右開區間)
  10. print(arr[1:3]) # [2 3]
  11. # 省略開始索引,從開頭訪問到索引2(不包括2)
  12. print(arr[:3]) # [1 2 3]
  13. # 省略結束索引,從索引1開始到結尾
  14. print(arr[1:]) # [2 3 4 5]
  15. # 使用負索引進行切片
  16. print(arr[:-1]) # [1 2 3 4]
  1. # 創建一個二維陣列
  2. arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
  3. # 使用索引訪問多個元素
  4. print(arr_2d[0, 0]) # 1
  5. # 使用索引訪問單個元素
  6. print(arr_2d[[2, 0]])
  7. # [[7 8 9]
  8. # [1 2 3]]
  9. # 使用切片訪問子陣列
  10. print(arr_2d[1:, :2])
  11. # [[4 5]
  12. # [7 8]]

數學運算

  1. # 創建兩個陣列
  2. arr1 = np.array([[1, 2], [3, 4]])
  3. arr2 = np.array([[5, 6], [7, 8]])
  • 基本的算術運算
  1. # 加法
  2. print(arr1 + arr2)
  3. # [[ 6 8]
  4. # [10 12]]
  5. # 減法
  6. print(arr1 - arr2)
  7. # [[-4 -4]
  8. # [-4 -4]]
  9. # 乘法(元素級別)
  10. print(arr1 * arr2)
  11. # [[ 5 12]
  12. # [21 32]]
  13. # 除法(元素級別)
  14. print(arr1 / arr2)
  15. # [[0.2 0.33333333]
  16. # [0.42857143 0.5 ]]
  • 統計運算
  1. # 求和
  2. print(np.sum(arr1)) # 10
  3. # 求每一行的和
  4. print(np.sum(arr1, axis=1)) # [3 7]
  5. # 求每一列的和
  6. print(np.sum(arr1, axis=0)) # [4 6]
  7. # 求平均值
  8. print(np.mean(arr1)) # 2.5
  9. # 求最大值
  10. print(np.max(arr1)) # 4
  11. # 求最小值
  12. print(np.min(arr1)) # 1

線性代數運算

  1. from numpy.linalg import inv
  2. arr1 = np.array([[1, 2], [3, 4]])
  3. arr2 = np.array([[5, 6], [7, 8]])
  4. # 矩陣乘法
  5. print(np.dot(arr1, arr2))
  6. # [[19 22]
  7. # [43 50]]
  8. # 行列式
  9. print(np.linalg.det(arr1)) # -2.0000000000000004
  10. # 反矩陣
  11. print(np.linalg.inv(arr1))
  12. # [[-2. 1. ]
  13. # [ 1.5 -0.5]]
  14. # 特徵值和特徵向量
  15. eigenvalues, eigenvectors = np.linalg.eig(arr1)
  16. print("特徵值:", eigenvalues)
  17. # 特徵值: [-0.37228132 5.37228132]
  18. print("特徵向量:", eigenvectors)
  19. # 特徵向量: [[-0.82456484 -0.41597356]
  20. # [ 0.56576746 -0.90937671]]

當然還有很多的用法本章節僅提及比較常用的。

延伸閱讀

2. Matplotlib套件 (視覺化資料)

NumPy 套件 (視覺化資料)

Read more

3. ngrok

ngrok 是一個方便、安全的工具,可以將本機區域網路連上外部網絡,無需對網路配置進行任何變更,並且有一個網址可供使用讓其他人直接連上該網址的服務或是內容。

Read more