Python:一篇文章掌握Numpy的基本用法
Python:一篇文章掌握Numpy的基本用法
https://mp.weixin.qq.com/s?__biz=MzI2NjY5NzI0NA==&mid=2247483867&idx=1&sn=6cafddd7868d4bfd6d2fbc2426cdae9a&chksm=ea8b6ea8ddfce7be7fe108fcc18ad945742f64657007a85805fe8b9ffcb660ae5ab3e3b2f147&scene=21#wechat_redirect
前言
Numpy是一個開源的Python科學計算庫,它是python科學計算庫的基礎庫,許多其他著名的科學計算庫如Pandas,Scikit-learn等都要用到Numpy庫的一些功能。
本文主要內容如下:
- Numpy陣列物件
- 建立ndarray陣列
- Numpy的數值型別
- ndarray陣列的屬性
- ndarray陣列的切片和索引
- 處理陣列形狀
- 陣列的型別轉換
- numpy常用統計函式
- 陣列的廣播
1 Numpy陣列物件
Numpy中的多維陣列稱為ndarray,這是Numpy中最常見的陣列物件。ndarray物件通常包含兩個部分:
- ndarray資料本身
- 描述資料的後設資料
Numpy陣列的優勢
- Numpy陣列通常是由相同種類的元素組成的,即陣列中的資料項的型別一致。這樣有一個好處,由於知道陣列元素的型別相同,所以能快速確定儲存資料所需空間的大小。
- Numpy陣列能夠運用向量化運算來處理整個陣列,速度較快;而Python的列表則通常需要藉助迴圈語句遍歷列表,執行效率相對來說要差。
- Numpy使用了最佳化過的C API,運算速度較快
關於向量化和標量化運算,對比下面的參考例子就可以看出差異
- 使用python的list進行迴圈遍歷運算
1. def pySum():
2. a = list(range(10000))
3. b = list(range(10000))
4. c = []
5. for i in range(len(a)):
6. c.append(a[i]**2 + b[i]**2)
7.
8. return c
1. %timeit pySum()
1. 10 loops, best of 3: 49.4 ms per loop
- 使用numpy進行向量化運算
1. import numpy as np
2. def npSum():
3. a = np.arange(10000)
4. b = np.arange(10000)
5. c = a**2 + b**2
6. return c
1. %timeit npSum()
1. The slowest run took 262.56 times longer than the fastest. This could mean that an intermediate result is being cached.
2. 1000 loops, best of 3: 128 ?s per loop
從上面的執行結果可以看出,numpy的向量化運算的效率要遠遠高於python的迴圈遍歷運算(效率相差好幾百倍)。 (1ms=1000?s)
2 建立ndarray陣列
首先需要匯入numpy庫,在匯入numpy庫時通常使用“np”作為簡寫,這也是Numpy官方倡導的寫法。
當然,你也可以選擇其他簡寫的方式或者直接寫numpy,但還是建議用“np”,這樣你的程式能和大都數人的程式保持一致。
1. import numpy as np
建立ndarray陣列的方式有很多種,這裡介紹我使用的較多的幾種:
Method 1: 基於list或tuple
1. # 一維陣列
2.
3. # 基於list
4. arr1 = np.array([1,2,3,4])
5. print(arr1)
6.
7. # 基於tuple
8. arr_tuple = np.array((1,2,3,4))
9. print(arr_tuple)
10.
11. # 二維陣列 (2*3)
12. arr2 = np.array([[1,2,4], [3,4,5]])
13. arr2
1. [1 2 3 4]
2. [1 2 3 4]
3. array([[1, 2, 4],
4. [3, 4, 5]])
請注意:
- 一維陣列用print輸出的時候為 [1 2 3 4],跟python的列表是有些差異的,沒有“,”
- 在建立二維陣列時,在每個子list外面還有一個"[]",形式為“[[list1], [list2]]”
Method 2: 基於np.arange
1. # 一維陣列
2. arr1 = np.arange(5)
3. print(arr1)
4.
5. # 二維陣列
6. arr2 = np.array([np.arange(3), np.arange(3)])
7. arr2
1. [0 1 2 3 4]
2. array([[0, 1, 2],
3. [0, 1, 2]])
Method 3: 基於arange以及reshape建立多維陣列
1. # 建立三維陣列
2. arr = np.arange(24).reshape(2,3,4)
3. arr
1. array([[[ 0, 1, 2, 3],
2. [ 4, 5, 6, 7],
3. [ 8, 9, 10, 11]],
4.
5. [[12, 13, 14, 15],
6. [16, 17, 18, 19],
7. [20, 21, 22, 23]]])
- 請注意:arange的長度與ndarray的維度的乘積要相等,即 24 = 2X3X4
- 用numpy.random建立陣列的方法,可以參考下面的文章
- 其他建立ndarray的方法,各位小夥伴們自己可以研究下。
3 Numpy的數值型別
Numpy的數值型別如下:
每一種資料型別都有相應的資料轉換函式,參考示例如下:
1. np.int8(12.334)
1. 12
1. np.float64(12)
1. 12.0
1. np.float(True)
1. 1.0
1. bool(1)
1. True
在建立ndarray陣列時,可以指定數值型別:
1. a = np.arange(5, dtype=float)
2. a
1. array([ 0., 1., 2., 3., 4.])
- 請注意,複數不能轉換成為整數型別或者浮點數,比如下面的程式碼會執行出錯
1. # float(42 + 1j)
4 ndarray陣列的屬性
- dtype屬性,ndarray陣列的資料型別,資料型別的種類,前面已描述。
1. np.arange(4, dtype=float)
1. array([ 0., 1., 2., 3.])
1. # 'D'表示複數型別
2. np.arange(4, dtype='D')
1. array([ 0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j])
1. np.array([1.22,3.45,6.779], dtype='int8')
1. array([1, 3, 6], dtype=int8)
- ndim屬性,陣列維度的數量
1. a = np.array([[1,2,3], [7,8,9]])
2. a.ndim
1. 2
- shape屬性,陣列物件的尺度,對於矩陣,即n行m列,shape是一個元組(tuple)
1. a.shape
1. (2, 3)
- size屬性用來儲存元素的數量,相當於shape中nXm的值
1. a.size
1. 6
- itemsize屬性返回陣列中各個元素所佔用的位元組數大小。
1. a.itemsize
1. 4
- nbytes屬性,如果想知道整個陣列所需的位元組數量,可以使用nbytes屬性。其值等於陣列的size屬性值乘以itemsize屬性值。
1. a.nbytes
1. 24
1. a.size*a.itemsize
1. 24
- T屬性,陣列轉置
1. b = np.arange(24).reshape(4,6)
2. b
1. array([[ 0, 1, 2, 3, 4, 5],
2. [ 6, 7, 8, 9, 10, 11],
3. [12, 13, 14, 15, 16, 17],
4. [18, 19, 20, 21, 22, 23]])
1. b.T
1. array([[ 0, 6, 12, 18],
2. [ 1, 7, 13, 19],
3. [ 2, 8, 14, 20],
4. [ 3, 9, 15, 21],
5. [ 4, 10, 16, 22],
6. [ 5, 11, 17, 23]])
- 複數的實部和虛部屬性,real和imag屬性
1. d = np.array([1.2+2j, 2+3j])
2. d
1. array([ 1.2+2.j, 2.0+3.j])
real屬性返回陣列的實部
1. d.real
1. array([ 1.2, 2. ])
imag屬性返回陣列的虛部
1. d.imag
1. array([ 2., 3.])
- flat屬性,返回一個numpy.flatiter物件,即可迭代的物件。
1. e = np.arange(6).reshape(2,3)
2. e
1. array([[0, 1, 2],
2. [3, 4, 5]])
1. f = e.flat
2. f
1. <numpy.flatiter at 0x65eaca0>
1. for item in f:
2. print(item)
1. 0
2. 1
3. 2
4. 3
5. 4
6. 5
可透過位置進行索引,如下:
1. f[2]
1. 2
1. f[[1,4]]
1. array([1, 4])
也可以進行賦值
1. e.flat=7
2. e
1. array([[7, 7, 7],
2. [7, 7, 7]])
1. e.flat[[1,4]]=1
2. e
1. array([[7, 1, 7],
2. [7, 1, 7]])
下圖是對ndarray各種屬性的一個小結
5 ndarray陣列的切片和索引
- 一維陣列
一維陣列的切片和索引與python的list索引類似。
1. a = np.arange(7)
2. a
1. array([0, 1, 2, 3, 4, 5, 6])
1. a[1:4]
1. array([1, 2, 3])
1. # 每間隔2個取一個數
2. a[ : 6: 2]
1. array([0, 2, 4])
- 二維陣列的切片和索引,如下所示:
插播一條硬廣:技術文章轉發太多。本文涉及的程式碼量比較多,如需要檢視原始碼,請在微信公眾號“Python資料之道”(ID:PyDataRoad)後臺回覆關鍵字“2017026”。
6 處理陣列形狀
6.1 形狀轉換
- reshape()和resize()
1. b.reshape(4,3)
1. array([[ 0, 1, 2],
2. [ 3, 4, 5],
3. [ 6, 7, 8],
4. [ 9, 10, 11]])
1. b
1. array([[ 0, 1, 2, 3],
2. [ 4, 5, 6, 7],
3. [ 8, 9, 10, 11]])
1. b.resize(4,3)
2. b
1. array([[ 0, 1, 2],
2. [ 3, 4, 5],
3. [ 6, 7, 8],
4. [ 9, 10, 11]])
函式resize()的作用跟reshape()類似,但是會改變所作用的陣列,相當於有inplace=True的效果
- ravel()和flatten(),將多維陣列轉換成一維陣列,如下:
1. b.ravel()
1. array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
1. b.flatten()
1. array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
1. b
1. array([[ 0, 1, 2],
2. [ 3, 4, 5],
3. [ 6, 7, 8],
4. [ 9, 10, 11]])
兩者的區別在於返回複製(copy)還是返回檢視(view),flatten()返回一份複製,需要分配新的記憶體空間,對複製所做的修改不會影響原始矩陣,而ravel()返回的是檢視(view),會影響原始矩陣。
參考如下程式碼:
- 用tuple指定陣列的形狀,如下:
1. b.shape=(2,6)
2. b
1. array([[ 0, 1, 20, 3, 4, 5],
2. [ 6, 7, 8, 9, 10, 11]])
- 轉置
前面描述了陣列轉置的屬性(T),也可以透過transpose()函式來實現
1. b.transpose()
1. array([[ 0, 6],
2. [ 1, 7],
3. [20, 8],
4. [ 3, 9],
5. [ 4, 10],
6. [ 5, 11]])
6.2 堆疊陣列
1. b
1. array([[ 0, 1, 20, 3, 4, 5],
2. [ 6, 7, 8, 9, 10, 11]])
1. c = b*2
2. c
1. array([[ 0, 2, 40, 6, 8, 10],
2. [12, 14, 16, 18, 20, 22]])
- 水平疊加
hstack()
1. np.hstack((b,c))
1. array([[ 0, 1, 20, 3, 4, 5, 0, 2, 40, 6, 8, 10],
2. [ 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22]])
column_stack()函式以列方式對陣列進行疊加,功能類似hstack()
1. np.column_stack((b,c))
1. array([[ 0, 1, 20, 3, 4, 5, 0, 2, 40, 6, 8, 10],
2. [ 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22]])
- 垂直疊加
vstack()
1. np.vstack((b,c))
1. array([[ 0, 1, 20, 3, 4, 5],
2. [ 6, 7, 8, 9, 10, 11],
3. [ 0, 2, 40, 6, 8, 10],
4. [12, 14, 16, 18, 20, 22]])
row_stack()函式以行方式對陣列進行疊加,功能類似vstack()
1. np.row_stack((b,c))
1. array([[ 0, 1, 20, 3, 4, 5],
2. [ 6, 7, 8, 9, 10, 11],
3. [ 0, 2, 40, 6, 8, 10],
4. [12, 14, 16, 18, 20, 22]])
- concatenate()方法,透過設定axis的值來設定疊加方向
axis=1時,沿水平方向疊加
axis=0時,沿垂直方向疊加
1. np.concatenate((b,c),axis=1)
1. array([[ 0, 1, 20, 3, 4, 5, 0, 2, 40, 6, 8, 10],
2. [ 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22]])
1. np.concatenate((b,c),axis=0)
1. array([[ 0, 1, 20, 3, 4, 5],
2. [ 6, 7, 8, 9, 10, 11],
3. [ 0, 2, 40, 6, 8, 10],
4. [12, 14, 16, 18, 20, 22]])
由於針對陣列的軸為0或1的方向經常會混淆,透過示意圖,或許可以更好的理解。
關於陣列的軸方向示意圖,以及疊加的示意圖,如下:
- 深度疊加
這個有點燒腦,舉個例子如下,自己可以體會下:
1. arr_dstack = np.dstack((b,c))
2. print(arr_dstack.shape)
3. arr_dstack
1. (2, 6, 2)
2.
3. array([[[ 0, 0],
4. [ 1, 2],
5. [20, 40],
6. [ 3, 6],
7. [ 4, 8],
8. [ 5, 10]],
9.
10. [[ 6, 12],
11. [ 7, 14],
12. [ 8, 16],
13. [ 9, 18],
14. [10, 20],
15. [11, 22]]])
疊加前,b和c均是shape為(2,6)的二維陣列,疊加後,arr_dstack是shape為(2,6,2)的三維陣列。
深度疊加的示意圖如下:
6.3 陣列的拆分
跟陣列的疊加類似,陣列的拆分可以分為橫向拆分、縱向拆分以及深度拆分。
涉及的函式為 hsplit()、vsplit()、dsplit() 以及split()
1. b
1. array([[ 0, 1, 20, 3, 4, 5],
2. [ 6, 7, 8, 9, 10, 11]])
- 沿橫向軸拆分(axis=1)
1. np.hsplit(b, 2)
1. [array([[ 0, 1, 20],
2. [ 6, 7, 8]]), array([[ 3, 4, 5],
3. [ 9, 10, 11]])]
1. np.split(b,2, axis=1)
1. [array([[ 0, 1, 20],
2. [ 6, 7, 8]]), array([[ 3, 4, 5],
3. [ 9, 10, 11]])]
- 沿縱向軸拆分(axis=0)
1. np.vsplit(b, 2)
1. [array([[ 0, 1, 20, 3, 4, 5]]), array([[ 6, 7, 8, 9, 10, 11]])]
1. np.split(b,2,axis=0)
1. [array([[ 0, 1, 20, 3, 4, 5]]), array([[ 6, 7, 8, 9, 10, 11]])]
- 深度拆分
1. arr_dstack
1. array([[[ 0, 0],
2. [ 1, 2],
3. [20, 40],
4. [ 3, 6],
5. [ 4, 8],
6. [ 5, 10]],
7.
8. [[ 6, 12],
9. [ 7, 14],
10. [ 8, 16],
11. [ 9, 18],
12. [10, 20],
13. [11, 22]]])
1. np.dsplit(arr_dstack,2)
1. [array([[[ 0],
2. [ 1],
3. [20],
4. [ 3],
5. [ 4],
6. [ 5]],
7.
8. [[ 6],
9. [ 7],
10. [ 8],
11. [ 9],
12. [10],
13. [11]]]), array([[[ 0],
14. [ 2],
15. [40],
16. [ 6],
17. [ 8],
18. [10]],
19.
20. [[12],
21. [14],
22. [16],
23. [18],
24. [20],
25. [22]]])]
拆分的結果是原來的三維陣列拆分成為兩個二維陣列。
這個燒腦的拆分過程可以自行分析下~~
7 陣列的型別轉換
- 陣列轉換成list,使用tolist()
1. b
1. array([[ 0, 1, 20, 3, 4, 5],
2. [ 6, 7, 8, 9, 10, 11]])
1. b.tolist()
1. [[0, 1, 20, 3, 4, 5], [6, 7, 8, 9, 10, 11]]
- 轉換成指定型別,astype()函式
1. b.astype(float)
1. array([[ 0., 1., 20., 3., 4., 5.],
2. [ 6., 7., 8., 9., 10., 11.]])
8 numpy常用統計函式
常用的函式如下:
請注意函式在使用時需要指定axis軸的方向,若不指定,預設統計整個陣列。
- np.sum(),返回求和
- np.mean(),返回均值
- np.max(),返回最大值
- np.min(),返回最小值
- np.ptp(),陣列沿指定軸返回最大值減去最小值,即(max-min)
- np.std(),返回標準偏差(standard deviation)
- np.var(),返回方差(variance)
- np.cumsum(),返回累加值
- np.cumprod(),返回累乘積值
1. b
1. array([[ 0, 1, 20, 3, 4, 5],
2. [ 6, 7, 8, 9, 10, 11]])
1. np.max(b)
1. 20
1. # 沿axis=1軸方向統計
2. np.max(b,axis=1)
1. array([20, 11])
1. # 沿axis=0軸方向統計
2. np.max(b,axis=0)
1. array([ 6, 7, 20, 9, 10, 11])
1. np.min(b)
1. 0
- np.ptp(),返回整個陣列的最大值減去最小值,如下:
1. np.ptp(b)
1. 20
1. # 沿axis=0軸方向
2. np.ptp(b, axis=0)
1. array([ 6, 6, 12, 6, 6, 6])
1. # 沿axis=1軸方向
2. np.ptp(b, axis=1)
1. array([20, 5])
- np.cumsum(),沿指定軸方向進行累加
1. b.resize(4,3)
2. b
1. array([[ 0, 1, 20],
2. [ 3, 4, 5],
3. [ 6, 7, 8],
4. [ 9, 10, 11]])
1. np.cumsum(b, axis=1)
1. array([[ 0, 1, 21],
2. [ 3, 7, 12],
3. [ 6, 13, 21],
4. [ 9, 19, 30]], dtype=int32)
1. np.cumsum(b, axis=0)
1. array([[ 0, 1, 20],
2. [ 3, 5, 25],
3. [ 9, 12, 33],
4. [18, 22, 44]], dtype=int32)
- np.cumprod(),沿指定軸方向進行累乘積 (Return the cumulative product of the elements along the given axis)
1. np.cumprod(b,axis=1)
1. array([[ 0, 0, 0],
2. [ 3, 12, 60],
3. [ 6, 42, 336],
4. [ 9, 90, 990]], dtype=int32)
1. np.cumprod(b,axis=0)
1. array([[ 0, 1, 20],
2. [ 0, 4, 100],
3. [ 0, 28, 800],
4. [ 0, 280, 8800]], dtype=int32)
9 陣列的廣播
當陣列跟一個標量進行數學運算時,標量需要根據陣列的形狀進行擴充套件,然後執行運算。
這個擴充套件的過程稱為“廣播(broadcasting)”
1. b
1. array([[ 0, 1, 20],
2. [ 3, 4, 5],
3. [ 6, 7, 8],
4. [ 9, 10, 11]])
1. d = b + 2
2. d
1. array([[ 2, 3, 22],
2. [ 5, 6, 7],
3. [ 8, 9, 10],
4. [11, 12, 13]])
寫在最後
numpy涵蓋的內容其實是非常豐富的,本文僅僅介紹了numpy一些常用的基本功能,算是對numpy的一個入門級的簡單的較為全面的描述。
numpy官方的《Numpy Reference》文件,光頁面數量就有1500+頁,如想要系統的學習numpy,建議仔細閱讀官方的參考文件,可在其官方網站進行查閱。當然,資料都是英文版的,可能看起來難度稍微大點,看習慣了就好。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29829936/viewspace-2149843/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一篇文章帶你掌握Flex佈局的所有用法Flex
- Numpy基本用法(很基礎的點哦)
- 一篇文章,全面掌握GitGit
- 前置機器學習(三):30分鐘掌握常用NumPy用法機器學習
- 一篇文章基本看懂gradleGradle
- Python numpy中矩陣的用法總結Python矩陣
- 一篇文章掌握常見的網站攻擊方式網站
- python中numpy模組下的np.clip()的用法Python
- git基本操作,一篇文章就夠了!Git
- 一篇文章讓你徹底掌握 shell 語言
- 一篇文章帶你掌握效能測試工具——JmeterJMeter
- Numpy的基本操作(五)
- 一篇文章搞定Python中的類Python
- (2)python_numpy: numpy.ma.masked_invalid 與 numpy.ma.compress_rowcols 函式用法Python函式
- numpy學習筆記 – numpy陣列的常見用法筆記陣列
- 掌握 CORS 跨域請求,讀這一篇文章就夠了CORS跨域
- 一篇文章搞定Python多程式(全)Python
- Python必備基礎:這些NumPy的神操作你都掌握了嗎?Python
- 一篇文章帶你掌握Web自動化測試工具——SeleniumWeb
- MongoDB的基本用法MongoDB
- webpack的基本用法Web
- rematch的基本用法REM
- Promise的基本用法Promise
- mysqldump的基本用法MySql
- 文章的基本結構
- numpy矩陣的基本方法和屬性矩陣
- Python中裝飾器的基本概念和用法Python
- Python2爬蟲利器:requests庫的基本用法Python爬蟲
- UIScrollView的基本用法UIView
- 瞭解 Oracle 中單引號與雙引號的用法,一篇文章教會你!Oracle
- Python科學計算庫Numpy陣列的初始化和基本操作Python陣列
- Promise基本用法Promise
- Git基本用法Git
- mongoose基本用法Go
- tcpdump基本用法TCP
- GORM基本用法GoORM
- 一篇文章引發的思考
- 理解python函式,這一篇文章就夠了Python函式