這是我學習北京理工大學嵩天老師的《Python數據分析與展示》課程的筆記。嵩老師的課程重點突出、層次分明,在這里特別感謝嵩老師的精彩講解。
NumPy庫入門
數據的維度
維度是一組數據的組織形式。數據維度就是在數據之間形成特定關系表達多種含義的一個概念。
一維數據:
一維數據由對等關系的有序或無序數據構成,采用線性方式組織。對應列表、數組和集合等概念。
列表和數組:一組數據的有序結構。
區別:
列表:數據類型可以不同
數組:數據類型相同
二維數據:
二維數據由多個一維數據構成,是一維數據的組合形式。
表格是典型的二維數據。其中,表頭是二維數據的一部分
多維數據:
多維數據由一維或二維數據在新維度上擴展形成。例如增加時間維度的表格
高維數據:
高維數據僅利用最基本的二元關系展示數據間的復雜結構。利用鍵值對將數據組織起來的形成的數據關系。
數據維度的Python表示
一維數據:列表(有序)和集合(無序)類型
二維數據:列表類型
多維數據:列表類型
高維數據:字典類型或數據表示格式(JSON、XML、YAML)
NumPy的數組對象:ndarray
NumPy是一個開源的Python科學計算基礎庫。NumPy提供了一個強大的N維數組對象ndarray,廣播功能函數,整合C/C++/Fortran代碼的工具,線性代數、傅里葉變換、隨機數生成等功能。NumPy是SciPy、Pandas等數據處理或科學計算庫的基礎。
Numpy引用:
import numpy as np
盡管別名可以省略或更改,建議使用上述約定的別名
引入ndarray的好處:
范例:計算A2 + B3 ,其中,A和B是一維數組
def pySum(): a = [0,1,2,3,4] b = [9,8,7,6,5] c = [] for i in range(len(a)): c.append(a[i]**2 + b[i]**3) return c print(pySum())
import numpy as np def npSum(): a = np.array([0,1,2,3,4]) b = np.array([9,8,7,6,5]) c = a**2 + b**3 return c print(npSum())
數組對象可以去掉元素間運算所需要的循環,使一維向量更像單個數據。設置專門的數組對象,經過優化,可以提升這類應用的運算速度。
觀察:科學計算中,一個維度所有數據的類型往往相同。
數組對象采用相同的數據類型,有助於節省運算和存儲空間。
N維數組對象:ndarray
ndarray是一個多維數組對象,由兩部分構成:實際的數據、描述這些數據的元數據(數據維度、數據類型等)。ndarray數組一般要求所有元素類型相同(同質),數組下標從0開始。
使用np.array()生成一個ndarray數組(ndarray在程序中的別名是:array),np.array()輸出成 [] 形式,元素由空格分割。
- 軸(axis):保存數據的維度
- 秩(rank):軸的數量
范例:生成一個ndarray數組
In [1]: import numpy as np In [2]: a = np.array([[0,1,2,3,4], ...: [9,8,7,6,5]]) ...: In [3]: a Out[3]: array([[0, 1, 2, 3, 4], [9, 8, 7, 6, 5]]) In [4]: print(a) [[0 1 2 3 4] [9 8 7 6 5]]
ndarray對象的屬性
屬性 | 說明 |
---|---|
.ndim | 秩,即軸的數量或維度的數量 |
.shape | ndarray 對象的尺寸,對於矩陣,n行m列 |
.size | ndarray對象元素的個數,相當於.shape中的n*m的值 |
.dtype | ndarray對象元素類型 |
.itemsize | ndarray對象中每個元素的大小,以字節為單位 |
范例:測試ndarray的屬性
In [5]: a.ndim Out[5]: 2 In [6]: a.shape Out[6]: (2, 5) In [7]: a.dtype Out[7]: dtype('int32') In [8]: a.itemsize Out[8]: 4
ndarray的元素類型
數據類型 | 說明 |
---|---|
bool | 布爾類型,True或False |
intc | 與C語言中的int類型一致,一般是int32或int64 |
intp | 用於索引的整數,與C語言sszie_t一致,int32或int64 |
int8 | 字節長度的整數,取值:[-128,127] |
int16 | 16位長度的整數,取值:[-32768,32767] |
int32 | 32位長度的整數,取值:[-231,231-1] |
int64 | 64位長度的整數,取值:[-263,263-1] |
uint8 | 8位無符號整數,取值:[0,255] |
uint16 | 16位無符號整數,取值:[0,255] |
uint32 | 32位無符號整數,取值:[0,232-1] |
uint64 | 64位無符號整數,取值:[0,264-1] |
float16 | 16位半精度浮點數:1位符號位,5位指數,10位尾數((符號)尾數*10指數) |
float32 | 32位半精度浮點數:1位符號位,5位指數,23位尾數 |
float64 | 64位半精度浮點數:1位符號位,11位指數,23位尾數 |
float64 | 64位半精度浮點數:1位符號位,11位指數,52位尾數 |
復數:實部(.real) + j虛部(.imag) | |
complex64 | 復數類型,實部和虛部都是32位浮點數 |
complex128 | 復數類型,實部和虛部都是64位浮點數 |
對比:Python語法僅支持整數、浮點數和復數3種類型。ndarray支持多種元素類型的原因:
- 科學計算涉及數據較多,對存儲和性能都有較高要求。
- 對元素類型精細定義,有助於Numpy合理使用存儲空間並優化性能。
- 對元素類型精細定義,有助於程序員對程序規模有合理評估。
非同質的ndarray對象
ndarray數組可以由非同質對象構成。非同質ndarray元素為對象類型,無法有效發揮Numpy優勢,盡量避免使用。
范例:非同質的ndarray對象的類型為Object
In [9]: x = np.array([[0,1,2,3,4], ...: [9,8,7,6] ]) ...: In [10]: x.shape Out[10]: (2,) In [11]: x.dtype Out[11]: dtype('O') In [12]: x Out[12]: array([list([0, 1, 2, 3, 4]), list([9, 8, 7, 6])], dtype=object) In [13]: x.itemsize Out[13]: 8 In [14]: x.size Out[14]: 2
ndarray數組的創建和變換
ndarray數組的創建方法
(1)從Pyhton中的列表、元祖等類型創建ndarray數組。
x = np.array(list/tuple)
x = np.array(list/tuple,dtype=np.float32)
當np.array()不指定dtype時,NumPy將根據數據情況關聯一個dtype類型。
范例:創建ndarray數組
In [15]: x = np.array([0,1,2,3]) # 從列表類型創建 In [16]: print(x) [0 1 2 3] In [17]: x = np.array((4,5,6,7)) # 從元組類型創建 In [18]: print(x) [4 5 6 7] In [19]: x = np.array([[1,2],[9,8],(0.1, 0.2)]) # 從列表和元組混合類型創建 In [20]: print(x) [[ 1. 2. ] [ 9. 8. ] [ 0.1 0.2]]
(2)使用Numpy中函數創建ndarray數組,如:arange,ones,zeros等。
函數 | 說明 |
---|---|
np.arange(n) | 類似range()函數,返回ndarray類型,元素從0到n-1 |
np.ones(shape) | 根據shape生成一個全1數組,shape是元組類型 |
np.zeros(shape) | 根據shape生成一個全0數組,shape是元組類型 |
np.full(shape,val) | g根據shape生成一個數組,每個元素值都是val |
np.eye(n) | 創建一個正方形的n*n單位矩陣,對角線為1,其余為0 |
np.ones_like(a) | 根據數組a的形狀生成一個全1數組 |
np.zeros_like(a) | 根據數組a的形狀生成一個全0數組 |
np.full_like(a,val) | 根據數組a形狀生成一個數組,每個元素值都是val |
使用Numpy中其他函數創建ndarray數組 | |
np.linspace() | 根據起止數據等間距地填充數據,形成數組 |
np.concatenate() | 將兩個或多個數組合並成一個新的數組 |
范例:創建ndarray數組
In [21]: np.arange(10) Out[21]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) In [22]: np.ones((3,6)) Out[22]: array([[ 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1.]]) In [23]: np.zeros((3,6),dtype=np.int32) Out[23]: array([[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]) In [24]: np.eye(5) Out[24]: array([[ 1., 0., 0., 0., 0.], [ 0., 1., 0., 0., 0.], [ 0., 0., 1., 0., 0.], [ 0., 0., 0., 1., 0.], [ 0., 0., 0., 0., 1.]]) In [25]: x = np.ones((2,3,4)) In [26]: print(x) [[[ 1. 1. 1. 1.] [ 1. 1. 1. 1.] [ 1. 1. 1. 1.]] [[ 1. 1. 1. 1.] [ 1. 1. 1. 1.] [ 1. 1. 1. 1.]]] In [27]: x.shape Out[27]: (2, 3, 4) In [28]: a = np.linspace(1, 10, 4) In [29]: a Out[29]: array([ 1., 4., 7., 10.]) In [30]: b = np.linspace(1, 10, 4, endpoint=False) In [31]: b Out[31]: array([ 1. , 3.25, 5.5 , 7.75]) In [32]: c = np.concatenate((a,b)) In [33]: c Out[33]: array([ 1. , 4. , 7. , 10. , 1. , 3.25, 5.5 , 7.75])
(3)從字節流(raw bytes)中創建ndarray數組。
(4)從文件中讀取特定格式,創建ndarray數組。
ndarray數組的變換
對於創建后的ndarray數組,可以對其進行維度變換和元素類型變換。
ndarray數組的維度變換
方法 | 說明 |
---|---|
.reshape(shape) | 不改變數組元素,返回一個shape形狀的數組,原數組不變 |
.resize(shape) | 與.reshape()功能一致,但修改原數組 |
.swapaxes(ax1,ax2) | 將數組n個維度中兩個維度進行調換 |
.flatten() | 對數組進行降維,返回折疊后的一維數組,原數組不變 |
In [34]: a = np.ones((2,3,4), dtype=np.int32) In [35]: a.reshape((3,8)) Out[35]: array([[1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]]) In [36]: a Out[36]: array([[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]]) In [37]: a.resize((3,8)) In [38]: a Out[38]: array([[1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]]) In [39]: a = np.ones((2,3,4), dtype=np.int32) In [40]: a.flatten() Out[40]: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) In [41]: a Out[41]: array([[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]]) In [42]: b = a.flatten() In [43]: b Out[43]: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
ndarray數組的類型變換
new_a = a.astype(new_type)
范例:數組類型變換
In [44]: a = np.ones((2,3,4), dtype=np.int) In [45]: a Out[45]: array([[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]]) In [46]: b = a.astype(np.float) In [47]: b Out[47]: array([[[ 1., 1., 1., 1.], [ 1., 1., 1., 1.], [ 1., 1., 1., 1.]], [[ 1., 1., 1., 1.], [ 1., 1., 1., 1.], [ 1., 1., 1., 1.]]])
astype()方法一定會創建新的數組(原始數據的一個拷貝),即使兩個類型一致。
ndarray數組向列表的轉換
ls = a.tolist()
范例:ndarray數組向列表的轉換
In [48]: a = np.full((2,3,4), 25, dtype=np.int32) In [49]: a Out[49]: array([[[25, 25, 25, 25], [25, 25, 25, 25], [25, 25, 25, 25]], [[25, 25, 25, 25], [25, 25, 25, 25], [25, 25, 25, 25]]]) In [50]: a.tolist() Out[50]: [[[25, 25, 25, 25], [25, 25, 25, 25], [25, 25, 25, 25]], [[25, 25, 25, 25], [25, 25, 25, 25], [25, 25, 25, 25]]]
ndarray數組的操作
數組的索引和切片
索引:獲取數組中特定位置元素的過程
切片:獲取數組元素子集的過程
一維數組的索引和切片:與Python的列表類似
In [51]: a = np.array([9,8,7,6,5]) In [52]: a[2] Out[52]: 7 In [53]: a[1:4:2] # 起始編號 : 終止編號(不含) : 步長(3元素冒號分割),編號0開始從左遞增,或-1開始從右遞減 Out[53]: array([8, 6])
多維數組的索引:
In [54]: a = np.arange(24).reshape((2,3,4)) In [55]: a Out[55]: array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]]) In [56]: a[1,2,3] # 每個維度一個索引值,逗號分割 Out[56]: 23 In [57]: a[0,1,2] Out[57]: 6 In [58]: a[-1,-2,-3] Out[58]: 17
多維數組的切片:
In [59]: a[: , 1, -3] # 選取一個維度用 Out[59]: array([ 5, 17]) In [60]: a[: , 1:3, :] # 每個維度切片方法與一維數組相同 Out[60]: array([[[ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[16, 17, 18, 19], [20, 21, 22, 23]]]) In [61]: a[: , :, ::2] # 每個維度可以使用步長跳躍切片 Out[61]: array([[[ 0, 2], [ 4, 6], [ 8, 10]], [[12, 14], [16, 18], [20, 22]]])
ndarray數組的運算
數組與標量之間的運算
數組與標量之間的運算作用於數組的每一個元素
范例:計算a與元素平均值的商
In [62]: a.mean() Out[62]: 11.5 In [63]: a = a/a.mean() In [64]: a Out[64]: array([[[ 0. , 0.08695652, 0.17391304, 0.26086957], [ 0.34782609, 0.43478261, 0.52173913, 0.60869565], [ 0.69565217, 0.7826087 , 0.86956522, 0.95652174]], [[ 1.04347826, 1.13043478, 1.2173913 , 1.30434783], [ 1.39130435, 1.47826087, 1.56521739, 1.65217391], [ 1.73913043, 1.82608696, 1.91304348, 2. ]]])
Numpy一元函數
對ndarray中的數據執行元素級運算的函數
函數 | 說明 |
---|---|
np.abs(x) np.fabs(x) | 計算數組各元素的絕對值 |
np.sqrt(x) | 計算數組各元素的平方根 |
np.square(x) | 計算數組各元素的平方 |
np.log(x) np.log10(x) np.log2(x) | 計算數組各元素的自然對數、10底對數和2底對數 |
np.ceil(x) np.floor(x) | 計算數組各元素的ceiling值或floor值 |
np.rint(x) | 計算數組各元素的四舍五入值 |
np.modf(x) | 將數組各元素的小數 |
np.cos(x) np.cosh(x) np.sin(x) np.sinh(x) np.tan(x) np.tanh(x) |
計算數組各元素的普通型和雙曲型三角函數 |
np.exp(x) | 計算數組各元素的指數值 |
np.sign(x) | 計算數組各元素的符號值,1(+),0,-1(-) |
范例:一元函數實例
In [65]: a = np.arange(24).reshape((2,3,4)) In [66]: np.square(a) Out[66]: array([[[ 0, 1, 4, 9], [ 16, 25, 36, 49], [ 64, 81, 100, 121]], [[144, 169, 196, 225], [256, 289, 324, 361], [400, 441, 484, 529]]], dtype=int32) In [67]: a = np.sqrt(a) In [68]: a Out[68]: array([[[ 0. , 1. , 1.41421356, 1.73205081], [ 2. , 2.23606798, 2.44948974, 2.64575131], [ 2.82842712, 3. , 3.16227766, 3.31662479]], [[ 3.46410162, 3.60555128, 3.74165739, 3.87298335], [ 4. , 4.12310563, 4.24264069, 4.35889894], [ 4.47213595, 4.58257569, 4.69041576, 4.79583152]]]) In [69]: np.modf(a) Out[69]: (array([[[ 0. , 0. , 0.41421356, 0.73205081], [ 0. , 0.23606798, 0.44948974, 0.64575131], [ 0.82842712, 0. , 0.16227766, 0.31662479]], [[ 0.46410162, 0.60555128, 0.74165739, 0.87298335], [ 0. , 0.12310563, 0.24264069, 0.35889894], [ 0.47213595, 0.58257569, 0.69041576, 0.79583152]]]), array([[[ 0., 1., 1., 1.], [ 2., 2., 2., 2.], [ 2., 3., 3., 3.]], [[ 3., 3., 3., 3.], [ 4., 4., 4., 4.], [ 4., 4., 4., 4.]]]))
NumPy二元函數
函數 | 說明 |
---|---|
+ - * / ** | 兩個數組各元素進行對應運算 |
np.maximum(x,y) np.fmax() np.minimum(x,y) np.fmin() |
元素級的最大值/最小值計算 |
np.mod(x,y) | 元素級的模運算 |
np.copysign(x,y) | 將數組y中各元素值的符號賦值給數組x對應元素 |
> < >= <= == != | 算術比較,產生布爾型數組 |
范例:NumPy二元函數
In [70]: a = np.arange(24).reshape((2,3,4)) In [71]: b = np.sqrt(a) In [72]: a Out[72]: array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]]) In [73]: b Out[73]: array([[[ 0. , 1. , 1.41421356, 1.73205081], [ 2. , 2.23606798, 2.44948974, 2.64575131], [ 2.82842712, 3. , 3.16227766, 3.31662479]], [[ 3.46410162, 3.60555128, 3.74165739, 3.87298335], [ 4. , 4.12310563, 4.24264069, 4.35889894], [ 4.47213595, 4.58257569, 4.69041576, 4.79583152]]]) In [74]: np.maximum(a,b) Out[74]: array([[[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.]], [[ 12., 13., 14., 15.], [ 16., 17., 18., 19.], [ 20., 21., 22., 23.]]]) In [75]: a > b Out[75]: array([[[False, False, True, True], [ True, True, True, True], [ True, True, True, True]], [[ True, True, True, True], [ True, True, True, True], [ True, True, True, True]]], dtype=bool)