Python資料分析 | Numpy與1維陣列操作

ShowMeAI發表於2022-02-25

ShowMeAI研究中心

作者:韓信子@ShowMeAI
教程地址http://www.showmeai.tech/tutorials/33
本文地址http://www.showmeai.tech/article-detail/142
宣告:版權所有,轉載請聯絡平臺與作者並註明出處


在這裡插入圖片描述

n維陣列是NumPy的核心概念,大部分資料的操作都是基於n維陣列完成的。本系列內容覆蓋到1維陣列操作2維陣列操作3維陣列操作方法,本篇講解Numpy與1維陣列操作。

一、向量初始化

可以通過Python列表建立NumPy陣列。

如圖中(a),將列表元素轉化為一維陣列。注意,這裡一般會確保列表元素型別相同,否則預設dtype=’object',會影響後續運算,甚至產生語法錯誤。

由於在陣列末尾沒有預留空間以快速新增新元素,NumPy陣列無法像Python列表那樣增長。因此,通常的處理方式包括:

  • 在變長Python列表中準備好資料,然後將其轉換為NumPy陣列
  • 使用 np.zerosnp.empty 預先分配必要的空間(圖中b)

通過圖中(c)方法,可以建立一個與某一變數形狀一致的空陣列。

不止是空陣列,通過上述方法還可以將陣列填充為特定值:

在NumPy中,還可以通過單調序列初始化陣列:

如果我們需要浮點陣列,可以使用 arange(3).astype(float) 這樣的操作更改arange輸出的型別,也可以在引數端使用浮點數,比如 arange(4.) 來生產浮點數Numpy陣列。
以下是arange浮點型別資料可能出現的一些問題及解決方案:

圖中,0.1對我們來說是一個有限的十進位制數,但對計算機而言,它是一個二進位制無窮小數,必須四捨五入為一個近似值。因此,將小數作為arange的步長可能導致一些錯誤。可以通過以下兩種方式避免如上錯誤:

  • 使間隔末尾落入非整數步數,但這會降低可讀性和可維護性;
  • 使用linspace,這樣可以避免四捨五入的錯誤影響,並始終生成要求數量的元素。
    • 使用linspace時尤其需要注意最後一個的數量引數設定,由於它計算點數量,而不是間隔數量,因此上圖中數量引數是11,而不是10。

隨機陣列的生成方法如下:

二、向量索引

NumPy可以使用非常直接的方式對陣列資料進行訪問:

圖中,除“fancy indexing”外,其他所有索引方法本質上都是views:它們並不儲存資料,如果原陣列在被索引後發生更改,則會反映出原始陣列中的更改。

上述所有這些方法都可以改變原始陣列,即允許通過分配新值改變原陣列的內容。這導致無法通過切片來複制陣列。如下是python列表和NumPy陣列的對比:

NumPy陣列支援通過布林索引獲取資料,結合各種邏輯運算子可以有很高階的資料選擇方式,這在Python列表中是不具備的:

注意,不可以使用3 <= a <= 5這樣的Python“三元”比較。

如上所述,布林索引是可寫的。如下圖 np.wherenp.clip 兩個專有函式。

三、向量操作

NumPy支援快速計算,向量運算操作接近C++速度級別,並不受Python迴圈本身計算慢的限制。NumPy允許像普通數字一樣操作整個陣列:

在python中,a//b表示a div b(除法的商),x**n表示 xⁿ

浮點數的計算也是如此,NumPy能夠將標量廣播到陣列:

Numpy提供了許多數學函式來處理向量:

向量點乘(內積)和叉乘(外積、向量積)如下:

NumPy也提供瞭如下三角函式運算:

陣列整體進行四捨五入:

floor向上取整,ceil向下取整,round四捨五入

np.aroundnp.round 是等效的,這樣做只是為了避免 from numpy import * 時與Python around的衝突(但一般的使用方式是import numpy as np)。當然,你也可以使用a.round()。

NumPy還可以實現以下功能:

以上功能都存在相應的nan-resistant變體:例如nansumnanmax

在NumPy中,排序函式功能有所閹割:

對於一維陣列,可以通過反轉結果來解決reversed函式缺失的不足,但在2維陣列中該問題變得棘手。

四、查詢向量中的元素

NumPy陣列並沒有Python列表中的索引方法,索引資料的對比如下:

index()中的方括號表示 j 或 i&j 可以省略

  • 可以通過 np.where(a==x)[0] [0]查詢元素,但這種方法很不pythonic,哪怕需要查詢的項在陣列開頭,該方法也需要遍歷整個陣列。
  • 使用Numba實現加速查詢,next((i[0] for i, v in np.ndenumerate(a) if v==x), -1),在最壞的情況下,它的速度要比where慢。
  • 如果陣列是排好序的,使用v = np.searchsorted(a, x); return v if a[v]==x else -1時間複雜度為O(log N),但在這之前,排序的時間複雜度為O(N log N)。

實際上,通過C實現加速搜尋並不是困難,問題是浮點資料比較。

五、浮點數比較

np.allclose(a, b)用於容忍誤差之內的浮點數比較。

  • np.allclose假定所有比較數字的尺度為1。如果在納秒級別上,則需要將預設atol引數除以1e9:np.allclose(1e-9,2e-9, atol=1e-17)==False
  • math.isclose不對要比較的數字做任何假設,而是需要使用者提供一個合理的abs_tol值(np.allclose預設的atol值1e-8足以滿足小數位數為1的浮點數比較,即math.isclose(0.1+0.2–0.3, abs_tol=1e-8)==True

此外,對於絕隊偏差和相對偏差,np.allclose依然存在一些問題。例如,對於某些值a、b, allclose(a,b)!=allclose(b,a),而在math.isclose中則不存在這些問題。檢視GitHub上的浮點資料指南和相應的NumPy問題了解更多資訊。

資料與程式碼下載

本教程系列的程式碼可以在ShowMeAI對應的github中下載,可本地python環境執行,能訪問Google的寶寶也可以直接藉助google colab一鍵執行與互動操作學習哦!

本系列教程涉及的速查表可以在以下地址下載獲取:

擴充參考資料

ShowMeAI相關文章推薦

ShowMeAI系列教程推薦

相關文章