系列文章地址
Numpy 是 Python 中科學計算的核心庫,NumPy 這個詞來源於 Numerical 和 Python 兩個單詞。它提供了一個高效能的多維陣列物件,以及大量的庫函式和操作,可以幫助程式設計師輕鬆地進行數值計算,廣泛應用於機器學習模型、影象處理和計算機圖形學、數學任務等領域。
Numpy 陣列:ndarray
NumPy 中定義的最重要的物件是稱為 ndarray 的 N 維陣列型別,它是描述相同型別的元素集合。ndarray 中的每個元素都是資料型別物件(dtype)的物件。ndarray 中的每個元素在記憶體中使用相同大小的塊。
numpy.array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0)
複製程式碼
引數 | 描述 |
---|---|
object | 任何暴露陣列介面方法的物件 |
dtype | 資料型別 |
copy | 如果為 True,則 object 物件被複制,否則,只有當__array__ 返回副本,object 是巢狀序列,或者需要副本來滿足任何其他要求(dtype,order等)時,才會生成副本。 |
order | 指定陣列的記憶體佈局。 如果 object 不是陣列,則新建立的陣列將按行排列(C),如果指定了(F),則按列排列。 如果 object 是一個陣列,則以下成立。C(按行)、F(按列)、A(原順序)、K(元素在記憶體中的出現順序) |
subok | 預設情況下,返回的陣列被強制為基類陣列。 如果為 True,則返回子類。 |
ndmin | 返回陣列的最小維數 |
例一:最簡單的示例
import numpy as np
a = [1, 2, 3]
b = np.array(a)
print(b)
print(type(b))
複製程式碼
輸出:
[1 2 3]
<class 'numpy.ndarray'>
複製程式碼
注意:
list
列印顯示是[1, 2, 3]
,而ndarray
列印顯示是[1 2 3]
,當中沒有逗號。
例二:dtype 引數用法示例 NumPy 支援比 Python 更多種類的數值型別
import numpy as np
a = [1, 2, 3]
b = np.array(a, dtype=np.float_)
# 或者
b = np.array(a, dtype=float)
print(b)
print(b.dtype)
print(type(b[0]))
複製程式碼
輸出:
[1. 2. 3.]
float64
<class 'numpy.float64'>
複製程式碼
例三:copy 引數的用法
import numpy as np
a = np.array([1, 2, 3])
b = np.array(a, copy=True)
a[0] = 0
print(a)
print(b)
複製程式碼
輸出:
[0 2 3]
[1 2 3]
複製程式碼
可以看到 a
和 b
的值不同,說明 b
是 a
的副本,兩個是不同的物件。
import numpy as np
a = np.array([1, 2, 3])
b = np.array(a, copy=False)
a[0] = 0
print(a)
print(b)
複製程式碼
輸出:
[0 2 3]
[0 2 3]
複製程式碼
a
改變同時引起了 b
的改變,說明 a
和 b
指向的是同一個物件。
例四:ndmin 引數用法示例
import numpy as np
a = [1, 2, 3]
b = np.array(a, ndmin=2)
print(b)
複製程式碼
輸出:
[[1 2 3]]
複製程式碼
可以看到結果已經變成了二維陣列。
例五:subok 引數用法示例
看解釋不是很清楚,看下面這個例子就會明白許多。其中 matrix
是矩陣,將在之後的內容中介紹。
import numpy as np
a = np.matrix('1 2 7; 3 4 8; 5 6 9')
print(type(a))
print(a)
at = np.array(a, subok=True)
af = np.array(a, subok=False)
print(type(at))
print(type(af))
複製程式碼
輸出:
<class 'numpy.matrix'>
[[1 2 7]
[3 4 8]
[5 6 9]]
<class 'numpy.matrix'>
<class 'numpy.ndarray'>
複製程式碼
NumPy 陣列屬性
NumPy 陣列的維度(又稱維數)稱為秩(rank),一維陣列的秩為 1,二維陣列的秩為 2,以此類推。 NumPy 中,每一個線性的陣列稱為是一個軸(axis),也就是維度(dimensions)。
屬性 | 說明 |
---|---|
ndarray.ndim | 秩,即軸的數量或維度的數量 |
ndarray.shape | 陣列的維度,對於矩陣,n 行 m 列 |
ndarray.size | 陣列元素的總個數,相當於 .shape 中 n*m 的值 |
ndarray.dtype | ndarray 物件的元素型別 |
ndarray.itemsize | ndarray 物件中每個元素的大小,以位元組為單位 |
ndarray.flags | ndarray 物件的記憶體資訊 |
ndarray.real | ndarray 元素的實部(複數的實部) |
ndarray.imag | ndarray 元素的虛部(複數的虛部) |
ndarray.data | 包含實際陣列元素的緩衝區,由於一般通過陣列的索引獲取元素,所以通常不需要使用這個屬性。 |
1、ndarray.shape
返回一個包含陣列維度的元組,對於矩陣,n 行 m 列,它也可以用於調整陣列維度。 例一:
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape)
複製程式碼
輸出:
(2, 3)
複製程式碼
例二:
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
a.shape = (3, 2)
print(a)
複製程式碼
輸出:
[[1 2]
[3 4]
[5 6]]
複製程式碼
例三:
NumPy 也提供了reshape()
函式來調整陣列維度。只是 reshape()
返回撥整維度後的副本,而不改變原 ndarray。
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = a.reshape(3, 2)
print(b) # a 沒變
複製程式碼
輸出:
[[1 2]
[3 4]
[5 6]]
複製程式碼
2、ndarray.ndim
返回陣列的維度(秩)。 例一:
import numpy as np
a = np.arange(24)
print(a.ndim)
# 現在調整其大小
b = a.reshape(2, 4, 3)
print(b.ndim)
複製程式碼
輸出:
1
3
複製程式碼
3、ndarray.flags
ndarray.flags 返回 ndarray 物件的記憶體資訊,包含以下屬性:
屬性 | 描述 |
---|---|
C_CONTIGUOUS | 資料是在一個單一的C風格的連續段中 |
F_CONTIGUOUS | 資料是在一個單一的Fortran風格的連續段中 |
OWNDATA | 陣列擁有它所使用的記憶體或從另一個物件中借用它 |
WRITEABLE | 資料區域可以被寫入,將該值設定為 False,則資料為只讀 |
ALIGNED | 資料和所有元素都適當地對齊到硬體上 |
WRITEBACKIFCOPY | UPDATEIFCOPY 已棄用,由 WRITEBACKIFCOPY 取代; |
UPDATEIFCOPY | 這個陣列是其它陣列的一個副本,當這個陣列被釋放時,原陣列的內容將被更新 |
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.flags)
複製程式碼
輸出:
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
WRITEBACKIFCOPY : False
UPDATEIFCOPY : False
複製程式碼
4、ndarray.real
import numpy as np
x = np.sqrt([1+0j, 0+1j])
print(x)
print(x.real)
print(x.real.dtype)
複製程式碼
輸出:
[1. +0.j 0.70710678+0.70710678j]
[1. 0.70710678]
float64
複製程式碼
NumPy 中的常數
- 正無窮:Inf = inf = infty = Infinity = PINF
- 負無窮:NINF
- 正零:PZERO
- 負零:NZERO
- 非數值:nan = NaN = NAN
- 自然數e:e
- π:pi
- 伽馬:euler_gamma
- None 的別名:newaxis
示例:
print(np.inf)
print(np.NINF)
print(np.PZERO)
print(np.NZERO)
print(np.nan)
print(np.e)
print(np.pi)
print(np.euler_gamma)
print(np.newaxis)
複製程式碼
輸出:
inf
-inf
0.0
-0.0
nan
2.718281828459045
3.141592653589793
0.5772156649015329
None
複製程式碼
NumPy 建立陣列
1、numpy.empty
此方法用來建立一個指定維度(shape)、資料型別(dtype)的未初始化的陣列。
numpy.empty(shape, dtype=float, order='C')
複製程式碼
引數 | 描述 |
---|---|
shape | 一個表示陣列維度的元組 |
dtype | 資料型別 |
order | 有 "C" 和 "F" 兩個選項 |
示例:
import numpy as np
x = np.empty([3, 2], dtype=int)
print(x)
複製程式碼
輸出:
[[ 0 1072693248]
[ 0 1072693248]
[ 0 1072693248]]
複製程式碼
empty()
方法和 zeros()
方法不同,不會將陣列值設定為零,因此可能會略微加快。另一方面,它要求使用者手動設定陣列中的所有值,並應謹慎使用。
2、numpy.zeros
建立指定維度,以 0 填充的新陣列。
numpy.zeros(shape, dtype=float, order='C')
複製程式碼
示例:
import numpy as np
x = np.zeros(5)
print(x)
複製程式碼
輸出:
[0. 0. 0. 0. 0.]
複製程式碼
注意:預設是 float 型別的
3、numpy.ones
建立指定維度,以 1 填充的新陣列。
numpy.ones(shape, dtype=float, order='C')
複製程式碼
示例:
import numpy as np
x = np.ones(5)
print(x)
複製程式碼
輸出:
[1. 1. 1. 1. 1.]
複製程式碼
4、numpy.full
返回給定維度和型別的新陣列,填充 fill_value。
numpy.full(shape, fill_value, dtype=None, order='C')
複製程式碼
引數 | 描述 |
---|---|
shape | 返回陣列的維度 |
fill_value | 填充值 |
dtype | 返回陣列的資料型別,預設值 None 指:np.array(fill_value).dtype |
order | 在計算機記憶體中的儲存元素的順序,只支援 'C'(按行)、'F'(按列),預設 'C' |
示例:
import numpy as np
a = np.full((2, 3), 9)
print(a)
複製程式碼
輸出:
[[9 9 9]
[9 9 9]]
複製程式碼
NumPy 從數值範圍建立陣列
1、numpy.arange
該函式等效於 Python 內建 range
函式,但返回的是 ndarray 而不是列表。
arange([start,] stop[, step,], dtype=None)
複製程式碼
[ ] 括起來的表示可選引數。
引數 | 描述 |
---|---|
start | 起始值,預設為 0 |
stop | 終止值(不包含) |
step | 步長,預設為1 |
dtype | 建立的 ndarray 的資料型別,如果沒有提供,則會使用輸入資料的型別。 |
示例:
import numpy as np
a = np.arange(5)
b = np.arange(10, 20, 2)
print(a)
print(b)
複製程式碼
輸出:
[0 1 2 3 4]
[10 12 14 16 18]
複製程式碼
2、numpy.linspace
建立一個一維等差數列的陣列,與 arange
函式不同,arange
是固定步長,而 linspace
則是固定元素數量。
linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
複製程式碼
引數 | 描述 |
---|---|
start | 序列的起始值 |
stop | 序列的終止值,如果 endpoint 為 True,則該值包含於數列中 |
num | 要生成的等步長的樣本數量,預設為 50 |
endpoint | 該值為 Ture 時,數列中中包含 stop 值,反之不包含,預設是 True。 |
retstep | 如果為 True 時,生成的陣列中會顯示間距,反之不顯示。 |
dtype | ndarray 的資料型別 |
例一:endpoint 引數的用法
我特意挑了下面這個除不盡的例子來顯示 endpoint
的效果。可以看到,endpoint=False
取值是 endpoint=True
,並且 num = num + 1
的結果去掉終止值。這話有點拗口啊,對比一下下例中的 num
引數值及輸出結果就明白了。
import numpy as np
a = np.linspace(0, 5, 3, endpoint=False)
b = np.linspace(0, 5, 4, endpoint=True)
print(a)
print(b)
複製程式碼
輸出:
[0. 1.66666667 3.33333333]
[0. 1.66666667 3.33333333 5. ]
複製程式碼
例二:retstep 引數的用法
返回一個元組,第一個元素是 numpy.ndarray,第二個元素是步長。
import numpy as np
a = np.linspace(0, 10, 5, retstep=True)
print(a)
複製程式碼
輸出:
(array([ 0. , 2.5, 5. , 7.5, 10. ]), 2.5)
複製程式碼
例三:dtype 引數
dtype 引數指定後會將結果強制轉換成 dtype 指定的型別,如果是 float 轉 int,最終值就可能不是等差的了。
import numpy as np
a = np.linspace(0, 10, 5, dtype=int)
print(a)
複製程式碼
輸出:
[ 0 2 5 7 10]
複製程式碼
3、numpy.logspace
numpy.logspace
函式用於建立一個等比數列。
numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
複製程式碼
引數 | 描述 |
---|---|
start | 序列的起始值為:base ** start (冪運算) |
stop | 序列的終止值為:base ** stop 。如果 endpoint 為 True,該值包含於數列中 |
num | 要生成的等步長的樣本數量,預設為50 |
endpoint | 該值為 Ture 時,數列中中包含 stop 值,反之不包含,預設是 True。 |
base | 對數 log 的底數。 |
dtype | ndarray 的資料型別 |
示例:
其實沒啥好說的,主要是注意 start 引數的值並非是真正的起始值。
import numpy as np
a = np.logspace(1, 4, num=4)
print(a)
複製程式碼
輸出:
[ 10. 100. 1000. 10000.]
複製程式碼
4、numpy.geomspace
建立一個一維等比數列。
numpy.geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0)
複製程式碼
引數 | 描述 |
---|---|
start | 序列的起始值 |
stop | 序列的終止值,如果 endpoint 為 True,該值包含於數列中 |
num | 要生成的樣本數量,預設為 50 |
endpoint | 該值為 Ture 時,數列中中包含 stop 值,反之不包含,預設是 True。 |
dtype | ndarray 的資料型別 |
axis | 1.16.0 版本中的新功能 ,沒看懂怎麼用,官網上連個例子都沒有,值為 0 和 -1 的時候結果相同,其他時候都報錯。 |
示例:
import numpy as np
a = np.geomspace(1, 8, num=4)
print(a)
複製程式碼
輸出:
[1. 2. 4. 8.]
複製程式碼
NumPy 從已有的陣列建立陣列
1、numpy.asarray
numpy.asarray
類似 numpy.array
,但 numpy.asarray
的引數只有三個。
numpy.asarray(a, dtype=None, order=None)
複製程式碼
引數 | 描述 |
---|---|
a | 輸入資料,可以轉換為陣列的任何形式。 這包括列表,元組列表,元組,元組元組,列表元組和 ndarray。 |
dtype | 資料型別 |
order | 在計算機記憶體中的儲存元素的順序,只支援 'C'(按行)、'F'(按列),預設 'C' |
示例:
import numpy as np
a = np.asarray([1, 2, 3])
print(a)
複製程式碼
輸出:
[1 2 3]
複製程式碼
2、numpy.frombuffer
numpy.frombuffer
用於實現動態陣列。numpy.frombuffer
接受 buffer 輸入引數,以流的形式讀入轉化成 ndarray 物件。
numpy.frombuffer(buffer, dtype=float, count=-1, offset=0)
複製程式碼
引數 | 描述 |
---|---|
buffer | 實現了 __buffer__ 方法的物件,(絕對不是菜鳥教程上說的任意物件都可以) |
dtype | 返回陣列的資料型別 |
count | 讀取的資料數量,預設為 -1,讀取所有資料。 |
offset | 讀取的起始位置,預設為 0。 |
例一: buffer 是字串的時候,Python3 預設 str 是 Unicode 型別,所以要轉成 bytestring 在原 str 前加上 b。
import numpy as np
a = np.frombuffer(b'Hello World', dtype='S1')
print(a)
複製程式碼
輸出:
[b'H' b'e' b'l' b'l' b'o' b' ' b'W' b'o' b'r' b'l' b'd']
複製程式碼
例二: 看了上面的例子,似乎對“實現動態陣列”沒啥感覺,那麼我們來看這個例子。
import numpy as np
import array
a = array.array('i', [1, 2, 3, 4])
print(a)
na = np.frombuffer(a, dtype=np.int_)
print(na)
a[0] = 10
print(a)
print(na)
複製程式碼
輸出:
array('i', [1, 2, 3, 4])
[1 2 3 4]
array('i', [10, 2, 3, 4])
[10 2 3 4]
複製程式碼
array.array
建立的陣列物件記憶體是連續的(這裡不能用 list,會報:AttributeError: 'list' object has no attribute '__buffer__
'),numpy.frombuffer
從 array.array
的記憶體中建立陣列,從上例中可以看出,改變 array.array
的值,numpy.frombuffer
的值也會跟著改變,由此可見。
例三:
array.array
陣列中的值改變是可以的,但是如果是新增值,那就不行了。
import numpy as np
import array
a = array.array("i", [1, 2, 3, 4])
na = np.frombuffer(a, dtype=int)
print(na)
a.append(5)
print(na)
複製程式碼
輸出:
[1 2 3 4]
[140896288 381 3 4]
複製程式碼
3、numpy.fromiter
numpy.fromiter
方法從可迭代物件中建立 ndarray 物件,返回一維陣列。
numpy.fromiter(iterable, dtype, count=-1)
複製程式碼
引數 | 描述 |
---|---|
iterable | 可迭代物件 |
dtype | 返回陣列的資料型別 |
count | 讀取的資料數量,預設為 -1,讀取所有資料 |
例一:
import numpy as np
iterable = (x * x for x in range(5))
a = np.fromiter(iterable, int)
print(a)
複製程式碼
輸出:
[ 0 1 4 9 16]
複製程式碼
看起來有點像
numpy.array
,array
方法需要傳入的是一個 list,而fromiter
可以傳入可迭代物件。
例二:
將上例換成 array
試試看。
import numpy as np
iterable = (x * x for x in range(5))
a = np.array(iterable)
print(a)
複製程式碼
輸出:
<generator object <genexpr> at 0x000000001442DD00>
複製程式碼
4、empty_like
返回一個與給定陣列具有相同維度和型別的未初始化的新陣列。
numpy.empty_like(prototype, dtype=None, order='K', subok=True)
複製程式碼
引數 | 描述 |
---|---|
prototype | 給定的陣列 |
dtype | 覆蓋結果的資料型別,版本1.6.0中的新功能。 |
order | 指定陣列的記憶體佈局。C(按行)、F(按列)、A(原順序)、K(元素在記憶體中的出現順序) |
subok | 預設情況下,返回的陣列被強制為基類陣列。 如果為 True,則返回子類。 |
示例:
import numpy as np
a = np.empty_like([[1, 2, 3], [4, 5, 6]])
print(a)
複製程式碼
輸出:*
[[870 0 0]
[ 0 0 0]]
複製程式碼
5、zeros_like
numpy.zeros_like(a, dtype=None, order='K', subok=True)
複製程式碼
引數同上。
示例:
import numpy as np
a = np.zeros_like([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
print(a)
複製程式碼
輸出:*
[[0. 0. 0.]
[0. 0. 0.]]
複製程式碼
6、ones_like
numpy.ones_like(a, dtype=None, order='K', subok=True)
複製程式碼
引數同上。
示例:
import numpy as np
a = np.ones_like([[1, 2, 3], [4, 5, 6]])
print(a)
複製程式碼
輸出:*
[[1 1 1]
[1 1 1]]
複製程式碼
7、numpy.full_like
返回與給定陣列具有相同維度和型別的並以 fill_value 填充的陣列。
numpy.full_like(a, fill_value, dtype=None, order='K', subok=True)
複製程式碼
引數 | 描述 |
---|---|
a | 給定的陣列 |
fill_value | 填充值 |
dtype | 返回陣列的資料型別,預設值 None,則使用給定陣列的型別 |
order | 指定陣列的記憶體佈局。C(按行)、F(按列)、A(原順序)、K(元素在記憶體中的出現順序) |
subok | 預設情況下,返回的陣列被強制為基類陣列。 如果為 True,則返回子類。 |
zeros_like、ones_like 其實都是此方法的特例。
示例:
import numpy as np
x = np.arange(6, dtype=int)
print(x)
print('-------------------')
a = np.full_like(x, 1)
b = np.full_like(x, 0.1)
c = np.full_like(x, 0.1, dtype=np.double)
print(a)
print(b)
print(c)
複製程式碼
輸出:
[0 1 2 3 4 5]
-------------------
[1 1 1 1 1 1]
[0 0 0 0 0 0]
[0.1 0.1 0.1 0.1 0.1 0.1]
複製程式碼