小蛇學(xué)python(16)numpy高階用法

如果只是從事簡(jiǎn)單的數(shù)據(jù)分析,其實(shí)numpy的用處并不是很大。簡(jiǎn)單了解一下numpy,學(xué)好pandas已經(jīng)夠用,尤其是對(duì)于結(jié)構(gòu)化或表格化數(shù)據(jù)。但是精通面向數(shù)組的編程和思維方式是成為python科學(xué)計(jì)算牛人的關(guān)鍵一步。

而且使用numpy的代碼往往比普通數(shù)組要快,因?yàn)閿?shù)組運(yùn)算一般都比純python循環(huán)要快得多。大量使用列表,將無(wú)可避免的使用循環(huán)。

當(dāng)大家對(duì)numpy足夠熟悉的時(shí)候,我建議大家這樣做:

  1. 將python循環(huán)和條件邏輯轉(zhuǎn)換為數(shù)組運(yùn)算和布爾數(shù)組運(yùn)算。
  2. 盡量使用廣播。
  3. 避免復(fù)制數(shù)據(jù),盡量使用數(shù)組視圖,即切片。
  4. 利用ufunc及其它各種方法。

線性代數(shù)

import numpy as np

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

y = np.array([[6, 23], [-1, 7], [8, 9]])
print(x)
print(y)

print(x.dot(y))

image.png

這是最基礎(chǔ)的矩陣計(jì)算。比較常用的矩陣計(jì)算函數(shù)如下。

函數(shù) 說(shuō)明
diag 以一位數(shù)組形式返回對(duì)角線元素
dot 矩陣乘法
trace 矩陣跡
det 行列式值
eig 本征值與本征向量
inv 求逆
pinv Moore-Penrose偽逆
qr QR分解
svd 奇異值分解
solve 解線性方程組Ax=b
lstsq 計(jì)算Ax=b的最小二乘解

高級(jí)數(shù)據(jù)操作

ndarray數(shù)組視圖不復(fù)制任何數(shù)據(jù)的原因是因?yàn)椋琻darray不只是一塊內(nèi)存和一個(gè)dtype,更準(zhǔn)確的說(shuō)它還有跨度信息,這使得數(shù)組能以各種步幅在內(nèi)存中移動(dòng)。(其實(shí)移動(dòng)的是指針)也因此,ndarray數(shù)組有很多我們意想不到的功能。

import numpy as np

arr = np.arange(8)
print(arr)
new_arr = arr.reshape((4, 2))
print(arr)
print(new_arr)
image.png

同樣,既然可以重塑,那也可以扁平化,即展開(kāi)。

import numpy as np

arr = np.arange(8)
new_arr = arr.reshape((4, 2))
print(new_arr)
new_new_arr = new_arr.ravel()
print(new_new_arr)

image.png

在這里要提及一點(diǎn)。與其他科學(xué)計(jì)算環(huán)境相反(R或matlab),numpy允許更為靈活地控制數(shù)據(jù)在內(nèi)存中的布局。具體來(lái)說(shuō),比如展開(kāi)數(shù)組時(shí)是按列優(yōu)先還是按行優(yōu)先。

pandas的操作對(duì)象主要是結(jié)構(gòu)化數(shù)據(jù),numpy的操作對(duì)象主要是ndarray數(shù)組。這兩者之間有很多功能函數(shù)是一一對(duì)應(yīng)的,比如,pandas有對(duì)表格的拼接,ndarray也有對(duì)數(shù)組的拼接。

import numpy as np

arr1 = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.array([[7, 8, 9], [10 ,11, 12]])
print(np.concatenate([arr1, arr2], axis=0))
print(np.concatenate([arr1, arr2], axis=1))
image.png

有拼接就有拆分,split函數(shù)用于將一個(gè)數(shù)組沿指定軸拆分為多個(gè)數(shù)組。

import numpy as np
from numpy.random import  randn

arr = randn(8, 2)
first, second, third = np.split(arr, [2, 3])
print(first)
print(second)
print(third)
image.png

還有很多功能不一一介紹,其實(shí)非常簡(jiǎn)單,在這里只是引起大家注意,知道numpy功能的強(qiáng)大。

還需要注意一點(diǎn)的是,這些函數(shù)都是建立在ndarray數(shù)組之上的,列表,元組等并無(wú)此功能。

廣播機(jī)制

所謂廣播是說(shuō)不同形狀的數(shù)組之間的算術(shù)運(yùn)算的執(zhí)行方式。

將標(biāo)量值和數(shù)組進(jìn)行組合時(shí)就會(huì)發(fā)生最簡(jiǎn)單的廣播。

import numpy as np


arr = np.arange(5)
print(arr)
print(arr-1)
image.png

如圖所示,當(dāng)數(shù)組和數(shù)字之間運(yùn)算時(shí),并沒(méi)有報(bào)錯(cuò),而是每個(gè)數(shù)組元素和該數(shù)字做了運(yùn)算。這在很多科研數(shù)據(jù)處理的時(shí)候,會(huì)方便很多。

ufunc高級(jí)應(yīng)用

ufunc除了一些通用的施行特定矢量化運(yùn)算的特殊方法外,還可以自定義函數(shù)對(duì)數(shù)組進(jìn)行運(yùn)算。

import numpy as np

def add_elements(x, y):
    return x + y

add_them = np.frompyfunc(add_elements, 2, 1)
print(add_them(np.arange(8), np.arange(8)))
image.png

當(dāng)然,不幸的是,這種創(chuàng)造ufunc的手段雖然很靈活,卻非常慢。因?yàn)樗鼈冊(cè)谟?jì)算的時(shí)候都要執(zhí)行一次python函數(shù)調(diào)用,這自然會(huì)比numpy自帶的基于C編寫(xiě)的ufunc慢很多。

為此,python科學(xué)計(jì)算社區(qū)正在開(kāi)發(fā)一些項(xiàng)目,力求使自定義ufunc的性能接近內(nèi)置的那些。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容