Numpy

      在〈Numpy〉中尚無留言

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其實還有統計的特異功能, 如下變異數,標準差,平均值。

有關變異數及標準差,請參照 數學變異數 這篇

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])
x=int(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("%3d " % (d[i][j]), 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

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *