<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          詳解NumPy庫(kù),強(qiáng)大的Python科學(xué)計(jì)算包

          共 8157字,需瀏覽 17分鐘

           ·

          2022-01-14 22:59

          哈嘍,大家好。

          之前寫了幾篇 Python 基礎(chǔ)的文章,效果不錯(cuò)。為感謝大家的支持,月底搞一波抽獎(jiǎng)送書活動(dòng)。

          閑話少敘,今天來(lái)詳解一個(gè) Python 庫(kù) —— NumPy

          NumPy是 Python 科學(xué)計(jì)算的基本包,幾乎所有用 Python 工作的科學(xué)家都利用了NumPy的強(qiáng)大功能。此外,它也廣泛應(yīng)用在開(kāi)源的項(xiàng)目中,如:PandasSeabornMatplotlibscikit-learn等。

          Numpy應(yīng)用的領(lǐng)域

          舉個(gè)栗子,直觀感下NumPy的強(qiáng)大。

          均方差公式

          上圖是計(jì)算均方差的公式,其中Y_predictionY是數(shù)組。

          下面是用NumPy代碼,一行便可完成。

          NumPy計(jì)算均方差

          NumPy結(jié)合可視化庫(kù),可以用幾行代碼,繪制出下面的數(shù)學(xué)函數(shù)圖

          記得學(xué)高中學(xué)數(shù)學(xué)的時(shí)候,畫函數(shù)圖都要自己在本上描點(diǎn),而現(xiàn)在用NumPy,幾行代碼就搞定,既快又準(zhǔn)確。

          簡(jiǎn)單認(rèn)識(shí)NumPy后,下面進(jìn)入詳解

          1. 與list的區(qū)別

          NumPylist都是數(shù)組結(jié)構(gòu),那它們之間有什么區(qū)別呢?

          1. NumPy數(shù)組中所有元素的數(shù)據(jù)類型是相同的。

          2. NumPy底層經(jīng)過(guò)充分優(yōu)化的 C 語(yǔ)言代碼,計(jì)算性能比list高。

          3. NumPy提供了全面的數(shù)學(xué)函數(shù)可以直接應(yīng)用在NumPy數(shù)組上。

          2. 創(chuàng)建數(shù)組

          NumPy中定義的數(shù)組叫ndarray,n-dimensions-array 即:n維數(shù)組

          np.array()函數(shù)可以創(chuàng)建NumPy數(shù)組

          >>>?import?numpy?as?np
          >>>?a?=?np.array([1,?2,?3])?#創(chuàng)建ndarray數(shù)組
          >>>?a
          array([1,?2,?3])
          >>>?type(a)
          <class?'numpy.ndarray'>

          a就是NumPy數(shù)組,也是numpy.ndarray類對(duì)象,該類定義了幾個(gè)常用的屬性

          • ndarray.ndim:維度的數(shù)量,二位數(shù)組ndim是 2
          • ndarray.shape:元組,每位代表該維度上元素個(gè)數(shù),元組長(zhǎng)度等于ndim
          • ndarray.size:數(shù)組中元素總數(shù)
          • ndarray.dtype:數(shù)組中元素的數(shù)據(jù)類型
          • ndarray.itemsize:數(shù)組中元素存儲(chǔ)大小(以字節(jié)為單位)
          >>>?a?=?np.array([[1,2,3],?[4,5,6]])
          >>>?a
          array([[1,?2,?3],
          ???????[4,?5,?6]])
          >>>?a.ndim
          2
          >>>?a.shape
          (2,?3)
          >>>?a.size
          6
          >>>?a.dtype
          dtype('int64')
          >>>?a.itemsize
          8

          除了np.array()創(chuàng)建數(shù)組外,還有下面的方式創(chuàng)建數(shù)組

          >>>?np.zeros((2,3))?#?以0填充的二維數(shù)組
          array([[0.,?0.,?0.],
          ???????[0.,?0.,?0.]])
          >>>?np.ones((2,3))?#?以1填充的二維數(shù)組
          array([[1.,?1.,?1.],
          ???????[1.,?1.,?1.]])
          >>>?np.empty((2,3))?#?空的二維數(shù)組,內(nèi)容為當(dāng)時(shí)內(nèi)存中的值
          array([[1.,?1.,?1.],
          ???????[1.,?1.,?1.]])
          >>>?np.arange(6)?#?用法跟range函數(shù)一樣
          array([0,?1,?2,?3,?4,?5])
          >>>?np.linspace(0,?10,?num=5)?#?以指定的線性間隔為初值,創(chuàng)建數(shù)組
          array([?0.?,??2.5,??5.?,??7.5,?10.?])
          >>>?rng?=?np.random.default_rng(0)?#?以隨機(jī)數(shù)創(chuàng)建二維數(shù)組
          >>>?rng.random((2,3))
          array([[0.63696169,?0.26978671,?0.04097352],
          ???????[0.01652764,?0.81327024,?0.91275558]])

          3. 訪問(wèn)數(shù)組

          支持索引切片。格式為:

          arr[i, j, k, ...],i, j, k分別代表數(shù)組第0維、第1維、第2維

          其中,i, j, k的格式為:

          s1:s2:s3,分別代表開(kāi)始下標(biāo),結(jié)束下標(biāo)和步長(zhǎng)

          步長(zhǎng)s3不填時(shí),第二個(gè)冒號(hào)可省略,步長(zhǎng)為1。

          以一個(gè)3維數(shù)組為例

          >>>?#?創(chuàng)建?5*4?二維數(shù)組(5行4列)
          >>>?c?=?np.array([[?0,??1,??2,??3],?[10,?11,?12,?13],?[20,?21,?22,?23],?[30,?31,?32,?33],?[40,?41,?42,?43]])
          >>>?c
          array([[?0,??1,??2,??3],
          ???????[10,?11,?12,?13],
          ???????[20,?21,?22,?23],
          ???????[30,?31,?32,?33],
          ???????[40,?41,?42,?43]])
          >>>?c.shape
          (5,?4)
          >>>?#?按照索引取?第1行,第2列的元素
          >>>?c[1,?2]
          12
          >>>?#?切片,取?1~2?行,第2列的元素(數(shù)組)
          >>>?c[1:3,?2]
          array([12,?22])
          >>>?#?切片,取?1~2?行,第2~3列元素(數(shù)組)
          >>>?c[1:3,?2:4]
          array([[12,?13],
          ???????[22,?23]])
          >>>?#?步長(zhǎng)=2,取到第?1,?3?行,第2~3列元素
          >>>?c[1:6:2,?2:4]
          array([[12,?13],
          ???????[32,?33]])

          如果取最后一維,下標(biāo)為2的元素,可以按照下面方式取

          >>>?c[:,2]
          array([?2,?12,?22,?32,?42])

          如果維度比較多,需要寫很多:NumPy提供...可以代表之前或之后的任意維度

          >>>?c[...,2]
          array([?2,?12,?22,?32,?42])

          取第0維的寫法也是一樣的。


          4. 運(yùn)算(四則運(yùn)算和函數(shù))

          NumPy數(shù)組支持四則運(yùn)算,它會(huì)將兩個(gè)數(shù)組相同位置的數(shù)值進(jìn)行加減乘除,生成新的數(shù)組。

          >>>?data?=?np.array([1,?2])
          >>>?ones?=?np.ones(2,?dtype=int)
          >>>?data?+?ones
          array([2,?3])
          NumPy數(shù)組相加

          除了基本的四則運(yùn)算符,還支持+=-=*=/=增量賦值運(yùn)算符,可修改原數(shù)組的值。

          除了運(yùn)算符NumPy中還提供了一些函數(shù)用于快速計(jì)算數(shù)組中的值。如summinmaxmean等。

          >>>?a?=?np.array([[1,2,3],[4,5,6]])
          >>>?np.sum(a)
          21

          上面例子中np.sum()函數(shù)對(duì)二維數(shù)組中所有元素求和。

          這類函數(shù)不光可以對(duì)所有元素做計(jì)算,還支持按照指定維度計(jì)算。如:

          >>>?#?按照第0維相加(行相加)
          >>>?a.sum(axis=0)
          array([5,?7,?9])
          >>>?#?按照第1維相加(列相加)
          >>>?a.sum(axis=1)
          array([?6,?15])

          參數(shù)axis指定對(duì)第幾維做計(jì)算,在NumPy經(jīng)常會(huì)用到這個(gè)參數(shù)。

          很多教程,包括官網(wǎng)文檔,直接告訴讀者axis=0代表按行計(jì)算,axis=1代表按列計(jì)算。

          我覺(jué)得這樣說(shuō)有局限性,一來(lái)容易記混,二來(lái)如果是三維或者更高維誰(shuí)是行,誰(shuí)又是列呢。

          所以,我覺(jué)得干脆不要記行、列,只要記住axis的取值就是第幾維就好了。

          比如,在三維數(shù)組的各維度運(yùn)用np.sum()

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

          ???????[[?7,??8,??9],
          ????????[10,?11,?12]]])
          >>>?a.shape
          (2,?2,?3)

          按第0維相加

          >>>?a.sum(axis=0)
          array([[?8,?10,?12],
          ???????[14,?16,?18]])

          第0維里面有兩個(gè)元素,每個(gè)元素都是二維數(shù)組,按照第0維相加就是將這倆二維數(shù)組相加,即:[[ 1, 2, 3],[ 4, 5, 6]] + [ 7, 8, 9],[10, 11, 12]]。上面說(shuō)了,NumPy數(shù)組相加,相同位置的數(shù)值直接相加即可,得到就是上面的結(jié)果。

          按第1維相加

          >>>?a.sum(axis=1)
          array([[?5,??7,??9],
          ???????[17,?19,?21]])

          第1維共有4個(gè)一維數(shù)組,但由于處在兩個(gè)第0維元素中,所以要分別計(jì)算,即:[ 1, 2, 3] + [ 4, 5, 6][ 7, 8, 9] + [10, 11, 12],最終返回兩個(gè)一維數(shù)組。

          按第2維相加

          >>>?a.sum(axis=2)
          array([[?6,?15],
          ???????[24,?33]])

          第2維是最內(nèi)層的數(shù)字,直接將數(shù)字相加即可。得到 4 個(gè)數(shù)字。

          按照這種方式去推導(dǎo)每一維的計(jì)算邏輯才是最容易理解的,而不是教條的去記是行或者列。

          5. 廣播

          上面的運(yùn)算中,運(yùn)算符兩邊的數(shù)組都是相同維度的。

          而實(shí)際中,可能會(huì)有不同維度的數(shù)組相加減,這時(shí)候NumPy會(huì)自動(dòng)將兩邊的數(shù)組維度調(diào)整相同后,再做計(jì)算,這個(gè)過(guò)程就叫廣播

          >>>?data?=?np.array([1.0,?2.0])
          >>>?data?*?1.6
          array([1.6,?3.2])

          在此,NumPy將數(shù)字1.6廣播成與data維度相同的一維數(shù)組,并用1.6填充,這樣就變成了兩個(gè)一維數(shù)組相乘。

          當(dāng)然,并不是任何情況都能廣播成功,規(guī)則是:從兩個(gè)數(shù)組最右側(cè)維度開(kāi)始,依次向左判斷是否滿足以下兩個(gè)條件:

          • 它們是相等的
          • 其中一個(gè)為1

          滿足一個(gè)條件即可,如果都不滿足,則拋ValueError: operands could not be broadcast together錯(cuò)誤。

          舉個(gè)栗子:

          A??????(4維數(shù)組):??8?x?1?x?6?x?1
          B??????(3維數(shù)組):??????7?x?1?x?5
          廣播后??(4維數(shù)組):??8?x?7?x?6?x?5

          從右往左,要么A維度是1,要么B維度是1,滿足規(guī)則,可以廣播。

          如果改成

          A??????(4維數(shù)組):??8?x?1?x?6?x?2
          B??????(3維數(shù)組):??????7?x?1?x?5

          就會(huì)報(bào)錯(cuò),最右邊兩個(gè)維度,既不相等,也不是1。

          再看一個(gè)計(jì)算的例子:

          x?=?np.array([[1],[2],[3],[4]])
          y?=?np.array([1,2,3,4])
          >>>?x?+?y
          array([[2,?3,?4,?5],
          ???????[3,?4,?5,?6],
          ???????[4,?5,?6,?7],
          ???????[5,?6,?7,?8]])

          x會(huì)被廣播成4*4的數(shù)組

          [[1,?1,?1,?1],
          ?[2,?2,?2,?2],
          ?[3,?3,?3,?4],
          ?[4,?4,?4,?4]]

          y也會(huì)被廣播成4*4的數(shù)組

          [[1,?2,?3,?4],
          ?[1,?2,?3,?4],
          ?[1,?2,?3,?4],
          ?[1,?2,?3,?4]]

          二者按照數(shù)組規(guī)則直接相加即可。

          6. 重塑數(shù)組

          NumPy提供了很多函數(shù)可以更改數(shù)組的形狀(維度)。

          reshape函數(shù)
          >>>?a?=?np.arange(10)
          >>>?a.reshape(5,2)
          array([[0,?1],
          ???????[2,?3],
          ???????[4,?5],
          ???????[6,?7],
          ???????[8,?9]])

          reshape()函數(shù)可以修改數(shù)組的維度,本例中將一個(gè)一維數(shù)組修改成5行2列的二維數(shù)組。

          transpose函數(shù)
          >>>?a?=?np.array([[1,2],[3,4],?[5,6]])
          >>>?a.transpose()
          array([[1,?3,?5],
          ???????[2,?4,?6]])

          transpose()函數(shù)可以轉(zhuǎn)置數(shù)組,實(shí)現(xiàn)線性代數(shù)里矩陣轉(zhuǎn)置的效果。

          數(shù)組轉(zhuǎn)置

          該函數(shù)也可以用a.T來(lái)代替。

          反轉(zhuǎn)數(shù)組

          np.flip()函數(shù)可以反轉(zhuǎn)數(shù)組。

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

          np.flip函數(shù)默認(rèn)將所有元素從左至右、從上至下全部反轉(zhuǎn)。當(dāng)然,也可以按照某維反轉(zhuǎn)

          >>>?#?按行反轉(zhuǎn)
          >>>?np.flip(a,?axis=0)
          array([[?9,?10,?11,?12],
          ???????[?5,??6,??7,??8],
          ???????[?1,??2,??3,??4]])
          >>>?#?按列反轉(zhuǎn)
          >>>?np.flip(a,?axis=1)
          array([[?4,??3,??2,??1],
          ???????[?8,??7,??6,??5],
          ???????[12,?11,?10,??9]])
          扁平化數(shù)組

          flatten()ravel()函數(shù)可以將多維數(shù)組拉平成一維數(shù)組,區(qū)別在于前者會(huì)返回新的數(shù)組,而后者只是創(chuàng)建了原數(shù)組的視圖

          >>>?a?=?np.array([[1?,?2,?3,?4],?[5,?6,?7,?8]])
          >>>?a
          array([[1,?2,?3,?4],
          ???????[5,?6,?7,?8]])?
          >>>?b?=?a.flatten()
          >>>?b
          array([1,?2,?3,?4,?5,?6,?7,?8])
          >>>?b[0]?=?10
          >>>?b
          array([10,??2,??3,??4,??5,??6,??7,??8])
          >>>?a
          array([[1,?2,?3,?4],
          ???????[5,?6,?7,?8]])

          a是二維數(shù)組,經(jīng)過(guò)flatten函數(shù)拉平后變成一維數(shù)組b,修改b數(shù)組的值,不會(huì)影響數(shù)組a

          >>>?a?=?np.array([[1?,?2,?3,?4],?[5,?6,?7,?8]])
          >>>?b?=?a.ravel()
          >>>?b
          array([1,?2,?3,?4,?5,?6,?7,?8])
          >>>?b[0]?=?10
          >>>?a
          array([[10,??2,??3,??4],
          ???????[?5,??6,??7,??8]])

          數(shù)組a經(jīng)過(guò)ravel函數(shù)拉平成一維數(shù)組b,修改b中值會(huì)影響數(shù)組a

          這里會(huì)發(fā)現(xiàn)一個(gè)現(xiàn)象,數(shù)組a的仍然是二維數(shù)組,說(shuō)明raval只是建立了a視圖,并沒(méi)有改變a本身的存儲(chǔ)結(jié)構(gòu)。

          如果想修改b而不影響a,可以調(diào)用copy()函數(shù)

          >>>?c?=?b.copy()
          >>>?c
          array([10,??2,??3,??4,??5,??6,??7,??8])
          >>>?c[0]=100
          >>>?a
          array([[10,??2,??3,??4],
          ???????[?5,??6,??7,??8]])

          copy()函數(shù)會(huì)創(chuàng)建一個(gè)新數(shù)組,并用原數(shù)組的值填充,因此修改新數(shù)組不會(huì)影響原數(shù)組。這個(gè)過(guò)程也叫做深拷貝

          重塑數(shù)組的函數(shù)還有很多,如:

          • np.sort():排序
          • np.hstack():橫向合并數(shù)組
          • np.vstack():縱向和并數(shù)組
          • np.concatenate():按維合并數(shù)組

          等等等等。

          用法上并不復(fù)雜,大家可以參考官方文檔學(xué)習(xí)一下。

          7. 高級(jí)訪問(wèn)

          7.1 索引數(shù)組

          第3小節(jié)講解訪問(wèn)數(shù)組時(shí),都是通過(guò)數(shù)字來(lái)訪問(wèn)。NumPy支持按照數(shù)組格式訪問(wèn)數(shù)組。

          >>>?a?=?np.arange(12)
          >>>?i?=?np.array([1,?1,?3,?8,?5])
          >>>?a[i]?
          array([1,?1,?3,?8,?5])

          數(shù)組i是一個(gè)索引數(shù)組,它里面的值都可以當(dāng)做a的下標(biāo)來(lái)訪問(wèn)。

          也可以通過(guò)同樣的方式訪問(wèn)多維數(shù)組。

          >>>?a?=?np.array([[0,?0,?0],?[255,?0,?0],?[0,?255,?0],?[0,?0,?255],?[255,?255,?255]])
          >>>?a
          array([[??0,???0,???0],
          ???????[255,???0,???0],
          ???????[??0,?255,???0],
          ???????[??0,???0,?255],
          ???????[255,?255,?255]])
          >>>?i?=?np.array([[0,?1,?2,?0],?[0,?3,?4,?0]])
          >>>?a[i]
          array([[[??0,???0,???0],
          ????????[255,???0,???0],
          ????????[??0,?255,???0],
          ????????[??0,???0,???0]],

          ???????[[??0,???0,???0],
          ????????[??0,???0,?255],
          ????????[255,?255,?255],
          ????????[??0,???0,???0]]])

          訪問(wèn)多維數(shù)組,索引數(shù)組i中的數(shù)值,都將作為數(shù)組a中的第0維的下標(biāo)。

          當(dāng)然索引數(shù)組并非只能訪問(wèn)第0維,也能支持多個(gè)索引數(shù)組訪問(wèn)同一個(gè)數(shù)組多個(gè)維度。

          >>>?a?=?np.arange(12).reshape(3,?4)
          >>>?a
          array([[?0,??1,??2,??3],
          ???????[?4,??5,??6,??7],
          ???????[?8,??9,?10,?11]])
          >>>?i?=?np.array([[0,?1],?[1,?2]])
          >>>?j?=?np.array([[2,?1],?[3,?3]])
          >>>?a[i,?j]
          array([[?2,??5],
          ???????[?7,?11]])

          索引數(shù)組的維度必須相同,排在第一位的索引數(shù)組i訪問(wèn)第0維,排在第二位的索引數(shù)組j訪問(wèn)第1維,以此類推。ij相同位置的數(shù)字正好對(duì)應(yīng)數(shù)組a中的某行某列的元素。

          7.2 布爾數(shù)組

          索引數(shù)組可以是個(gè)布爾類型的數(shù)組,True代表保留元素,False代表刪除元素。

          >>>?a?=?np.arange(12).reshape(3,?4)
          >>>?b?=?a?>?4
          >>>?a[b]
          array([?5,??6,??7,??8,??9,?10,?11])
          >>>?a[a?>?4]
          array([?5,??6,??7,??8,??9,?10,?11])

          因?yàn)?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">a和b形狀一樣,所以返回的結(jié)果是一維數(shù)組。

          當(dāng)然也可以指定維度來(lái)篩選

          >>>?a?=?np.arange(12).reshape(3,?4)
          >>>?b1?=?np.array([False,?True,?True])
          >>>?b2?=?np.array([True,?False,?True,?False])
          >>>?a[b1,?:]
          array([[?4,??5,??6,??7],
          ???????[?8,??9,?10,?11]])
          >>>?a[:,?b2]
          array([[?0,??2],
          ???????[?4,??6],
          ???????[?8,?10]])
          >>>?a[b1,?b2]
          array([?4,?10])

          到這里,我們就把NumPy結(jié)構(gòu)、訪問(wèn)和操作都講解完了,涵蓋了NumPy大部分常用的功能。

          有了這篇詳解,相信大家不管是直接用還是再看官方文檔都會(huì)很容易。

          如果本文對(duì)你有用就點(diǎn)個(gè)?在看?鼓勵(lì)一下吧


          相關(guān)閱讀:



          瀏覽 92
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品久久久久久久久久乐趣播 | 日本欧美久久久久免费播放网 | 超碰在线青娱乐 | 国产精品操逼 | 大香蕉伊人免费看 |