NumPy 介紹
什么是 NumPy?
NumPy是Python中科學(xué)計算的基礎(chǔ)包。它是一個Python庫,提供多維數(shù)組對象,各種派生對象(如掩碼數(shù)組和矩陣),以及用于數(shù)組快速操作的各種API,有包括數(shù)學(xué)、邏輯、形狀操作、排序、選擇、輸入輸出、離散傅立葉變換、基本線性代數(shù),基本統(tǒng)計運算和隨機(jī)模擬等等。
NumPy包的核心是 ndarray 對象。它封裝了python原生的同數(shù)據(jù)類型的 n 維數(shù)組,為了保證其性能優(yōu)良,其中有許多操作都是代碼在本地進(jìn)行編譯后執(zhí)行的。
NumPy數(shù)組 和 原生Python Array(數(shù)組)之間有幾個重要的區(qū)別:
- NumPy 數(shù)組在創(chuàng)建時具有固定的大小,與Python的原生數(shù)組對象(可以動態(tài)增長)不同。更改ndarray的大小將創(chuàng)建一個新數(shù)組并刪除原來的數(shù)組。
- NumPy 數(shù)組中的元素都需要具有相同的數(shù)據(jù)類型,因此在內(nèi)存中的大小相同。 例外情況:Python的原生數(shù)組里包含了NumPy的對象的時候,這種情況下就允許不同大小元素的數(shù)組。
- NumPy 數(shù)組有助于對大量數(shù)據(jù)進(jìn)行高級數(shù)學(xué)和其他類型的操作。通常,這些操作的執(zhí)行效率更高,比使用Python原生數(shù)組的代碼更少。
- 越來越多的基于Python的科學(xué)和數(shù)學(xué)軟件包使用NumPy數(shù)組; 雖然這些工具通常都支持Python的原生數(shù)組作為參數(shù),但它們在處理之前會還是會將輸入的數(shù)組轉(zhuǎn)換為NumPy的數(shù)組,而且也通常輸出為NumPy數(shù)組。換句話說,為了高效地使用當(dāng)今科學(xué)/數(shù)學(xué)基于Python的工具(大部分的科學(xué)計算工具),你只知道如何使用Python的原生數(shù)組類型是不夠的 - 還需要知道如何使用 NumPy 數(shù)組。
關(guān)于數(shù)組大小和速度的要點在科學(xué)計算中尤為重要。舉一個簡單的例子,考慮將1維數(shù)組中的每個元素與相同長度的另一個序列中的相應(yīng)元素相乘的情況。如果數(shù)據(jù)存儲在兩個Python 列表 a
和 b
中,我們可以迭代每個元素,如下所示:
c = []
for i in range(len(a)):
c.append(a[i]*b[i])
確實符合我們的要求,但如果a
和b
每一個都包含數(shù)以百萬計的數(shù)字,我們會付出Python中循環(huán)的效率低下的代價。我們可以通過在C中寫入以下代碼,更快地完成相同的任務(wù)(為了清楚起見,我們忽略了變量聲明和初始化,內(nèi)存分配等)。
for (i = 0; i < rows; i++): {
c[i] = a[i]*b[i];
}
這節(jié)省了解釋Python代碼和操作Python對象所涉及的所有開銷,但犧牲了用Python編寫代碼所帶來的好處。此外,編碼工作需要增加的維度,我們的數(shù)據(jù)。例如,對于二維數(shù)組,C代碼(如前所述)會擴(kuò)展為這樣:
for (i = 0; i < rows; i++): {
for (j = 0; j < columns; j++): {
c[i][j] = a[i][j]*b[i][j];
}
}
NumPy 為我們提供了兩全其美的解決方案:當(dāng)涉及到 ndarray 時,逐個元素的操作是“默認(rèn)模式”,但逐個元素的操作由預(yù)編譯的C代碼快速執(zhí)行。在NumPy中:
c = a * b
以近C速度執(zhí)行前面的示例所做的事情,但是我們期望基于Python的代碼具有簡單性。的確,NumPy的語法更為簡單!最后一個例子說明了NumPy的兩個特征,它們是NumPy的大部分功能的基礎(chǔ):矢量化和廣播。
為什么 NumPy 這么快?
矢量化描述了代碼中沒有任何顯式的循環(huán),索引等 - 這些當(dāng)然是預(yù)編譯的C代碼中“幕后”優(yōu)化的結(jié)果。矢量化代碼有許多優(yōu)點,其中包括:
- 矢量化代碼更簡潔,更易于閱讀
- 更少的代碼行通常意味著更少的錯誤
- 代碼更接近于標(biāo)準(zhǔn)的數(shù)學(xué)符號(通常,更容易正確編碼數(shù)學(xué)結(jié)構(gòu))
- 矢量化導(dǎo)致產(chǎn)生更多 “Pythonic” 代碼。如果沒有矢量化,我們的代碼就會被低效且難以閱讀的
for
循環(huán)所困擾。
廣播是用于描述操作的隱式逐元素行為的術(shù)語; 一般來說,在NumPy中,所有操作,不僅僅是算術(shù)運算,而是邏輯,位,功能等,都以這種隱式的逐元素方式表現(xiàn),即它們進(jìn)行廣播。此外,在上面的例子中,a
并且b
可以是相同形狀的多維數(shù)組,或者標(biāo)量和數(shù)組,或者甚至是具有不同形狀的兩個數(shù)組,條件是較小的數(shù)組可以“擴(kuò)展”到更大的形狀。結(jié)果廣播明確無誤的方式。有關(guān)廣播的詳細(xì)“規(guī)則”,請參閱numpy.doc.broadcasting
。
還有誰在使用 NumPy?
NumPy完全支持面向?qū)ο蟮姆椒?,我們再夸獎一?ndarray 。 我們知道 ndarray 是一個類,擁有許多方法和屬性。它的許多方法都由最外層的NumPy命名空間中的函數(shù)鏡像,允許程序員在他們喜歡的范例中進(jìn)行編碼。這種靈活性使NumPy數(shù)組方言和NumPy ndarray 類成為在Python中使用的多維數(shù)據(jù)交換的 首選 對象。
作者:柯廣的網(wǎng)絡(luò)日志 ? NumPy 介紹
微信公眾號:Java大數(shù)據(jù)與數(shù)據(jù)倉庫