NumPy

郭耀仁

我們的問題

  • 我想一次把這幾個距離從公里換算成英里
km_list = [3, 5, 10, 21, 42.195]
km_to_mile = 0.621371192

我們的問題(2)

  • Python 的 list 無法使用 element-wise 運算
  • 在不引用套件的情況下我們可以使用迴圈來處理
In [1]:
km_list = [3, 5, 10, 21, 42.195]
km_to_mile = 0.621371192
mile_list = []

for km in km_list:
    mile_list.append(km * km_to_mile)

print(mile_list)
[1.864113576, 3.10685596, 6.21371192, 13.048795032000001, 26.21875744644]

我們的問題(3)

  • 或者使用 map()lambda 函數 來處理
In [2]:
km_list = [3, 5, 10, 21, 42.195]
mile_list = list(map(lambda x: x * 0.621371192, km_list))
print(mile_list)
[1.864113576, 3.10685596, 6.21371192, 13.048795032000001, 26.21875744644]

我們的問題(4)

  • 這樣處理會不會覺得太麻煩呢?
  • R 語言使用者表示:

第一次使用 ndarray

In [3]:
import numpy # 引入 numpy 套件

km_list = [3, 5, 10, 21, 42.195]
km_array = numpy.array(km_list)
print(type(km_array))
km_to_mile = 0.621371192
mile_array = km_array * km_to_mile
print(mile_array)
<class 'numpy.ndarray'>
[  1.86411358   3.10685596   6.21371192  13.04879503  26.21875745]

第一次使用 ndarray(2)

  • 把套件名稱變成縮寫
In [4]:
import numpy as np # 引入 numpy 套件

km_list = [3, 5, 10, 21, 42.195]
km_array = np.array(km_list)
print(type(km_array))
km_to_mile = 0.621371192
mile_array = km_array * km_to_mile
print(mile_array)
<class 'numpy.ndarray'>
[  1.86411358   3.10685596   6.21371192  13.04879503  26.21875745]

練習計算 BMI

  • 請同學練習計算這五個人的 BMI
heights = [173, 168, 171, 189, 179]
weights = [65.4, 59.2, 63.6, 88.4, 68.7]

建立 ndarray 的方法

方法 描述
numpy.array() 基本的建立
numpy.arange() 類似 range()
numpy.linspace() 建立等距切分的陣列
numpy.ones() 建立都是 1 的陣列
numpy.zeros() 建立都是 0 的陣列
numpy.eye() 建立單位矩陣
numpy.random.rand() 建立符合均勻分布的陣列
numpy.random.randn() 建立符合常態分布的陣列
numpy.random.randint() 建立隨機整數的陣列

建立 ndarray 的方法(2)

  • numpy.arange()
  • 可以只提供 stop 輸入
In [5]:
import numpy as np

arr = np.arange(10)
print(arr)
arr = np.arange(1, 10)
print(arr)
arr = np.arange(1, 10, 2)
print(arr)
[0 1 2 3 4 5 6 7 8 9]
[1 2 3 4 5 6 7 8 9]
[1 3 5 7 9]

建立 ndarray 的方法(3)

  • numpy.linspace()
  • 輸入起始值、停止值與個數
In [6]:
import numpy as np

arr = np.linspace(1, 10, 10)
print(arr)
[  1.   2.   3.   4.   5.   6.   7.   8.   9.  10.]

建立 ndarray 的方法(4)

  • numpy.ones()
  • 建立都是 1 的陣列
  • 輸入一個數字建立一維的陣列
  • 輸入 tuple 建立多維的陣列
In [7]:
import numpy as np

arr = np.ones(5)
print(arr)
print("\n")
arr = np.ones((2, 3))
print(arr)
print("\n")
arr = np.ones((2, 3, 2))
print(arr)
[ 1.  1.  1.  1.  1.]


[[ 1.  1.  1.]
 [ 1.  1.  1.]]


[[[ 1.  1.]
  [ 1.  1.]
  [ 1.  1.]]

 [[ 1.  1.]
  [ 1.  1.]
  [ 1.  1.]]]

建立 ndarray 的方法(5)

  • numpy.zeros()
  • 建立都是 0 的陣列
  • 輸入一個數字建立一維的陣列
  • 輸入 tuple 建立多維的陣列
  • 可以比照 numpy.ones() 自行試試

建立 ndarray 的方法(6)

  • numpy.eye()
  • 建立單位矩陣
  • 輸入 n 就會得到 nxn 的單位矩陣
In [8]:
import numpy as np

arr = np.eye(3) # 3x3 的單位矩陣
print(arr)
print("\n")
arr = np.eye(5) # 5x5 的單位矩陣
print(arr)
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]]


[[ 1.  0.  0.  0.  0.]
 [ 0.  1.  0.  0.  0.]
 [ 0.  0.  1.  0.  0.]
 [ 0.  0.  0.  1.  0.]
 [ 0.  0.  0.  0.  1.]]

建立 ndarray 的方法(7)

  • numpy.diag()
  • 建立對角矩陣
In [9]:
import numpy as np

arr = np.diag([1, 2, 3])
print(arr)
[[1 0 0]
 [0 2 0]
 [0 0 3]]

建立 ndarray 的方法(8)

  • numpy.random.rand()
  • 建立符合 0~1 均勻分布的陣列
In [10]:
import numpy as np
import matplotlib.pyplot as plt

arr = np.random.rand(1000)
print(arr[:6])
plt.hist(arr)
plt.show()
[ 0.05475295  0.50316867  0.50825385  0.39994612  0.6010682   0.63313496]

建立 ndarray 的方法(9)

  • numpy.random.randn()
  • 建立符合平均數 0,標準差 1 的常態分佈陣列
In [11]:
import numpy as np
import matplotlib.pyplot as plt

arr = np.random.randn(1000)
print(arr[:6])
plt.hist(arr)
plt.show()
[ 0.71550618  0.97164187  0.06570055 -0.22835471 -0.0327245  -0.63464055]

建立 ndarray 的方法(10)

  • numpy.random.randint(low, high, size)
  • 建立介於 low,high 之間的整數陣列
In [12]:
import numpy as np

arr = np.random.randint(0, 100, size = 10)
print(arr)
arr = np.random.randint(0, 100, size = (2, 5))
print(arr)
[89 87 27  7 31 13 79 97 55 47]
[[14 67 65 70 17]
 [73 68  7 43 10]]

建立 ndarray 的方法(11)

  • 練習在 [-2, 2] 之間均分出 50 個數字的數列
  • 練習建立一個 (5, 5) 的單位矩陣
  • 練習在隨機產出 5 個介於 100 與 200 之間整數的數列

資料類型

  • 使用 dtype 屬性來指定或檢視
  • 整數 int
    • int8
    • int16
    • int32
    • int64(預設)
In [13]:
import numpy as np

arr = np.ones(5, dtype = 'int')
print(arr)
print(arr.dtype) # 預設是 64 位元的整數
arr = np.ones(5, dtype = 'int8') # 可以改成 8 位元的整數
print(arr)
print(arr.dtype)
[1 1 1 1 1]
int64
[1 1 1 1 1]
int8

資料類型(2)

  • 使用 dtype 屬性來指定或檢視
  • 浮點數 float
    • float16
    • float32
    • float64(預設)
    • float128
In [14]:
import numpy as np

arr = np.ones(5)
print(arr)
print(arr.dtype) # 預設是 64 位元的浮點數
arr = np.ones(5, dtype = 'float16') # 可以改成 16 位元的浮點數
print(arr)
print(arr.dtype)
[ 1.  1.  1.  1.  1.]
float64
[ 1.  1.  1.  1.  1.]
float16

資料類型(3)

  • 使用 dtype 屬性來指定或檢視
  • 複數
    • complex64
    • complex128(預設)
    • complex256
In [15]:
import numpy as np

arr = np.ones(5, dtype = 'complex')
print(arr)
print(arr.dtype) # 預設是 128 位元的複數
arr = np.ones(5, dtype = 'complex64') # 可以改成 64 位元的複數
print(arr)
print(arr.dtype)
[ 1.+0.j  1.+0.j  1.+0.j  1.+0.j  1.+0.j]
complex128
[ 1.+0.j  1.+0.j  1.+0.j  1.+0.j  1.+0.j]
complex64

資料類型(4)

  • 使用 dtype 屬性來指定或檢視
  • 布林
    • bool
In [16]:
import numpy as np

arr = np.array((True, False))
print(arr)
print(arr.dtype)
[ True False]
bool

資料類型(5)

  • 使用 dtype 屬性來指定或檢視
  • 文字
    • string_(一個字元以一個 byte 儲存)
    • unicode_(預設)
In [17]:
import numpy as np

arr = np.array(("1", "中文", "English")) # 預設為 unicode
print(arr)
print(arr.dtype)
arr = np.array(("1", "English"), dtype = 'string_') # 中文一個字元要以兩個 byte 儲存,所以不能儲存為 string_
print(arr)
print(arr.dtype)
['1' '中文' 'English']
<U7
[b'1' b'English']
|S7

資料類型(6)

  • 除了在建立的時候使用 dtype 指定資料類型
  • 也可以使用 astype() 方法轉換資料類型
In [18]:
import numpy as np

arr = np.ones(5)
print(arr.dtype)
arr = arr.astype('str')
print(arr)
print(arr.dtype)
float64
['1.0' '1.0' '1.0' '1.0' '1.0']
<U32

ndarray 只能容許一個變數類型

  • 同時儲存有數值,布林值,會被自動轉換為數值
  • 同時儲存有數值,布林值與文字,會被自動轉換為文字
In [19]:
import numpy as np

arr = np.array([1, True])
print(arr.dtype)
arr = np.array([1, True, "one"])
print(arr.dtype)
int64
<U21

選擇 ndarray 的元素

  • 用索引值選擇
In [20]:
import numpy as np

arr = np.arange(5)
print(arr)
print(arr[0])
print(arr[1])
print(arr[-1])
print(arr[[0, 2, 4]]) # To the rescue!
[0 1 2 3 4]
0
1
4
[0 2 4]

選擇 ndarray 的元素(2)

  • 用索引值選擇
  • slicing arr[startIndex: endIndex: stepValue]
In [21]:
import numpy as np

arr = np.arange(5)
print(arr[:3])
print(arr[3:])
print(arr[0:5:2])
[0 1 2]
[3 4]
[0 2 4]

選擇 ndarray 的元素(3)

  • 多維度的 ndarray 可以用 tuple 方式選擇
In [22]:
import numpy as np

arr = np.array(range(10)).reshape(2, 5)
print(arr)
print(arr[1][0])
print(arr[1, 0])
print("\n")
arr = np.array(range(20)).reshape(2, 2, 5)
print(arr)
print(arr[0][1][0])
print(arr[0, 1, 0])
[[0 1 2 3 4]
 [5 6 7 8 9]]
5
5


[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]]

 [[10 11 12 13 14]
  [15 16 17 18 19]]]
5
5

選擇 ndarray 的元素(4)

  • 用布林選擇
In [23]:
import numpy as np

arr = np.array(range(10))
num_filter = arr < 5
print(num_filter)
print(arr[num_filter])
[ True  True  True  True  True False False False False False]
[0 1 2 3 4]

選擇 ndarray 的元素(5)

  • 練習選出未滿 20 與超過 30 的元素
age = [19, 21, 20, 19, 21, 17, 30, 36, 90]

選擇 ndarray 的元素(6)

  • 練習從五人中選出 BMI > 21 的元素
heights = [173, 168, 171, 189, 179]
weights = [65.4, 59.2, 63.6, 88.4, 68.7]

選擇 ndarray 的元素(7)

  • 練習使用布林選出 Matthew Perry 與 Lisa Kudrow
friends_stars = ["Jennifer Aniston", "Courteney Cox", "Lisa Kudrow",
"Matt LeBlanc", "Matthew Perry", "David Schwimmer"]

選擇 ndarray 的元素(8)

  • 假如希望判斷兩個 ndarray 是否相同,可以使用 np.array_equal()
In [24]:
import numpy as np

friends_stars = ["Jennifer Aniston", "Courteney Cox", "Lisa Kudrow",
"Matt LeBlanc", "Matthew Perry", "David Schwimmer"]
friends_arr_1 = np.array(friends_stars)
friends_arr_2 = np.array(friends_stars[:5])
print(np.array_equal(friends_arr_1, friends_arr_2))
friends_arr_2 = np.array(friends_stars[:])
print(np.array_equal(friends_arr_1, friends_arr_2))
False
True

ndarray 的運算

  • 一如我們一開始所說的,是 element-wise 的運算
In [25]:
import numpy as np

arr = np.arange(10)
print(arr + 8)
print(arr - 7)
print(arr * 8)
print(arr / 7)
print(arr**2)
print(arr % 7)
[ 8  9 10 11 12 13 14 15 16 17]
[-7 -6 -5 -4 -3 -2 -1  0  1  2]
[ 0  8 16 24 32 40 48 56 64 72]
[ 0.          0.14285714  0.28571429  0.42857143  0.57142857  0.71428571
  0.85714286  1.          1.14285714  1.28571429]
[ 0  1  4  9 16 25 36 49 64 81]
[0 1 2 3 4 5 6 0 1 2]

ndarray 的運算(2)

  • 一維的 ndarray 與二維的 ndarray 也都符合 element-wise 運算
In [26]:
import numpy as np

arr_1 = np.arange(10)
arr_2 = np.arange(11, 21)
print(arr_1)
print(arr_2)
print("\n")
print(arr_1 * arr_2)
[0 1 2 3 4 5 6 7 8 9]
[11 12 13 14 15 16 17 18 19 20]


[  0  12  26  42  60  80 102 126 152 180]
In [27]:
import numpy as np

arr_1 = np.arange(10).reshape(2, 5)
arr_2 = np.arange(11, 21).reshape(2, 5)
print(arr_1)
print(arr_2)
print("\n")
print(arr_1 * arr_2)
[[0 1 2 3 4]
 [5 6 7 8 9]]
[[11 12 13 14 15]
 [16 17 18 19 20]]


[[  0  12  26  42  60]
 [ 80 102 126 152 180]]

ndarray 的運算(3)

  • 二維的 ndarray 可以進行矩陣的內積運算
  • 使用 .dot() 方法或 np.dot()
In [28]:
import numpy as np

arr_1 = np.arange(10).reshape(2, 5)
arr_2 = np.arange(10).reshape(5, 2)
print(arr_1.dot(arr_2))
print("\n")
print(np.dot(arr_1, arr_2))
[[ 60  70]
 [160 195]]


[[ 60  70]
 [160 195]]

ndarray 的運算(4)

  • 練習計算 $u^Tv$
$$u = \begin{bmatrix} 4 \\ -4 \\ -3 \end{bmatrix}$$$$v = \begin{bmatrix} 4 \\ 2 \\ 4 \end{bmatrix}$$

ndarray 的運算(5)

  • 練習計算 $AI$ 與 $IA$
$$A = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{bmatrix}$$$$I = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{bmatrix}$$

ndarray 的運算(6)

  • 練習計算 $AB$ 與 $BA$
$$A = \begin{bmatrix} 1 & 2 \\ 4 & 5 \\ \end{bmatrix}$$$$B = \begin{bmatrix} 4 & 3 \\ 2 & 1 \\ \end{bmatrix}$$

常用屬性與方法

  • 元素個數:.size
  • 外觀:.shape
  • 維度:.ndim
In [29]:
import numpy as np

arr = np.array(range(10))
print(arr.size)
print(arr.shape)
print(arr.ndim)
print("\n")
arr = np.array(range(10)).reshape(2, 5)
print(arr.size)
print(arr.shape)
print(arr.ndim)
10
(10,)
1


10
(2, 5)
2

常用屬性與方法(2)

  • 變形:.reshape(m, n)
  • 轉置:.T
  • 攤平:.ravel()
  • 依條件取代:.where()
In [30]:
import numpy as np

arr = np.arange(10)
print(arr.shape)
arr = arr.reshape(2, 5)
print(arr.shape)
print("\n")
print(arr)
print(arr.T)
print("\n")
arr = arr.ravel()
print(arr)
print(arr.shape)
print("\n")
print(np.where(arr < 5, 99, arr))
(10,)
(2, 5)


[[0 1 2 3 4]
 [5 6 7 8 9]]
[[0 5]
 [1 6]
 [2 7]
 [3 8]
 [4 9]]


[0 1 2 3 4 5 6 7 8 9]
(10,)


[99 99 99 99 99  5  6  7  8  9]

常用屬性與方法(3)

  • 相乘:.prod()
  • 加總:.sum()
  • 平均:.mean()
In [31]:
import numpy as np

arr = np.arange(1, 11).reshape(2, 5)
print(arr)
print(arr.prod())
print(arr.prod(axis = 0)) # column
print(arr.prod(axis = 1)) # row
print("\n")
print(arr.sum())
print(arr.sum(axis = 0)) # column
print(arr.sum(axis = 1)) # row
print("\n")
print(arr.mean())
print(arr.mean(axis = 0)) # column
print(arr.mean(axis = 1)) # row
[[ 1  2  3  4  5]
 [ 6  7  8  9 10]]
3628800
[ 6 14 24 36 50]
[  120 30240]


55
[ 7  9 11 13 15]
[15 40]


5.5
[ 3.5  4.5  5.5  6.5  7.5]
[ 3.  8.]

常用屬性與方法(4)

  • 找出 unique values:np.unique()
  • 檢查每個元素是否包含於:np.in1d()
  • 連結 ndarrays:np.concatenate()
In [32]:
import numpy as np

arr = np.array(["female", "female", "female", "male", "male"])
print(np.unique(arr))
arr = np.concatenate([np.ones(5), np.zeros(5)])
print(np.unique(arr))
arr_1 = np.arange(10)
arr_2 = np.arange(5)
print(np.in1d(arr_1, arr_2))
['female' 'male']
[ 0.  1.]
[ True  True  True  True  True False False False False False]

常用屬性與方法(5)

  • np.all() 判斷是否所有元素都滿足判斷條件
  • np.any() 判斷是否有任何元素滿足判斷條件
  • np.sort() 排序
In [33]:
import numpy as np

arr = np.ones(5)
print(np.all(arr == 1))
print(np.any(arr != 1))
print("\n")
arr = np.random.randint(0, 100, size = (2, 5))
print(arr)
print(np.sort(arr, axis = 0)) # by column
print(np.sort(arr, axis = 1)) # by row
True
False


[[13 93 71  5 12]
 [33 85  7  4 36]]
[[13 85  7  4 12]
 [33 93 71  5 36]]
[[ 5 12 13 71 93]
 [ 4  7 33 36 85]]

隨堂練習

  • 建立一個外觀為 (9, 9) 的 ndarray
  • 填入九九乘法表

作業

$$SD = \sqrt{\frac{1}{N-1}\sum_{i=1}^{N}(x_i - \bar{x})^2}$$
my_sd(range(10))
## 3.0276503540974917