學機器學習,不會資料分析怎麼行?之NumPy詳解
NumPy計算
這裡將介紹Numpy的一些基本計算
1.條件運算
2.統計運算
求最大值
求最小值
平均值
方差
3.線性代數
轉置是重塑的一種特殊形式,它返回的是源資料的檢視(不會進行任何複製操作)。陣列不僅有transpose方法,還有一個特殊的T屬性
在進行矩陣計算時,經常需要用到該操作,比如利用np.dot計算矩陣內積
對於高維陣列,我們可以使用transpose進行轉置操作(有點難懂)
在這裡,如果我們使用arr.shape(),則會返回(2,2,4),第一個2表示兩組,第二個則表示每組都有兩行,4則表示4列。而這三個數字由一個元組(0,1,2)進行索引,所以使用arr.transpose((1, 0, 2))時,則表示將第一位數與第二位數交換位置。最終會得到圖中所示結果。
當然,我們也可以使用.T進行操作,不過.T進行的只是軸對換而已。
ndarray還有一個swapaxes方法,它需要接受一對軸編號
矩陣拼接
- 水平拼接
- 垂直拼接
基本索引和切片
1.一維陣列
NumPy陣列的索引是一個內容豐富的主題,因為選取資料子集或單個元素的方式有很多。一維陣列很簡單。從表面上看,它們跟Python列表的功能差不多
如上所示,當你將一個標量值賦值給一個切片時(如arr[5:8]=12),該值會自動傳播到整個選區。跟列表最重要的區別在於,陣列切片是原始陣列的檢視。這意味著資料不會被複制,檢視上的任何修改都會直接反映到源陣列上。
先建立一個arr的切片
修改其中的值,會發現陣列arr中的值也會改變
切片[ : ]會給陣列中所有的值賦值
2.高維陣列
對於高維度陣列,能做的事情更多。在一個二維陣列中,各索引位置上的元素不再是標量而是一維陣列
索引方式
在多維陣列中,如果省略了後面的索引,則返回物件會是一個維度低一點的ndarray(它含有高一級維度上的所有資料),且標量值和陣列都可用於賦值。
切片索引
ndarray的切片語法跟Python列表這樣的一維物件差不多。對於之前的二維陣列arr2d,其切片方式稍顯不同
可以看出,它是沿著第0軸(即第一個軸)切片的。也就是說,切片是沿著一個軸向選取元素的。表示式arr2d[:2]可以被認為是“選取arr2d的前兩行”。
當然,也可以一次傳入多個切片,像傳入多個索引那樣
像這樣進行切片時,只能得到相同維數的陣列檢視。通過將整數索引和切片混合,可以得到低維度的切片。
布林型索引
來看這樣一個例子,假設我們有一個用於儲存資料的陣列以及一個儲存姓名的陣列(含有重複項)。在這裡,我將使用numpy.random中的randn函式(上面表格中漏了這個)生成一些正態分佈的隨機資料:
假設每個名字都對應data陣列中的一行,而我們想要選出對應於名字"Bob"的所有行。跟算術運算一樣,陣列的比較運算(如==)也是向量化的。因此,對names和字串"Bob"的比較運算將會產生一個布林型陣列,這個布林型陣列課用於陣列索引
注:布林型陣列的長度必須跟被索引的軸長度一致,如果布林型陣列的長度不對,布林型選擇就會出錯。
此外,我們還可以將布林型陣列跟切片、整數(或整數序列)混合使用
如果我們要選取多個名字,則組合應用多個布林條件,使用 &、| 之類的布林算術運算子即可
注:通過布林型索引選取陣列中的資料,將總是建立資料的副本,即使返回一模一樣的陣列也是如此。
花式索引
花式索引(Fancy indexing)是一個NumPy術語,它指的是利用整數陣列進行索引。假設我們有一個8×4陣列
array([[ 0., 0., 0., 0.],
[ 1., 1., 1., 1.],
[ 2., 2., 2., 2.],
[ 3., 3., 3., 3.],
[ 4., 4., 4., 4.],
[ 5., 5., 5., 5.],
[ 6., 6., 6., 6.],
[ 7., 7., 7., 7.]])
為了以特定順序選取行子集,只需傳入一個用於指定順序的整數列表或ndarray即可
使用負數索引將會從末尾開始選取行
一次傳入多個索引陣列會返回一個一維陣列,其中的元素對應各個索引元組
注:花式索引跟切片不一樣,它總是將資料複製到新陣列中。
隨機數
1.偽隨機數生成
NumPy可生成隨機數,這些隨機數是通過演算法基於隨機數生成器種子,在確定性條件下生成的,是偽隨機數。我們可以使用normal來得到標準正態分佈的樣本陣列,並且,在需要產生大量隨機數時,NumPy的隨機數生成速度比Python內建的random快了不止一個數量級
同時,我們可以用NumPy的np.random.seed更改隨機數生成種子
np.random.seed(1234)
numpy.random的資料生成函式使用了全域性的隨機種子。要避免全域性狀態,我們可以使用numpy.random.RandomState,建立一個與其它隔離的隨機數生成器
rng = np.random.RandomState(1234) rng.randn(10) Out: array([ 0.4714, -1.191 , 1.4327, -0.3127, -0.7206, 0.8872, 0.8596, -0.6365, 0.0157, -2.2427])
下圖給出了numpy.random中的部分函式
下面屬於補充了
2.例項:隨機漫步
我們可以通過模擬隨機漫步來說明如何運用陣列運算。先來看一個簡單的隨機漫步的例子:從0開始,步長1和-1出現的概率相等。
這提示就是隨機漫步中各步的累計和,可以用一個數組運算來實現。因此,我用np.random模組一次性隨機產生1000個“擲硬幣”結果(即兩個數中任選一個),將其分別設為1或-1,然後計算累計和
有了這些資料之後,我們就可以沿著漫步路徑做一些統計工作了,比如求取最大值和最小值等
1 walk.min() 2 3 walk.max()
再看一個複雜點的統計任務——首次穿越時間,即隨機漫步過程中第一次到達某個特定值的時間。假設我們想要知道本次隨機漫步需要多久才能距離初始0點至少10步遠(任一方向均可)。np.abs(walk)>=10可以得到一個布林型陣列,它表示的是距離是否達到或超過10,而我們想要知道的是第一個10或-10的索引。可以用argmax來解決這個問題,它返回的是該布林型陣列第一個最大值的索引(True就是最大值):
In [103]: (np.abs(walk) >= 10).argmax() Out[103]: 57
一次模擬多個隨機漫步
如果你希望模擬多個隨機漫步過程(比如5000個),只需對上面的程式碼做一點點修改即可生成所有的隨機漫步過程。只要給numpy.random的函式傳入一個二元元組就可以產生一個二維陣列,然後我們就可以一次性計算5000個隨機漫步過程的累計和了:
In [105]: nwalks = 5000 nsteps = 1000 draws = np.random.randint(0, 2, size=(nwalks, nsteps)) steps = np.where(draws > 0, 1 , -1) walks = steps.cumsum(1) walks Out[105]: array([[-1, 0, -1, ..., 12, 11, 10], [ 1, 2, 3, ..., -2, -1, 0], [-1, 0, 1, ..., 34, 35, 36], ..., [ 1, 0, -1, ..., 32, 33, 32], [ 1, 0, 1, ..., 20, 21, 22], [-1, 0, -1, ..., 18, 19, 18]], dtype=int32)
剩下的資料處理就由你們自行發揮了。
結尾
上面只介紹了NumPy的部分內容,剩下的如歸一化操作,排序,檔案輸入輸出(大部分人都用pandas載入文字或表格資料)等等都沒寫入,但都在程式碼中給出了示例。頭一回部落格寫這麼長(雖說圖片居多),中間還幾次頁面錯誤沒儲存。。。如有錯誤,歡迎大家指正。
參考部落格:
參考書籍:
《利用Python進行資料分析·第2版》