關(guān)于numpy的使用和一些問(wèn)題解答(Python)
Table of Contents
1??
numpy
?= Numerical Python 數(shù)值計(jì)算用的Python2??多維數(shù)組
ndarray
3??
ndarray
?上手4??
ndarray
中標(biāo)量 scalar 的數(shù)據(jù)類(lèi)型對(duì)象?dtype
5??數(shù)組的維度與軸 Axis
5.1??改變
ndarray
的形狀5.2??加入新的軸
5.3??問(wèn)題
6??數(shù)組的基本索引
6.1??返回一個(gè)標(biāo)量
6.2??返回一個(gè)
ndarray
6.3??多維索引
6.4??更新
ndarray
7??進(jìn)階索引
7.1??整數(shù)數(shù)組索引
7.2??與基本索引混合
7.3??條件索引 Boolean Masking
7.4??問(wèn)題
numpy
?= Numerical Python 數(shù)值計(jì)算用的Python
什么是 NumPy?
NumPy是一個(gè)功能強(qiáng)大的Python庫(kù),主要用于對(duì)多維數(shù)組執(zhí)行計(jì)算。NumPy這個(gè)詞來(lái)源于兩個(gè)單詞-- Numerical和Python。NumPy提供了大量的庫(kù)函數(shù)和操作,可以幫助程序員輕松地進(jìn)行數(shù)值計(jì)算。這類(lèi)數(shù)值計(jì)算廣泛用于以下任務(wù):
機(jī)器學(xué)習(xí)模型:在編寫(xiě)機(jī)器學(xué)習(xí)算法時(shí),需要對(duì)矩陣進(jìn)行各種數(shù)值計(jì)算。例如矩陣乘法、換位、加法等。NumPy提供了一個(gè)非常好的庫(kù),用于簡(jiǎn)單(在編寫(xiě)代碼方面)和快速(在速度方面)計(jì)算。NumPy數(shù)組用于存儲(chǔ)訓(xùn)練數(shù)據(jù)和機(jī)器學(xué)習(xí)模型的參數(shù)。
圖像處理和計(jì)算機(jī)圖形學(xué):計(jì)算機(jī)中的圖像表示為多維數(shù)字?jǐn)?shù)組。NumPy成為同樣情況下最自然的選擇。實(shí)際上,NumPy提供了一些優(yōu)秀的庫(kù)函數(shù)來(lái)快速處理圖像。例如,鏡像圖像、按特定角度旋轉(zhuǎn)圖像等。
數(shù)學(xué)任務(wù):NumPy對(duì)于執(zhí)行各種數(shù)學(xué)任務(wù)非常有用,如數(shù)值積分、微分、內(nèi)插、外推等。因此,當(dāng)涉及到數(shù)學(xué)任務(wù)時(shí),它形成了一種基于Python的MATLAB的快速替代。
多維數(shù)組ndarray
NumPy主要由?多維數(shù)組ndarray
?一個(gè)用來(lái)儲(chǔ)存同一種數(shù)據(jù)類(lèi)型的有序容器, 和用來(lái)操縱ndarry
的函數(shù)組成.?ndarray
是NumPy核心概念.
ndarray
中的元素的可以是整數(shù), 浮點(diǎn)數(shù), 固定長(zhǎng)度的字符串, 等等, 還可以是任何Python對(duì)象的reference(并不儲(chǔ)存對(duì)象本身). 這些元素稱(chēng)為標(biāo)量 scalar.ndarrays
?是同質(zhì)的?:即其所有元素在內(nèi)存中占據(jù)了同樣的大小. 每一個(gè)元素的數(shù)據(jù)類(lèi)型對(duì)象dtype
是一樣的.ndarray
中的元素可以用整數(shù)(位置)來(lái)索引. 這和list
很像, 但ndarray
可以是多維的 (有多個(gè)軸?axis
)
一個(gè)ndarray
在計(jì)算機(jī)內(nèi)存中由兩個(gè)部分組成
組成了
ndarray
的標(biāo)量們 (scalars)ndarray
的頭文件, 定義了數(shù)值中標(biāo)量們唯一的數(shù)據(jù)類(lèi)型
ndarray
?上手
使用?import
?來(lái)調(diào)用 pacakage.
調(diào)用?numpy
. 將 numpy 簡(jiǎn)稱(chēng)為 np.
1import numpy as np2a = np.array([[1,2,3,4,5],[2,3,4,5,6]],dtype=int)1a[27]:array([[1, 2, 3, 4, 5], , ? ? ? [2, 3, 4, 5, 6]])1a.shape2a.ndim3a.dtype[28]:dtype('int64')
調(diào)用numpy中的一個(gè)常數(shù)(constant)來(lái)檢查 numpy的版本
1np.__version__[5]:'1.19.4'
使用np.array()
或者?np.asarray()
來(lái)建立?ndarray
1a = np.array([1, 2, 3]) ? # Create a 1d array2a[6]:array([1, 2, 3])1a = np.asarray([1, 2, 3])2a[7]:array([1, 2, 3])1print(type(a)) ? ? ? ? ? ?# Prints "<class 'numpy.ndarray'>"2print(a.shape) ? ? ? ? ? ?# Prints "(3,)"3print(a.ndim)4print(a.dtype)5print(a[0], a[1], a[2]) ? # Prints "1 2 3"6a[0] = 5 ? ? ? ? ? ? ? ? ?# Change an element of the array7print(a) ? ? ? ? ? ? ? ? ?# Prints "[5, 2, 3]"<class 'numpy.ndarray'> (3,) 1 int64 1 2 3 [5 2 3]
調(diào)用?ndarray
?的 屬性(attribute)shape
?來(lái)查看它的形狀
ndarray
中標(biāo)量 scalar 的數(shù)據(jù)類(lèi)型對(duì)象?dtype
ndarray
中的元素的可以是整數(shù), 浮點(diǎn)數(shù), 字符串, 等等, 還可以是任何Python對(duì)象的reference(并不儲(chǔ)存對(duì)象本身). 與數(shù)組對(duì)應(yīng), 這些元素統(tǒng)稱(chēng)為標(biāo)量 scalar.
以下是這些標(biāo)量的數(shù)據(jù)類(lèi)型對(duì)象之間的繼承關(guān)系:
對(duì)象類(lèi)型?np.object_
object_
?任何Python對(duì)象的reference, 而非對(duì)象本身. 但是在使用時(shí)會(huì)返回這個(gè)對(duì)象本身
數(shù)字類(lèi)型?np.number
?NumPy比Python有更豐富的數(shù)字類(lèi)型
bool_
?布爾型數(shù)據(jù)類(lèi)型(True 或者 False)int_
?默認(rèn)的整數(shù)類(lèi)型(類(lèi)似于 C 語(yǔ)言中的 long,int32 或 int64)intc
?與 C 的 int 類(lèi)型一樣,一般是 int32 或 int 64intp
?用于索引的整數(shù)類(lèi)型(類(lèi)似于 C 的 ssize_t,一般情況下仍然是 int32 或 int64)int8
?字節(jié)(-128 to 127)int16
?整數(shù)(-32768 to 32767)int32
?整數(shù)(-2147483648 to 2147483647)int64
?整數(shù)(-9223372036854775808 to 9223372036854775807)uint8
?無(wú)符號(hào)整數(shù)(0 to 255)uint16
?無(wú)符號(hào)整數(shù)(0 to 65535)uint32
?無(wú)符號(hào)整數(shù)(0 to 4294967295)uint64
?無(wú)符號(hào)整數(shù)(0 to 18446744073709551615)float_
?float64 類(lèi)型的簡(jiǎn)寫(xiě)float16
?半精度浮點(diǎn)數(shù),包括:1 個(gè)符號(hào)位,5 個(gè)指數(shù)位,10 個(gè)尾數(shù)位float32
?單精度浮點(diǎn)數(shù),包括:1 個(gè)符號(hào)位,8 個(gè)指數(shù)位,23 個(gè)尾數(shù)位float64
?雙精度浮點(diǎn)數(shù),包括:1 個(gè)符號(hào)位,11 個(gè)指數(shù)位,52 個(gè)尾數(shù)位
(指數(shù)位決定范圍,尾數(shù)位決定精度)complex_
?complex128 類(lèi)型的簡(jiǎn)寫(xiě),即 128 位復(fù)數(shù)complex64
?復(fù)數(shù),表示雙 32 位浮點(diǎn)數(shù)(實(shí)數(shù)部分和虛數(shù)部分)complex128
?復(fù)數(shù),表示雙 64 位浮點(diǎn)數(shù)(實(shí)數(shù)部分和虛數(shù)部分)
額外閱讀:?https://www.numpy.org.cn/user_guide/numpy_basics/data_types.html
字符類(lèi)型?np.character
str_
?字符串?unicode_
?unicode字符串, 默認(rèn)是UTF8, 支持中文
它們的方法和屬性與Python原生的str
一致
額外閱讀:?https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.char.html
NumPy標(biāo)量與Python的基本數(shù)據(jù)類(lèi)型
有些標(biāo)量的數(shù)據(jù)類(lèi)型對(duì)象dtype
與Python中的基本數(shù)據(jù)類(lèi)型對(duì)象int, float, str, bool
概念上是一樣的, 兩者也可以很容易地互相轉(zhuǎn)換和比較數(shù)值大小, 但是他們是不同的對(duì)象.
比如Python的int
?42
?存入ndarray
以后就變成了numpy.int32
對(duì)象. 由于它是一個(gè)Numpy標(biāo)量, 它有一個(gè)dtype
屬性, 其值為int32
.
盡管它是Numpy標(biāo)量, 但依然可以和int
比較和做運(yùn)算
Q.?s1[0]
,?s2[0]
和s2[1]
的類(lèi)型是什么?
s1 = np.array(['a', 'abc']) s2 = np.array([u'a', 'abc'])
1s1 = np.array(['a', 'abc'])2type(s1[0])[25]:numpy.str_1s1.dtype[27]:dtype('<U3')1s1[0].dtype[26]:dtype('<U1')1s2 = np.array([u'a', 'abc'])2s2.dtype, s2[0].dtype, s2[1].dtype[28]:(dtype('<U3'), dtype('<U1'), dtype('<U3'))
數(shù)據(jù)類(lèi)型的轉(zhuǎn)換
1c = np.array([1, 2, 3], dtype=float)2c.dtype[29]:dtype('float64')1c[30]:array([1., 2., 3.])1c.astype(np.int8).dtype[16]:dtype('int8')1c.astype(np.int8)[31]:array([1, 2, 3], dtype=int8)
overflow
默認(rèn)數(shù)據(jù)類(lèi)型為np.float_
1a = np.ones((3, 3))2a.dtype, a[35]:(dtype('float64'), array([[1., 1., 1.], , ? ? ? ?[1., 1., 1.], , ? ? ? ?[1., 1., 1.]]))
數(shù)組的維度與軸 Axis
ndarray
的維度ndim
即指明了其軸的數(shù)量
0軸定義為"最里面的"那個(gè)一維數(shù)組
1import numpy as np23a = np.array([[1,2],[3,4],[5,6]])4a[42]:array([[1, 2], , ? ? ? [3, 4], , ? ? ? [5, 6]])1from PIL import Image2import numpy as np3im_row = Image.open('1.jpg')4im = Image.open('1.jpg').convert('L')5im_row = np.asarray(im_row)6im = np.array(im)7im.shape8im.ndim9im.dtype10im_row.shape[73]:(300, 390, 3)1im[260,289] = 255 1import matplotlib.pyplot as plt2plt.imshow(im,cmap='gray')3# plt.imshow(im_row)[75]:<matplotlib.image.AxesImage at 0x7f2c2834fb70>
0軸上有3個(gè)長(zhǎng)度為2的一維數(shù)組, 1軸上有2個(gè)長(zhǎng)度為3的一維數(shù)組
1a.shape[43]:(3, 2)
這是3個(gè)長(zhǎng)度為2的一維數(shù)組之和, 即0軸上有3個(gè)長(zhǎng)度為2的一維數(shù)組
1np.sum(a, axis=0)[26]:array([ 9, 12])
這是2個(gè)長(zhǎng)度為3的一維數(shù)組之和, 即1軸上有2個(gè)長(zhǎng)度為3的一維數(shù)組
1np.sum(a, axis=1)[27]:array([ 3, ?7, 11])
等間距的數(shù)組
1# np.arange(10) # 0 .. n-1 ?(!)2a = np.arange(0,255,1)3# start,end,4b = a.reshape(5,51)5b[1,34] = 2556plt.imshow(b)1np.arange(1, 9, 2) # start, end (exclusive), step[10]:array([1, 3, 5, 7])
指定元素個(gè)數(shù)的數(shù)組
1np.linspace(0, 1, 6) ? # start, end, num-points[11]:array([0. , 0.2, 0.4, 0.6, 0.8, 1. ])1np.linspace(0, 1, 5, endpoint=False)[12]:array([0. , 0.2, 0.4, 0.6, 0.8])
改變ndarray
的形狀
一維數(shù)據(jù)結(jié)構(gòu)
1np.arange(12).shape[28]:(12,)
通過(guò)reshape, 將一維數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)成了3××4的矩陣
1M = np.arange(12).reshape(3,4)2M[62]:array([[ 0, ?1, ?2, ?3], , ? ? ? [ 4, ?5, ?6, ?7], , ? ? ? [ 8, ?9, 10, 11]])1M[2][1] = 82M[2,1][92]:81M[1, 1] = -92M[70]:array([[ 0, ?1, ?2, ?3], , ? ? ? [ 4, -9, ?6, ?7], , ? ? ? [ 8, ?8, 10, 11]])
數(shù)組的基本索引
基本索引返回的的原數(shù)組的另外一個(gè)視角(view)而非一個(gè)新的數(shù)組
view:?https://docs.scipy.org/doc/numpy-1.13.0/glossary.html#term-view
額外閱讀:?https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html#basic-slicing-and-indexing
返回一個(gè)標(biāo)量
ndarray
支持所有list
的索引方式,?-1
?-3
返回最后一個(gè)和倒數(shù)第三個(gè)
1a=[1,2,3]2a[-1][67]:31import numpy as np2a = np.arange(10)3a, a[0], a[2], a[-1], a[-3][38]:(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), 0, 2, 9, 7)
對(duì)角矩陣
1a = np.diag(np.arange(3))2a[39]:array([[0, 0, 0], , ? ? ? [0, 1, 0], , ? ? ? [0, 0, 2]])
一維索引, 在0軸上 (axis=0).?ndarray
中, 0軸定義為最里面的那個(gè)一維數(shù)組
1a[1][40]:array([0, 1, 0])
多維索引
1M[1, 1][65]:5
更新索引位置對(duì)應(yīng)的值
1a[2, 1] = 10 # third line, second column2a[42]:array([[ 0, ?0, ?0], , ? ? ? [ 0, ?1, ?0], , ? ? ? [ 0, 10, ?2]])
返回一個(gè)ndarray
切割會(huì)返回一個(gè)ndarray
, 而不是一個(gè)標(biāo)量
生成一個(gè)ndarray
, 注意如果寫(xiě)了指代位置的數(shù)字, 其定義的區(qū)間是前閉后開(kāi)的
1np.arange(0, 10, 1)[68]:array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])1a = np.arange(10)2a[69]:array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
使用range
, 從index為2的元素開(kāi)始(包含), 至最后一個(gè), 注意如果寫(xiě)了指代位置的數(shù)字, 其定義的區(qū)間是前閉后開(kāi)的
1a[2:][70]:array([2, 3, 4, 5, 6, 7, 8, 9])
從第一個(gè), 至index為9的位置(不包含), 注意如果寫(xiě)了指代位置的數(shù)字, 其定義的區(qū)間是前閉后開(kāi)的
1a[:9][46]:array([0, 1, 2, 3, 4, 5, 6, 7, 8])
Q.?a[2:9:2], a[1:3], a[::2], a[3:]
?返回的結(jié)果分別是什么?
hint?[start=0: stop=len(a): step=1]
?和?range
?一樣
1a[2:9:2], a[1:3], a[::2], a[3:][75]:(array([2, 4, 6, 8]), , array([1, 2]), , array([0, 2, 4, 6, 8]), , array([3, 4, 5, 6, 7, 8, 9]))
更新ndarray
要更新一個(gè)ndarray
中的值, 我們只需對(duì)該ndarray
做索引, 并對(duì)結(jié)果"賦值". 可以使用一個(gè)標(biāo)量更新, 也可以使用另一個(gè)ndarray
更新, 但需要注意形狀shape
和dtype
是否匹配.
1a = np.arange(10)2a[5:] = 103a[78]:array([ 0, ?1, ?2, ?3, ?4, 10, 10, 10, 10, 10])1b = np.arange(5)2a[5:] = b[::-1]3a[93]:array([0, 1, 2, 3, 4, 4, 3, 2, 1, 0])1M = np.arange(6) + np.arange(0, 51, 10)[:, np.newaxis]2M[80]:array([[ 0, ?1, ?2, ?3, ?4, ?5], , ? ? ? [10, 11, 12, 13, 14, 15], , ? ? ? [20, 21, 22, 23, 24, 25], , ? ? ? [30, 31, 32, 33, 34, 35], , ? ? ? [40, 41, 42, 43, 44, 45], , ? ? ? [50, 51, 52, 53, 54, 55]])1M[2::2, :] = 02# 開(kāi)始,結(jié)束,間隔3M[84]:array([[ 0, ?1, ?2, ?3, ?4, ?5], , ? ? ? [10, 11, 12, 13, 14, 15], , ? ? ? [ 0, ?0, ?0, ?0, ?0, ?0], , ? ? ? [30, 31, 32, 33, 34, 35], , ? ? ? [ 0, ?0, ?0, ?0, ?0, ?0], , ? ? ? [50, 51, 52, 53, 54, 55]])
注意形狀?shape
1M[2::2, :] = np.arange(12).reshape(2,6)2M[95]:array([[ 0, ?1, ?2, ?3, ?4, ?5], , ? ? ? [10, 11, 12, 13, 14, 15], , ? ? ? [ 0, ?1, ?2, ?3, ?4, ?5], , ? ? ? [30, 31, 32, 33, 34, 35], , ? ? ? [ 6, ?7, ?8, ?9, 10, 11], , ? ? ? [50, 51, 52, 53, 54, 55]])
Q. 為什么在更新后的M
中, 對(duì)應(yīng)的位置仍是整數(shù)? 而N
則是浮點(diǎn)數(shù)
1np.linspace(0,10,12)[58]:array([ 0. ? ? ? ?, ?0.90909091, ?1.81818182, ?2.72727273, ?3.63636364, , ? ? ? ?4.54545455, ?5.45454545, ?6.36363636, ?7.27272727, ?8.18181818, , ? ? ? ?9.09090909, 10. ? ? ? ?])1M[2::2, :] = np.linspace(0,10,12).reshape(2,6)2M[59]:array([[ 0, ?1, ?2, ?3, ?4, ?5], , ? ? ? [10, 11, 12, 13, 14, 15], , ? ? ? [ 0, ?0, ?1, ?2, ?3, ?4], , ? ? ? [30, 31, 32, 33, 34, 35], , ? ? ? [ 5, ?6, ?7, ?8, ?9, 10], , ? ? ? [50, 51, 52, 53, 54, 55]])
復(fù)制
1M[85]:array([[ 0, ?1, ?2, ?3, ?4, ?5], , ? ? ? [10, 11, 12, 13, 14, 15], , ? ? ? [ 0, ?0, ?0, ?0, ?0, ?0], , ? ? ? [30, 31, 32, 33, 34, 35], , ? ? ? [ 0, ?0, ?0, ?0, ?0, ?0], , ? ? ? [50, 51, 52, 53, 54, 55]])1N = M.copy()2X = M.view()3N[2,1] = 234N5# N = N.astype(np.float_)6# N[2::2, :] = np.linspace(0,10,12).reshape(2,6)7# N[97]:array([[ 0, ?1, ?2, ?3, ?4, ?5], , ? ? ? [10, 11, 12, 13, 14, 23], , ? ? ? [ 0, 23, ?0, 23, ?0, ?0], , ? ? ? [30, 31, 32, 33, 34, 35], , ? ? ? [ 0, ?0, ?0, ?0, ?0, ?0], , ? ? ? [50, 51, 52, 53, 54, 55]])
進(jìn)階索引
與基本索引不同, 進(jìn)階索引總是會(huì)返回一個(gè)新的數(shù)組, 而非原數(shù)組的視圖, 但更新操作與基本索引無(wú)異
額外閱讀:?https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html#advanced-indexing
條件索引 Boolean Masking
1np.random.seed(42)2a = np.random.randint(0, 21, 15)3a[98]:array([ 6, 19, 14, 10, ?7, 20, ?6, 18, 10, 10, 20, ?3, ?7, ?2, 20])1c = a % 3 == 02c.dtype3print(c)4a[c][ True False False False False False ?True ?True False False False ?True ?False False False] [102]:array([ 6, ?6, 18, ?3])1mask = (a % 3 == 0)2a[mask] # or, ?a[a%3==0], extract a sub-array with the mask[73]:array([ 6, ?6, 18, ?3])