introduction
對一份大型的數據來說,是由多筆樣本所構成的
- 列(column)通常為樣本的指標或是特徵(feature)
- 行(row)則代表一筆含有多項特徵的資料集合
綜合以上,以矩陣形式表示資料會更為直觀
- 計算方便
- 計算效率高
numpy庫可用於矩陣計算
導入numpy Library
1 | import numpy as np |
產生陣列(array)
從列表(list)產生陣列
將列表類型轉換為numpy.ndarray
以創建陣列1
2
3data = [1,2,3,4,5]
arr = np.array(data)
arr
亦可直接填入list1
2arr = np.array([1,2,3,4,5])
arr
result1
array([1, 2, 3, 4, 5])
查看類型1
type(arr)
result1
numpy.ndarray
- 類型為
numpy.ndarray
arrange產生陣列
產生int陣列1
np.arange(10)
result1
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
產生float陣列1
np.arange(10.0)
result1
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
步進產生陣列
example 1:1
np.arange(10,30,5)
- 從10開始,每+5產生值到30停止,但不包含30
result1
array([10, 15, 20, 25])
example 2:1
np.aarange(0,2,0.3)
result1
array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])
linspace產生1D陣列
得到特定範圍內指定個數元素的陣列1
2from numpy import pi
np.linspace(0,2*pi,6)
- 產生從0開始到2pi(包含2pi),分成6等份的一維陣列
- 若未指定分成多少等份,預設為50等份,即(start,inclusive stop,50)
result1
2array([0. , 1.25663706, 2.51327412, 3.76991118, 5.02654825,
6.28318531])
logspace產生1D陣列
得到10的start次方到10的inclusive stop次方的陣列1
np.logspace(0, 3, 8) # 10^0 to 10^3 (inclusive) with 8 points
result1
2array([ 1. , 2.6826958 , 7.19685673, 19.30697729,
51.79474679, 138.94954944, 372.75937203, 1000. ])
創建二維(2D)矩陣
搭配range()
創建2D array1
2
3data2 = [range(1, 5), range(5, 9)] # list of lists
arr2 = np.array(data2) # 2d array
arr2
直接填入嵌套的list創建1
2arr2 = np.array([[1,2,3,4],[5,6,7,8]])
arr2
result1
2array([[1, 2, 3, 4],
[5, 6, 7, 8]])
將矩陣轉為列表類型
- 將
numpy.ndrray
轉為list
result1
2a = arr2.tolist() # convert array back to list
type(a)1
list
陣列檢查
查看矩陣存放的類型(dtype)
在創建矩陣時不像list,各元素之間可為不同類型,
矩陣中的元素必須為同一類型
1 | arr_test = np.array([1,2,3,4,5]) |
result1
dtype('int64')
只要其中一個元素類型不一樣,
為了滿足其中一個元素的類型,會將其他元素轉換為更泛用的類型
example 1:1
2arr_test = np.array([1,2,3,4,5.0])
arr_test.dtype
result1
dtype('float64')
example 2:1
2arr_test = np.array([1,2,3,'4',5.0])
arr_test.dtype
result1
dtype('<\U21')
查看矩陣的結構(shape)
常用於debug
2D array
1 | arr2.shape |
- shape返回一個tuple,為(row, column)形式
result1
(2, 4)
1D array
1 | arr.shape |
result1
(5,)
查看矩陣維度(ndim)
1 | print(arr.ndim) |
result1
21
2
查看矩陣的元素總數(size)
1 | print(arr.size) |
result1
25
8
矩陣的選取(切片slicing)
透過索引(index)選取特定範圍內的陣列
語法
與list切片的方法一樣,只是不同維度需用逗號(,
)隔開start (= 0) : stop (= last) :step (= 1)
取特定行
example 1:1
2arr = np.array([range(1,4),range(4,7),range(7,10)])
arr[0, :]
result1
array([1, 2, 3])
example 2:1
arr[0:2, :]
result1
2array([[1, 2, 3],
[4, 5, 6]])
取特定列
example 1:1
arr[:, 0]
result1
array([1, 4, 7])
- 單取一列值時,返回為1d-array
example 2:1
arr[:, 1:]
result1
2
3array([[2, 3],
[5, 6],
[8, 9]])
取特定範圍
1 | arr[0:2, 0:2] |
result1
2array([[1, 2],
[4, 5]])
取特定值
1 | val = arr[2:2] |
- 其等同於
arr[2][2]
,先取行在取列
result1
9
修改特定值
1 | arr[1:1] = 100 |
- 其等同於
arr[1][1] = 100
,先取行在取列
result1
2
3array([[ 1, 2, 3],
[ 4, 100, 6],
[ 7, 8, 9]])
矩陣的邏輯運算
普通邏輯運算
進行普通邏輯運算時會對陣列中的每一個元素都進行計算,並返回一個bool類型的陣列(不需使用for循環進行運算)
example 1:1
2matrix = np.array([range(1,4),range(4,7),range(7,10)])
matrix > 5
result1
2
3array([[False, False, False],
[False, False, True],
[ True, True, True]])
example 2:1
matrix == 9
result1
2
3array([[False, False, False],
[False, False, False],
[False, False, True]])
返回為True的值
example 1:1
2
3arr_bool = np.array([False,True,False])
arr_int = np.array([1,2,3])
arr_int[arr_bool] # 將arr_bool當作index,傳入arr_int中計算
result1
array([2])
example 2:1
2
3
4matrix = np.array([[5,15,20],[20,25,30],[35,40,45]])
second_col_25 = matrix[1, :] == 25
print(second_col_25)
matrix[second_col_25] # 從matrix中查找符合此bool矩陣的row之值
result1
2
3[False True False]
array([[20, 25, 30]])
- 結果為
matrix[1,:]
與或運算
example 1:1
2matrix = np.array([[5,15,20],[20,25,30],[35,40,45]])
(matrix > 25) & (matrix < 50)
- 務必加上括號
()
result1
2
3array([[False, False, False],
[False, False, True],
[ True, True, True]])
example 2:1
(matrix > 25) | (matrix < 10)
result1
2
3array([[ True, False, False],
[False, False, True],
[ True, True, True]])
判斷有無非數字值(isnan)
1 | a = np.array([1,2,3,4,5,np.nan]) |
result1
array([False, False, False, False, False, True])
矩陣的運算
減法
1 | a = np.array([10,20,30,40,50]) |
result1
2
3[10 19 28 37 46]
[-1 0 1 2 3]
- 對應位置相減
求次方
1 | b = np.arrane(5) |
result1
array([ 0, 1, 4, 9, 16])
矩陣乘法
使用*則對應位置元素相乘1
2
3
4
5A = np.array([[1,1],
[0,1]])
B = np.array([[2,0],
[3,4]])
A*B
result1
2array([[2, 0],
[0, 4]])
使用dot求積1
2print(A.dot(B))
print(np.dot(A,B))
- 兩個效果是一樣的
result1
2
3
4
5[[5 4]
[3 4]]
[[5 4]
[3 4]]
變換矩陣存儲的類型(astype)
透過astype()將矩陣原類型,轉換為其他類型1
2
3
4
5str_matrix = np.array([['1','2','3']])
print(str_matrix.dtype)
int_matrix = str_matrix.astype(int)
print(int_matrix.dtype)
int_matrix
result1
2
3
4<\U1
int64
array([[1, 2, 3]])
矩陣的內置屬性
求最小值(min
)
1 | IntVector = np.array([1,2,3,4,5,6,7,8,9]) |
result1
1
求最大值(max
)
1 | IntVector = np.array([1,2,3,4,5,6,7,8,9]) |
result1
9
比較同座標值之大小(maximum,minimum)
1 | nums = np.arange(5) |
- maximum返回較大的值之矩陣,minimum返回較小值之矩陣
result1
array([1, 1, 3, 3, 5])
求極值(最大值,最小值)的索引(argmax
,argmin
)
1 | a = np.floor(10*np.random.random((3,4))) |
- axis=1為求每一行(row)最大值的索引,axis=0為求每一列(column),不加則是全部運算取一返回值
result1
2
3
4
5[[8. 8. 8. 4.]
[5. 2. 7. 3.]
[8. 9. 5. 6.]]
array([0, 2, 1])
求和(sum)
example 1:1
2IntMatrix = np.array([range(1,4),range(4,7),range(7,10)])
IntMatrix.sum(axis = 0)
- axis = 0 代表 求每一列(column)之總和,不加怎是全部元素求和
result1
array([12, 15, 18])
example 2:1
2IntMatrix = np.array([range(1,4),range(4,7),range(7,10)])
IntMatrix.sum(axis = 1)
- axis = 1 代表 求每一行(row)之總和
result1
array([ 6, 15, 24])
求集合(unique)
陣列中不會有重複的元素,相當於set()1
2Intmatrix = np.array([1,2,1,2,3,3,4,5,6,6,6,7,7,8,8])
np.unique(Intmatrix)
result1
array([1, 2, 3, 4, 5, 6, 7, 8])
向量(vector)與矩陣(matrix)的轉換
使用reshape將向量轉為矩陣
1 | matrix = np.arange(15) |
- 在reshape過程中,元素數量為一固定值,因此確定了3行必定為5列,
亦可寫成reshape(3,-1)
result1
2
3array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
shape賦值將向量轉為矩陣
1 | matrix = np.arange(15) |
result1
2
3array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
將矩陣拉成一向量
ravel
1 | matrix =np.array([[5, 7, 1, 3], |
result1
array([5, 7, 1, 3, 7, 8, 9, 4, 8, 8, 7, 0])
- ravel產生的陣列仍指向原矩陣,操作其值,原矩陣亦會發生改變
flatten
1 | matrix =np.array([[5, 7, 1, 3], |
result1
array([5, 7, 1, 3, 7, 8, 9, 4, 8, 8, 7, 0])
- flatten產生的陣列為一復本,操作其值,原矩陣不會發生改變
使用np.newaxis
將平行向量轉換為垂直向量1
2
3a = np.array([0, 1, 2, 3])
a_col = a[:, np.newaxis] # same as a_col = a[:, None]
a_col
result1
2
3
4array([[0],
[1],
[2],
[3]])
初始化矩陣
zeros
初始化一個元素皆為0的矩陣(參數為一tuple)1
np.zeros((3, 4),dtype=np.int32)
- dtype可決定存放的類型(亦可不設置,默認為float64)
result1
2
3array([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]], dtype=int32)
ones
初始化一個元素皆為1的矩陣(參數為一tuple)1
np.ones((2,3,4),dtype=np.int8)
result1
2
3
4
5
6
7array([[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]],
[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]]], dtype=int8)
random
初始化一個元素為0至1之間隨機浮點數的矩陣(參數為一tuple)1
np.random.random((2,3))
result1
2array([[0.78248299, 0.52270045, 0.0945345 ],
[0.30580916, 0.31472853, 0.34269623]])
numpy開啟格式化文件(genfromtxt)
- 使用
numpy.genfromtxt()
讀取格式化的數據1
np.genfromtxt("student_score.txt",delimiter=',',dtype=str)
- 參數1:指定文件路徑
- delimiter : 指定分隔符(文件中元素之間的分隔符)
- dtype : 以何種類型將文件讀入(大部分用
str
方式讀入再去轉換成其他類型)
1 | array([['Amy', '1001', '18', '95.0'], |
- 讀入為一矩陣
1 | stu_info = np.genfromtxt("student_score.txt",delimiter=',',dtype=str) |
1 | numpy.ndarray |
- 為numpy.ndarray類型
其他操作
指數函數(exp)
1 | B = np.arange(3) |
result1
array([1. , 2.71828183, 7.3890561 ])
開根號(sqrt)
1 | np.sqrt(B) |
result1
array([0. , 1. , 1.41421356])
無條件捨去取整(floor)
將矩陣內元素的小數位皆丟棄,只留下整數位的數1
2
3A = np.random.random((3,4))*10
print(A)
print(np.floor(A))
result1
2
3
4
5
6
7[[4.79808472 2.44399243 5.548923 6.92783862]
[2.83681077 4.38694273 8.19855738 4.97988545]
[1.04608979 1.0399803 2.22577406 7.76268637]]
[[4. 2. 5. 6.]
[2. 4. 8. 4.]
[1. 1. 2. 7.]]
無條件進位取整(ceil)
將矩陣內元素的小數位皆進位,只留下整數位的數1
2
3A = np.random.random((3,4))*10
print(A)
print(np.ceil(A))
result1
2
3
4
5
6
7[[1.9360702 1.05170707 5.41654963 7.97196499]
[8.12826589 7.20266718 8.15762529 5.84988628]
[4.32137618 9.08694857 1.05489433 6.37825292]]
[[ 2. 2. 6. 8.]
[ 9. 8. 9. 6.]
[ 5. 10. 2. 7.]]
轉置矩陣(T)
1 | matrix =np.array([[9., 3., 8., 0., 6., 9.], |
result1
2
3
4
5
6array([[9., 4.],
[3., 1.],
[8., 4.],
[0., 3.],
[6., 8.],
[9., 3.]])
擴展矩陣(tile)
定義一個矩陣,以此矩陣為單元擴展成自己需要的維度1
2
3a = np.arange(1,3)
b = np.tile(a,(2,2))
b
result1
2array([[1, 2, 1, 2],
[1, 2, 1, 2]])
矩陣疊加
平行疊加(hstack)
增加特徵數1
2
3
4
5a = np.floor(10*np.random.random((2,2)))
b = np.floor(10*np.random.random((2,2)))
print(a)
print(b)
print(np.hstack((a,b)))
result1
2
3
4
5
6
7
8[[1. 3.]
[8. 6.]]
[[1. 4.]
[3. 7.]]
[[1. 3. 1. 4.]
[8. 6. 3. 7.]]
垂直疊加(vstack)
增加樣本數1
2
3
4
5a = np.floor(10*np.random.random((2,2)))
b = np.floor(10*np.random.random((2,2)))
print(a)
print(b)
print(np.vstack((a,b)))
result1
2
3
4
5
6
7
8
9
10[[2. 1.]
[8. 0.]]
[[5. 5.]
[3. 7.]]
[[2. 1.]
[8. 0.]
[5. 5.]
[3. 7.]]
多維疊加(stack)
- 兩個一維的矩陣疊加為二維矩陣
- 兩個二維的矩陣疊加為三維矩陣
1
2
3
4
5a = np.floor(10*np.random.random((2,2)))
b = np.floor(10*np.random.random((2,2)))
print(a)
print(b)
np.stack((a,b))
result1
2
3
4
5
6
7
8
9
10
11[[7. 7.]
[3. 3.]]
[[4. 4.]
[4. 9.]]
[[[7. 7.]
[3. 3.]]
[[4. 4.]
[4. 9.]]]
矩陣切分(split)
平行切分(np.hsplit)
第二參數為一整數1
2
3a = np.floor(10*np.random.random((2,12)))
print(a)
print(np.hsplit(a,3))
- 將a平行切分成3等份
result1
2
3
4
5
6
7
8
9[[1. 5. 8. 1. 3. 1. 9. 4. 3. 8. 8. 9.]
[2. 8. 9. 7. 1. 9. 6. 6. 9. 1. 1. 7.]]
[array([[1., 5., 8., 1.],
[2., 8., 9., 7.]]),
array([[3., 1., 9., 4.],
[1., 9., 6., 6.]]),
array([[3., 8., 8., 9.],
[9., 1., 1., 7.]])]
指定平行切分
第二參數為一tuple1
2
3a = np.floor(10*np.random.random((2,12)))
print(a)
print(np.hsplit(a,(3,4,6)))
- 將陣列於index第3 4 6的位置進行拆分
1 | [[3. 4. 8. 7. 1. 7. 3. 8. 5. 7. 1. 3.] |
垂直切分(np.vsplit)
1 | b = np.floor(10*np.random.random((2,2))) |
result1
2
3
4
5[[1. 6.]
[5. 9.]]
[array([[1., 6.]]),
array([[5., 9.]])]
指定垂直切分
1 | b = np.floor(10*np.random.random((3,2))) |
result1
2
3
4
5
6
7[[5. 8.]
[9. 9.]
[5. 1.]]
[array([[5., 8.]]),
array([[9., 9.],
[5., 1.]])]
矩陣間的拷貝
Situation 1 - 非拷貝
A與B指向同一矩陣(非拷貝)
只是變量名不同,但指向的為同一個矩陣1
2
3
4
5
6
7
8
9
10a = np.arange(12)
print(a.shape)
b = a
print(b is a)
b.shape = (3,-1)
print(a.shape)
print(id(a))
print(id(b))
result1
2
3
4
5(12,)
True
(3, 4)
4395559392
4395559392
- 對A操作等同於對B操作
Situation 2 - 淺拷貝(view)
A與B指向不同矩陣,
但矩陣中存放的值為共用的1
2
3
4
5
6
7
8
9
10
11
12
13a =np.arange(12)
print(a.shape)
b = a.view()
print(b is a)
b.shape = (3,-1)
print(a.shape)
print(id(a))
print(id(b))
a[0] = 10000
print(a)
print(b)
result1
2
3
4
5
6
7
8
9(12,)
False
(12,)
4395385280
4395385120
[10000 1 2 3 4 5 6 7 8 9 10 11]
[[10000 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
- a.view()創建一個a矩陣的淺拷貝
a 與 b 為不同矩陣
- 改變b矩陣的shape,a並無變化
- a 與 b 指向不同的內存地址
a 與 b 矩陣中的值是共用的
- 操作 a 矩陣的值 b 矩陣仍會改變
Situation 3 - 深拷貝
A與B指向不同矩陣,
矩陣中存放的值也互不相干1
2
3
4
5
6
7
8
9
10
11
12
13a =np.arange(12)
print(a.shape)
b = a.copy()
print(b is a)
b.shape = (3,-1)
print(a.shape)
print(id(a))
print(id(b))
a[0] = 10000
print(a)
print(b)
result1
2
3
4
5
6
7
8
9(12,)
False
(12,)
4395558752
4395560832
[10000 1 2 3 4 5 6 7 8 9 10 11]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
- a.copy()創建一個a矩陣的深拷貝
- a 與 b 矩陣中的值互不相干
矩陣排序
np.sort排序
返回一個排序好的矩陣1
2
3
4matrix =np.array([[9., 3., 8., 0., 6., 9.],
[4., 1., 4., 3., 8., 3.]])
a = np.sort(matrix,axis=1)
a
- axis=1代表按行排序,axis=0則為按列排序
result1
2array([[0., 3., 6., 8., 9., 9.],
[1., 3., 3., 4., 4., 8.]])
矩陣內置.sort()排序
對當前調用方法的矩陣排序1
2
3
4matrix =np.array([[9., 3., 8., 0., 6., 9.],
[4., 1., 4., 3., 8., 3.]])
matrix.sort(axis =1)
matrix
result1
2array([[0., 3., 6., 8., 9., 9.],
[1., 3., 3., 4., 4., 8.]])
argsort返回由小到大排序的索引值
1 | matrix =np.array([[9., 3., 8., 0., 6., 9.], |
result1
2array([[3, 1, 4, 2, 0, 5],
[1, 3, 5, 0, 2, 4]])
- 返回原矩陣由小到大原索引值的矩陣