Numpy

denngamin發表於2024-04-09

NumPy 學習筆記

NumPy 是一個 Python 庫。

NumPy 用於處理陣列。

NumPy 是“Numerical Python”的縮寫。
建立一個 NumPy 陣列:

import numpy as np
arr = np.array([1, 2, 3, 4, 5])
print(arr)
print(type(arr))

輸出:

[1 2 3 4 5]  
<class 'numpy.ndarray'>  

NumPy 介紹

在 Python 中,我們有用於陣列目的的列表,但它們的處理速度很慢。

NumPy 旨在提供比傳統的 Python 快的列表。

NumPy 中的陣列物件稱為ndarray, 它提供了許多支援功能,使使用變得非常容易。

陣列在資料科學中非常頻繁地使用,其中速度和資源 都非常重要。

資料科學:是電腦科學的一個分支,我們研究如何儲存、使用和分析資料以從中獲取資訊。

與列表不同,NumPy 陣列儲存在記憶體中的一個連續位置,因此程序可以非常有效地訪問和操作它們。

這種行為在電腦科學中稱為參考區域性性。

這就是 NumPy 比傳統python列表更快的主要原因。此外,它還經過最佳化,可與最新的 CPU 架構配合使用。

NumPy是一個Python庫,部分是用Python編寫的,但大多數需要快速計算的部分都是用C或C++編寫的。

NumPy 的原始碼位於此 github 儲存庫 Numpy

NumPy 入門

pip install numpy安裝numpy

匯入 NumPy
import numpy as np

arr = np.array([1, 2, 3, 4, 5])

print(arr)

NumPy 建立陣列

可以將列表、元組或任何類似陣列的物件傳遞到方法中,它將被轉換為:ndarray

arr = np.array((1, 2, 3, 4, 5))

arr = np.array([1, 2, 3, 4, 5])

建立一個值為 42 的 0-D 陣列:

arr = np.array(42)

建立一個包含值 1、2、3、4、5 的 1-D 陣列:

arr = np.array([1, 2, 3, 4, 5])

建立一個包含兩個陣列的 2-D 陣列,其值分別為 1,2,3 和 4,5,6:

arr = np.array([[1, 2, 3], [4, 5, 6]])

建立一個具有兩個二維陣列的三維陣列:

arr = np.array([[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]])

檢查陣列有多少個維度:

arr.ndim

陣列可以具有任意數量的維度。

建立一個具有 5 個維度的陣列,並驗證它是否具有 5 個維度:

arr = np.array([1, 2, 3, 4], ndmin=5)

print(arr)

print('number of dimensions :', arr.ndim)

[[[[[1 2 3 4]]]]]
number of dimensions : 5

NumPy 陣列索引

從以下陣列中獲取第一個元素:

arr = np.array([1, 2, 3, 4])

print(arr[0])

1

二維陣列想象成一個包含行和列的表格,其中維度 表示行,索引表示列。

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

print('2nd element on 1st row: ', arr[0, 1])

2

三維陣列,訪問第一個陣列的第二個陣列的第三個元素:

arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])

print(arr[0, 1, 2])

6

也和python一樣支援負索引

NumPy 陣列切片

一維的和python一樣
二維的:

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

print(arr[1, 1:4])

輸出:

[7 8 9]

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

print(arr[0:2, 2])

輸出:

[3 8]

NumPy 資料型別

i - integer
b - boolean
u - unsigned integer
f - float
c - complex float
m - timedelta
M - datetime
O - object
S - string
U - unicode string
V - fixed chunk of memory for other type ( void )

獲取陣列物件的資料型別:

arr = np.array([1, 2, 3, 4])

arr = np.array(['apple', 'banana', 'cherry'])

print(arr.dtype)

print(arr.dtype)

int32
<U6 (長度不超過6的Unicode字串)

建立資料型別為字串的陣列:
arr = np.array([1, 2, 3, 4], dtype='S')
print(arr)
print(arr.dtype)

[b'1' b'2' b'3' b'4']
|S1 (長度為1的字串)

在現有陣列上轉換資料型別:
arr = np.array([1.1, 2.1, 3.1])
newarr = arr.astype('i')
print(newarr)
print(newarr.dtype)

[1 2 3]
int32

NumPy 陣列副本與檢視

副本擁有資料,對副本所做的任何更改都不會影響原始陣列,並且對原始陣列所做的任何更改都不會影響副本。

檢視不擁有資料,對檢視所做的任何更改都將擁有影響原始陣列,對原始陣列所做的任何更改都將影響檢視。
副本:

arr = np.array([1, 2, 3, 4, 5])
x = arr.copy()

檢視:

arr = np.array([1, 2, 3, 4, 5])
x = arr.view()

檢查陣列是否擁有其資料:

arr = np.array([1, 2, 3, 4, 5])
x = arr.copy()
y = arr.view()

print(x.base)
print(y.base)

輸出:

None (如果陣列擁有資料,則返回None)
[1 2 3 4 5] (否則,該屬性引用原始物件)

NumPy 陣列形狀

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])

print(arr.shape)

輸出:

(2, 4) (這意味著陣列有 2 個維度, 其中第一個維度有 2 個元素,第二個維度有 4 個元素)  

再例:

arr = np.array([1, 2, 3, 4], ndmin=5)

print(arr)
print('shape of array :', arr.shape)

輸出:

[[[[[1 2 3 4]]]]]
shape of array : (1, 1, 1, 1, 4)
# 可以說第 5 個維度有 4 個元素

NumPy 陣列reshape

即:改變陣列的形狀。

透過重塑,我們可以新增或刪除維度或更改每個維度中的元素數量。

從一維到二維重塑:

將以下具有 12 個元素的一維陣列轉換為二維陣列。

最外層的維度將有 4 個陣列,每個陣列有 3 個元素:

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])

newarr = arr.reshape(4, 3)

print(newarr)

輸出:

[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]

從一維到三維重塑:

將以下具有 12 個元素的一維陣列轉換為三維陣列。

最外層維度將有 2 個陣列,每個陣列包含 3 個陣列 有 2 個元素:

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])

newarr = arr.reshape(2, 3, 2)

print(newarr)

輸出:

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

 [[ 7  8]
  [ 9 10]
  [11 12]]]

返回 Copy 還是 View?

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])

print(arr.reshape(2, 4).base)

輸出:

[1 2 3 4 5 6 7 8]
# 因此它是一個檢視。

未知維度

這意味著您不必為其中一個指定確切的數字 Reshape 方法中的尺寸。

傳遞-1作為值,NumPy 將為您計算這個數字

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])

newarr = arr.reshape(2, 2, -1)

print(newarr)

輸出:

[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]

展平陣列

意味著將多維陣列轉換為一維陣列。

我們可以用它來做到這一點。reshape(-1)

arr = np.array([[1, 2, 3], [4, 5, 6]])

newarr = arr.reshape(-1)

print(newarr)

輸出:

[1 2 3 4 5 6]

NumPy 陣列迭代

迭代一維陣列

arr = np.array([1, 2, 3])

for x in arr:
    print(x)

輸出:

1
2
3

迭代二維陣列

arr = np.array([[1, 2, 3], [4, 5, 6]])

for x in arr:
    print(x)

輸出:

[1 2 3]
[4 5 6]
# 如果我們迭代一個 n 維陣列,它將一個接一個地經歷 n-1 維。

逐一遍歷:

arr = np.array([[1, 2, 3], [4, 5, 6]])

for x in arr:
    for y in x:
        print(y)

輸出:

1
2
3
4
5
6

迭代以下 3-D 陣列的元素:

arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])

for x in arr:
    print(x)

輸出:

[[1 2 3]
 [4 5 6]]
[[ 7  8  9]
 [10 11 12]]

使用 nditer() 迭代陣列

在基本迴圈中,遍歷陣列的每個標量,我們需要使用 n 個for迴圈,這對於具有非常高維數的陣列來說可能很難編寫

arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])

for x in np.nditer(arr):
    print(x)

輸出:

1
2
3
4
5
6
7
8

使用不同的步長進行迭代

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])

for x in np.nditer(arr[:, ::2]):
print(x)

輸出:

1
3
5
7

使用 ndenumerate() 的列舉迭代

列舉意味著逐個提及序列號。

有時我們在迭代時需要元素的相應索引

arr = np.array([1, 2, 3])

for idx, x in np.ndenumerate(arr):
print(idx, x)

輸出:

(0,) 1
(1,) 2
(2,) 3

NumPy 連線陣列

arr1 = np.array([1, 2, 3])

arr2 = np.array([4, 5, 6])

arr = np.concatenate((arr1, arr2))
#沿行堆疊  arr = np.hstack((arr1, arr2))
print(arr)

輸出:

[1 2 3 4 5 6]

沿行連線兩個二維陣列 (axis=1)

arr1 = np.array([[1, 2], 
                 [3, 4]])

arr2 = np.array([[5, 6], 
                 [7, 8]])

arr = np.concatenate((arr1, arr2), axis=1)# 沿行
arr1 = np.concatenate((arr1, arr2), axis=0)# 沿列
print(arr)
print(arr1)
# 維數不變

輸出:

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

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

使用堆疊函式聯接陣列

堆疊與串聯相同,唯一的區別是堆疊是沿著新軸完成的。

我們可以沿第二個軸連線兩個一維陣列,這將導致將它們一個放在另一個上
沿列豎著堆疊(axis = 0可以省略)維數+1:

arr1 = np.array([1, 2, 3])

arr2 = np.array([4, 5, 6])

arr = np.stack((arr1, arr2), axis=0)  
# axis=0 可以省略
# 等於 arr = np.vstack((arr1, arr2))
print(arr)

輸出:

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

沿高度(深度)堆疊:

arr1 = np.array([1, 2, 3])

arr2 = np.array([4, 5, 6])

arr = np.stack((arr1, arr2), axis=1)
# arr = np.dstack((arr1, arr2))
print(arr)

輸出:

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

NumPy 拆分陣列

我們用於拆分陣列,我們將要拆分的陣列傳遞給它 以及拆分次數。

arr = np.array([1, 2, 3, 4, 5, 6])

newarr = np.array_split(arr, 3)

print(newarr)

輸出:

[array([1, 2]), array([3, 4]), array([5, 6])]

如果陣列的元素少於所需的元素,它將相應地從末尾進行調整。

arr = np.array([1, 2, 3, 4, 5, 6])

newarr = np.array_split(arr, 4)

print(newarr)

輸出:

[array([1, 2]), array([3, 4]), array([5]), array([6])]

訪問拆分的陣列:

arr = np.array([1, 2, 3, 4, 5, 6])

newarr = np.array_split(arr, 3)

print(newarr[0])
print(newarr[1])
print(newarr[2])

輸出:

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

拆分二維陣列

將二維陣列拆分為三個二維陣列。

arr = np.array([[1, 2], 
                [3, 4], 
                [5, 6], 
                [7, 8], 
                [9, 10], 
                [11, 12]])

newarr = np.array_split(arr, 3)

print(newarr)

輸出:

[array([[1, 2],
        [3, 4]]), 
 array([[5, 6],
        [7, 8]]), 
 array([[ 9, 10],
        [11, 12]])]

此外,還可以指定要圍繞哪個軸進行分割。

下面的示例還返回三個二維陣列,但它們沿著深度 (axis=1)

arr = np.array([[1, 2, 3], 
                [4, 5, 6], 
                [7, 8, 9], 
                [10, 11, 12], 
                [13, 14, 15], 
                [16, 17, 18]])

newarr = np.array_split(arr, 3, axis=1)
# 沿深度 newarr = np.hsplit(arr, 3)
print(newarr)

輸出:

[array([[ 1],
    [ 4],
    [ 7],
    [10],
    [13],
    [16]]), 
array([[ 2],
    [ 5],
    [ 8],
    [11],
    [14],
    [17]]), 
array([[ 3],
    [ 6],
    [ 9],
    [12],
    [15],
    [18]])]

NumPy 搜尋陣列

在陣列中搜尋特定值,並返回獲得匹配項的索引。

若要搜尋陣列,請使用以下方法。where()

arr = np.array([1, 2, 3, 4, 5, 4, 4])

x = np.where(arr == 4)
# 查詢值為偶數的索引: x = np.where(arr%2 == 0)
# 查詢值為奇數的索引: x = np.where(arr%2 == 1)
print(x)

輸出:

(array([3, 5, 6], dtype=int64),)

搜尋排序

在陣列中執行二進位制搜尋, 並返回將插入指定值的索引,以保持 搜尋順序。searchsorted()

arr = np.array([6, 7, 8, 9])

x = np.searchsorted(arr, 7)

print(x)

輸出:

1

從右側搜尋:

arr = np.array([6, 7, 8, 9])

x = np.searchsorted(arr, 7, side='right')

print(x)

多個值:

arr = np.array([1, 3, 5, 7])

x = np.searchsorted(arr, [2, 4, 6])

print(x)

輸出:

[1 2 3]

NumPy 排序陣列

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

print(np.sort(arr))

輸出:

[0 1 2 3]

對布林陣列進行排序:

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

print(np.sort(arr))

輸出:

[False  True  True]

對二維陣列進行排序

如果對二維陣列使用 sort() 方法,則兩個陣列都將進行排序:

arr = np.array([[3, 2, 4], [5, 0, 1]])

print(np.sort(arr))

輸出:

[[2 3 4]
 [0 1 5]]

NumPy 過濾陣列

從現有陣列中獲取一些元素並建立一個新陣列 其中稱為過濾。

在 NumPy 中,使用布林索引列表篩選陣列。

如果該索引處的值是False,則從篩選陣列中排除該元素。

arr = np.array([41, 42, 43, 44])

x = [True, False, True, False]

newarr = arr[x]

print(newarr)

輸出:

[41 43]

建立篩選器陣列

建立一個僅返回大於 42 的值的篩選器陣列:

arr = np.array([41, 42, 43, 44])

filter_arr = []

for element in arr:
    if element > 42: # 根據任務修改這行
        filter_arr.append(True)
    else:
        filter_arr.append(False)

newarr = arr[filter_arr]

print(filter_arr)
print(newarr)

直接從陣列建立過濾器

arr = np.array([41, 42, 43, 44])

filter_arr = arr > 42

newarr = arr[filter_arr]

print(filter_arr)
print(newarr)

輸出:

[False False  True  True]
[43 44]

NumPy random庫-暫略

NumPy 以下介紹ufuncs

ufuncs 代表“通用函式”,它們是 NumPy 函式, 對ndarray物件進行操作

ufuncs 用於在 NumPy 中實現向量化(將迭代語句轉換為基於向量的操作稱為向量化。),這比迭代元素要快得多。

由於現代 CPU 針對此類操作進行了最佳化,因此速度更快。

沒有 ufunc,我們可以使用 Python 的內建方法:

x = [1, 2, 3, 4]
y = [4, 5, 6, 7]
z = []

for i, j in zip(x, y):
z.append(i + j)
print(z)

輸出:

[5, 7, 9, 11]

使用 ufunc,我們可以使用以下函式:add()

x = [1, 2, 3, 4]
y = [4, 5, 6, 7]
z = np.add(x, y)

print(z)

輸出相同

建立自己的 ufunc

要建立自己的 ufunc,您必須定義一個函式,就像您在 Python 中使用普通函式一樣,然後使用frompyfunc()方法將其新增到您的 NumPy ufunc 庫中。

該方法採用以下引數:frompyfunc()

function- 函式的名稱。
inputs- 輸入引數(陣列)的數量。
outputs- 輸出陣列的數量。

def myadd(x, y):
    return x+y
# 輸入2個,輸出1個
myadd = np.frompyfunc(myadd, 2, 1)

print(myadd([1, 2, 3, 4], [5, 6, 7, 8]))

檢查函式的型別以檢查它是否是 ufunc。

print(type(np.add))

輸出:

<class 'numpy.ufunc'>

ufunc 簡單算術

加法:上述已說明(np.add())

減法:

arr1 = np.array([10, 20, 30, 40, 50, 60])
arr2 = np.array([20, 21, 22, 23, 24, 25])

newarr = np.subtract(arr1, arr2)

print(newarr)

輸出:

[-10  -1   8  17  26  35]

乘法:

arr1 = np.array([10, 20, 30, 40, 50, 60])
arr2 = np.array([20, 21, 22, 23, 24, 25])

newarr = np.multiply(arr1, arr2)

print(newarr)

輸出:

[ 200  420  660  920 1200 1500]

除法:

arr1 = np.array([10, 20, 30, 40, 50, 60])
arr2 = np.array([3, 5, 10, 8, 2, 33])

newarr = np.divide(arr1, arr2)

print(newarr)

輸出:

[ 3.33333333  4.          3.          5.         25.          1.81818182]

冪運算:

arr1 = np.array([10, 20, 30, 40, 50, 60])
arr2 = np.array([3, 5, 6, 8, 2, 33])

newarr = np.power(arr1, arr2)

print(newarr)

輸出:

[1000 3200000 729000000 6553600000000 2500 0]

求餘:

arr1 = np.array([10, 20, 30, 40, 50, 60])
arr2 = np.array([3, 7, 9, 8, 2, 33])

newarr = np.mod(arr1, arr2)
# newarr = np.remainder(arr1, arr2)
print(newarr)

輸出:

[1 6 3 0 0 27]

商和餘數:

arr1 = np.array([10, 20, 30, 40, 50, 60])
arr2 = np.array([3, 7, 9, 8, 2, 33])

newarr = np.divmod(arr1, arr2)

print(newarr)

輸出:

(array([ 3,  2,  3,  5, 25,  1]), array([ 1,  6,  3,  0,  0, 27]))

絕對值:

arr = np.array([-1, -2, 1, 2, 3, -4])

newarr = np.absolute(arr)

print(newarr)

ufunc 四捨五入

截斷

刪除小數,並返回最接近零的浮點數。trunc()和fix()

arr = np.trunc([-3.1666, 3.6667])
# arr = np.fix([-3.1666, 3.6667])
print(arr)

輸出:

[-3.  3.]

四捨五入

如果 >=5,則該函式將前面的數字或十進位制遞增 1,否則什麼都不做。

arr = np.around(3.1666, 2)

print(arr)

輸出:

3.17

下取整

將小數四捨五入到最接近的下整數

arr = np.floor([-3.1666, 3.6667])

print(arr)

輸出:

[-4.  3.]

上取整

將小數四捨五入到最接近的大整數

arr = np.ceil([-3.1666, 3.6667])

print(arr)

輸出:

[-3.  4.]

ufunc log()對數函式

NumPy 提供了在基數 2、e 和 10 上執行對數函式。

log2()

使用該函式在基數 2 處執行日誌。log2()

arr = np.arange(1, 10)

print(np.log2(arr))

輸出:

[0.         1.         1.5849625  2.         2.32192809 2.5849625
2.80735492 3.         3.169925  ]

log10()

arr = np.arange(1, 10)

print(np.log10(arr))

輸出:

[0.         0.30103    0.47712125 0.60205999 0.69897    0.77815125
0.84509804 0.90308999 0.95424251]

自然對數

arr = np.arange(1, 10)

print(np.log(arr))

輸出:

[0.         0.69314718 1.09861229 1.38629436 1.60943791 1.79175947
 1.94591015 2.07944154 2.19722458]

在任何基底的log

from math import log
import numpy as np

nplog = np.frompyfunc(log, 2, 1)

print(nplog(100, 15))

輸出:

ufunc add()和sum()求和

arr1 = np.array([1, 2, 3])  
arr2 = np.array([1, 2, 3])  

前面

newarr = np.add(arr1, arr2)  
# [2 4 6]

是對應求和
下面 將 arr1 中的值和 arr2 中的值相加:

newarr = np.sum([arr1, arr2])
# 12
newarr = np.sum([arr1, arr2], axis=1)
# [6 6]

累計求和

例如,[1, 2, 3, 4] 的部分和將是 [1, 1+2, 1+2+3, 1+2+3+4] = [1, 3, 6, 10]

newarr = np.cumsum(arr1)
# [1 3 6]

ufunc prod()乘積

arr = np.array([1, 2, 3, 4])

x = np.prod(arr)

print(x)

輸出:

返回:因為 1*2*3*4 = 2424

求兩個陣列元素的乘積:

arr1 = np.array([1, 2, 3, 4])
arr2 = np.array([5, 6, 7, 8])

x = np.prod([arr1, arr2])
# newarr = np.prod([arr1, arr2], axis=1)

print(x)
# print(newarr)

輸出:

返回:因為 1*2*3*4*5*6*7*8 = 40320
# 輸出[24 1680]

累計求積

# 例如,[1, 2, 3, 4] 的偏積為 [1, 1*2, 1*2*3, 1*2*3*4] = [1, 2, 6, 24]

arr = np.array([5, 6, 7, 8])

newarr = np.cumprod(arr)

print(newarr)

輸出:

[5 30 210 1680]

ufunc diff()

離散差值意味著減去兩個連續的元素。

例如,對於 [1, 2, 3, 4],離散差為 [2-1, 3-2, 4-3] = [1, 1, 1]

可以透過給出引數來重複執行此操作。

arr = np.array([10, 15, 25, 5])

newarr = np.diff(arr)

print(newarr)

輸出:

返回:因為 15-10=5、25-15=10 和 5-25=-20[5 10 -20]

計算以下陣列的離散差值兩次:

arr = np.array([10, 15, 25, 5])

newarr = np.diff(arr, n=2)

print(newarr)

輸出:

返回:因為:15-10=5、25-15=10、5-25=-20、10-5=5 和 -20-10=-30[5 -30]

ufunc 查詢 LCM(最小公倍數)

num1 = 4
num2 = 6

x = np.lcm(num1, num2)

print(x)

輸出:

12

在陣列中查詢 LCM

arr = np.array([3, 6, 9])

x = np.lcm.reduce(arr)

print(x)

輸出:

18

求陣列包含從 1 到 10 的所有整數的陣列的所有值的 LCM:

arr = np.arange(1, 11)

x = np.lcm.reduce(arr)

print(x)

輸出:

2520

ufunc GCD(最大公約數)

num1 = 6
num2 = 9

x = np.gcd(num1, num2)

print(x)

在以下陣列中查詢所有數字的 GCD:

arr = np.array([20, 8, 32, 36, 16])

x = np.gcd.reduce(arr)

print(x)

輸出:

4

ufunc 三角函式

x = np.sin(np.pi/2)

print(x)

查詢 arr 中所有值的正弦值:

arr = np.array([np.pi/2, np.pi/3, np.pi/4, np.pi/5])

x = np.sin(arr)

print(x)

輸出:

[1.         0.8660254  0.70710678 0.58778525]

將度數轉換為弧度deg2rad()

注意:弧度值為 pi/180 * degree_values。

arr = np.array([90, 180, 270, 360])

x = np.deg2rad(arr)

print(x)

輸出:

[1.57079633 3.14159265 4.71238898 6.28318531]

弧度到度rad2deg()

arr = np.array([np.pi/2, np.pi, 1.5*np.pi, 2*np.pi])

x = np.rad2deg(arr)

print(x)

輸出:

[ 90. 180. 270. 360.]

尋找角度arcsin()、arccos()、arctan()

x = np.arcsin(1.0)

print(x)

輸出:

1.5707963267948966(pi/2)

斜邊hypot()

base = 3
perp = 4

x = np.hypot(base, perp)

print(x)

輸出:

5

NumPy 雙曲函式暫略

NumPy 集合操作暫略

學習地址W3S