numpy[ˋnʌmpi](讀音為難py) 可以把它想像成是一台強大的工程計算機。
Python 常用的三台強大計算機分別為 Numpy、Tensorflow、PyTorch。
Numpy : 使用 CPU 計算。
Tensorflow : 使用 CPU/GPU計算,由 Google 開發。
PyTorch : 使用 CPU/GPU計算,由 Facebook開發。烏俄戰爭無人機使用 Yolo 搭配 PyTorch 演算而來。
Numpy 是計算統計學及許多科學函數的第三方套件,基本資料形態就是陣列。numpy 涵蓋範圍多且廣,不易完全熟悉。
numpy 會產生很多有用的數字,但這些數字人類無法理解,所以可以透過 Matplotlib 將數字視覺化。
numpy 可以包含基本的整數,小數及字元,甚至是字串。 而 numpy 的效能遠比 list、tuple 高出許多。
numpy 一但建立出來, 其元素的長度就無法變更。因為它就是基於陣列建立出來的,其本質並不是集合,所以和 list 完全不一樣。
安裝套件及 import
numpy 在使用前,需使用如下指令進行安裝
pip install numpy
然後再 import numpy
import numpy as np
numpy 在 2024 年 6 月進化到了 2.0 版,跟 1.0 版有些大幅的改進,效能也更好。
一維陣列
下面的代碼是比較簡單的一維陣列. 使用 np.array()建立一個陣列, 參數必需是list, 如
a=np.array([1,2,3,4,5]). 當陣列一建立後, 其長度就無法再改變.
存取每個元素, 可以使用索引(index)指定. 但請注意, 索引是由 0 開始. 當指定的索引超出陣列的長度, 就會於Runtime時期發生out of bundle exception
Array跟List用法表面上蠻像的,如a[0]=100, list也是 l[0]=100。但List可以增加長度,如l.append(100)。而Array就無法增加。
Numpy增加了sort類別方法 : np.sort([…])
也有物件方法 : sum ,mean, var, std等統計的功能,這是List所沒有的。
列印陣列時, 如果直接列印 a, 則會將每個元素以陣列的方式印出. 若要一個一個印出, 可以使用迴圈.
import numpy as np
import random a=np.array([1,2,3,4,5]) print(a) for i in range(0,5): a[i]=random.randint(1,100) for i in range(0,5): print("a[%d]=%d" % (i, a[i])) b=np.array(range(1, 11))
print(b)
結果 : [1 2 3 4 5] a[0]=7 a[1]=85 a[2]=75 a[3]=20 a[4]=70
[ 1 2 3 4 5 6 7 8 9 10]
型別
np.array其實還有第二個參數,可以指定型別,如下所示
x=np.array([1,2,3,4], dtype=np.int32)
print(x.dtype) #印出int32
dtype即為型別參數,若沒有dtype, 則整數預設為 np.int64,小數預設為 np.float64。可用的型別有
bool, string,
int8, int16, int32, int64,
uint8, uint16, uint32, uint64
float16, float32, float64
dtype可以使用np.intxx,亦可以使用字串 “intxx”,或直接使用 np.intxx({})
x=np.array([1,2,3], dtype=np.int32)
y=np.array([1,2,3], dtype="int32")
z=np.int32([1,2,3])
np.zeros
np.zeros([長度]), 可以產生特定長度的空陣列, 每個元素皆填入 0.
import numpy as np
a=np.zeros([10])
np.ones
全部填入1
import numpy as np
a=np.ones([10])
print(a)
結果 :
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
排序
np的類別方法 np.sort([….]) 可進行排序,其參數可以為陣列,亦可以為List。結果為排序後的陣列。
而系統函數 sorted([…]),其參數亦可以為陣列或List,結果為排序後的List。
a=np.array([6,4,5,1,8,7])
print(np.sort(a)) #印出排序後的陣列
print(sorted(a, reverse=False)) #印出厞序後的list
汽泡排序法
下面的演算法, 就是頂頂有名的汽泡排序法,但此法僅作為教學用。若真的要排序,np.sort()會切換到C/C++語言進行排序,故效能會高很多。
import numpy as np, random
#產生10個元素的陣列, 並把每個元素都填入 0
d=np.zeros([10])
#將亂數填入陣列中
for i in range(0,len(d)):
d[i]=random.randint(1,100)
#列印未排序的陣列
for i in range(0,len(d)):
print("%d " % d[i],end='')
print()
#汽泡排序法
for i in range(0, len(d)-1):
for j in range(i+1, len(d)):
if d[i]>d[j]:
tmp=d[i]
d[i]=d[j]
d[j]=tmp
#列印已排序的陣列
for i in range(0,len(d)):
print("%d " % d[i],end='')
print()
結果 :
9 41 5 19 3 59 42 26 73 10
3 5 9 10 19 26 41 42 59 73
陣列相加
二個陣列可以進行相加, 這功能還蠻方便的
import numpy as np a=np.array([1,2,3,4,5]) b=np.array([6,7,8,9,10]) c=a+b print(c) 結果 : [ 7 9 11 13 15]
二維陣列
二維陣列的宣告, 就是使用 [ [], [],[] …], 每一列的長度都可以不一樣.
import numpy as np
a=np.array([[1,2,3,4,5], [6,7,8], [10,20,30,40]])
for i in range(0,len(a)):
for j in range(0,len(a[i])):
print("%d " % a[i][j], end='')
print()
結果 :
1 2 3 4 5
6 7 8
10 20 30 40
空二維陣列
要產生特定長度的二維陣列, 同樣使用zeros(), 於list中指定列數及行數
a=np.zeros([3,10])
reshape
這個功能是要將一維變成二維, 或是二維變成一維. 請注意, 如果是二維的話, 在變換時, 每列的長度都必需一樣
import numpy as np
a=np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print ("2*4陣列 : \n%s" % a)
a=a.reshape([1, 8])
print ("1*8陣列 : \n %s" % a)
a=a.reshape([4, 2])
print ("4*2陣列 : \n %s " % a)
結果 :
2*4陣列 :
[[1 2 3 4]
[5 6 7 8]]
1*8陣列 :
[[1 2 3 4 5 6 7 8]]
4*2陣列 :
[[1 2]
[3 4]
[5 6]
[7 8]]
統計功能
numpy其實還有統計的特異功能, 如下變異數,標準差,平均值。
變異數的公式為
$$variance = \frac{1}{n}\sum_{i=1}^{n}(x_{i}-\bar{x})^{2}$$
標準差的公式為
$$std= \sqrt{\frac{1}{n}\sum_{i=1}^{n}(x_{i}-\bar{x})^{2}}$$
import array, numpy as np
a=np.array([1,2,3,4,5])
print("標準差 : %.2f" % a.std())
print("最小值 : %.2f" % a.min())
print("最大值 : %.2f" % a.max())
print("平均值 : %.2f" % a.mean())
print("總 合 : %.2f" % a.sum())
結果 :
標準差 : 1.41
最小值 : 1.00
最大值 : 5.00
平均值 : 3.00
總 合 : 15.00
範例一
公司請了三個營業員, 販賣五項商品, 每個營業員的銷售數量如下
sales1 : 10, 15, 11, 13, 20
sales2 : 8, 20, 18, 19, 25
sales3 : 15, 25, 31, 10, 28
公司的每項商品價格如下
price : 10, 20, 30, 40, 50
請計算
1. 每位營業員的銷售金額, 如
sales1 : 10*10+15*20+11*30+13*40+20+50
2. 計算每項商品的營業額, 如
item1 : (10+8+15)*10
import numpy as np, random
qty=np.array([
[10,15,11,13,20],
[8,20,18,19,25],
[15,25,31,10,28]])
price=np.array([10,20,30,40,50])
for i in range(0,len(qty)):
total=0
for j in range(0,len(price)):
total+=qty[i][j]*price[j]
print(f"sales{i} 銷售額為 : {total:.2f}")
for i in range(0,len(price)):
total=0
for j in range(0,len(qty)):
total+=qty[j][i]
print(f"item{i} 營業額 : {total*price[i]:.2f}")
結果 :
sales1 銷售額為 : 2250.00
sales2 銷售額為 : 3030.00
sales3 銷售額為 : 3380.00
item1 營業額 : 330.00
item2 營業額 : 1200.00
item3 營業額 : 1800.00
item4 營業額 : 1680.00
item5 營業額 : 3650.00
但是如果使用 numpy 的新思維,可以改成如下
import numpy as np, random
qty=np.array([
[10,15,11,13,20],
[8,20,18,19,25],
[15,25,31,10,28]])
price=np.array([10,20,30,40,50])
sales=qty*price
print(sales)
for i in range(0,len(qty)):
print(f"sales{i} 銷售額為 : {sales[i].sum():.2f}")
範例二
河圖洛書, 每列加總=每行加總=對角加總
| 8 | 1 | 6 |
| 3 | 5 | 7 |
| 4 | 9 | 2 |
import numpy as np, random
n=5
d=np.zeros([n, n], dtype=np.int32)
x=n//2
y=0
index=1
while index <= n*n:
d[y][x]=index
index+=1
if x==n-1 and y==0 :y+=1
else:
x=(x+1)%n
y=(y-1+n)%n
if(d[y][x]!=0):
x-=1
y+=2
for i in range(0,n):
for j in range(0,n):
print(f"{(d[i][j]):4d", end="")
print()
結果 :
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
三角函數
三角函數需且需先pip install numpy(1.19.3版)
(File/Setting/專案名稱/Python Interpreter/再加 numpy套件,然後於右下角的Specify version選取 1.19.3)
np.sin(np.pi/180*角度) : 請注意,三角函數裏面的參數不是角度,而是弧度。
import numpy as np
for i in [0,30,60,45,90]:
sin = np.sin(np.pi / 180 * i)
cos = np.cos(np.pi / 180 * i)
tan = np.tan(np.pi / 180 * i)
print(f'sin{i:02}={sin:.3f}, cos{i:02}={cos:.3f}, tan{i:02}={tan:.3f}')
結果 :
sin00=0.000, cos00=1.000, tan00=0.000
sin30=0.500, cos30=0.866, tan30=0.577
sin60=0.866, cos60=0.500, tan60=1.732
sin45=0.707, cos45=0.707, tan45=1.000
sin90=1.000, cos90=0.000, tan90=16331239353195370.000 <==此為無窮大
反三角函數
反三角函數的目的,是經由三角函數的值反算其角度。比如$(sin(30) = 0.5)$. 那麼
$(sin^{-1}(0.5)=0.524)$。 0.524是弧度,需再經由np.degress(0.524)才會算出30度角
arc=np.arcsin(0.5)
ang=np.degrees(arc)
print(f'弧度 : {arc:.3f}')
print(f'角度 : {ang:.3f}')
結果 :
弧度 : 0.524
角度 : 30.000
array.array
array並不是陣列, 其本質就是集合, 而且跟list一樣, 但只能包含整數, 小數及字元, 其他如物件等無法加入. 所以其效能也比list高出許多
import array
a=array.array("l")
a.append(1)
a.append(2)
a.append(3)
a.append(4)
a.append(5)
a.pop()
a.remove(2) #刪除第二個, 第一個為 1
print(a[0])
print(a)
建立array
建立arry時, 使用array.array(數據型態). 數據型態如下表所示
| Type code | C Type | Python Type | Minimum size in bytes | Notes |
|---|---|---|---|---|
'b' |
signed char | int | 1 | |
'B' |
unsigned char | int | 1 | |
'u' |
Py_UNICODE | Unicode character | 2 | (1) |
'h' |
signed short | int | 2 | |
'H' |
unsigned short | int | 2 | |
'i' |
signed int | int | 2 | |
'I' |
unsigned int | int | 2 | |
'l' |
signed long | int | 4 | |
'L' |
unsigned long | int | 4 | |
'q' |
signed long long | int | 8 | (2) |
'Q' |
unsigned long long | int | 8 | (2) |
'f' |
float | float | 4 | |
'd' |
double | float | 8 |
存取
array可以使用索引進行存取, 如 a[0]
常用函數
常用的有如 reverse, count, index, 請參照如下
import array, numpy as np
a=array.array("l")
a.append(1)
a.append(3)
a.append(3)
a.append(4)
print("3出現的次數 : %d" % a.count(3))#3出現的次數
print("4第一次出現的位置 : %d" % a.index(4))#4第一次出現的位置, 位置由0開始
a.reverse()#反轉
print("反轉後的結果 : ", a)
結果 :
3出現的次數 : 2
4第一次出現的位置 : 3
反轉後的結果 : array('l', [4, 3, 3, 1])
Slicing
Slicing是要擷取陣列某片段的資料。底下代碼中,a為[1,2,3…10]的陣列,
a[2:4]表示式中,2為擷取的啟始編號,4為擷取的結束編號,但不包含4。
import numpy as np
a=np.array([1,2,3,4,5,6,7,8,9,10])
b=a[2:4]
print(b)
結果:
[3,4]
若要擷取全部的資料,只需使用 a[:]即可
結束編號亦可為負值,表示由後面開始算起,如a[2:-1],則由2開始抓取到最後第2個,所以結果為
[3 4 5 6 7 8 9]
如果是二維陣列,則用 “,” 隔開每一維的編號,如下
0:2 表示取得 第0及1列
2:4 表示第2到3行
import numpy as np
a=np.array([
[1,2,3,4,5],
[6,7,8,9,10]
])
b=a[0:2,2:4]
print(b)
結果:
[[3 4]
[8 9]]
過濾器
todo
