書名: Python數據分析與挖掘作者名: 齊福利 楊玲主編本章字數: 4965字更新時間: 2024-03-14 11:21:32
1.3 NumPy數組常用函數
下面以學生的學習成績為數據樣本展開練習,介紹NumPy數組常用函數。
通過隨機函數生成一個班50名同學的語文、數學、化學、物理和外語5門課的相應成績,假設每個同學的成績范圍為46~100。
>>>import numpy as np >>>score=np.random.randint(46,100,(50,5))
1.3.1 統計函數
1.計算數組/矩陣中的最大值和最小值
np.amax(np數組[,[axis=]0])用于計算數組中的元素沿指定軸的最大值;np.amin(np數組[,[axis=]0]) 用于計算數組中的元素沿指定軸的最小值。
二維數據對象的大多數方法都會有axis這個參數,它控制了用戶指定的操作是沿著0軸還是1軸進行。一般而言,axis=0代表對列進行操作,axis=1代表對行進行操作,省略該項則默認找到整個數組的最大值、最小值。
【動動手練習1-6】 計算數組/矩陣中的最大值、最小值
>>>np.amax(score) #產生一個單一的值 99 >>>np.amin(score) 46 #或 >>>score.max() >>>score.min()
分別計算語文、數學、化學、物理和外語的最高成績和最低成績。
>>> np.amax(score,axis=0) #生成一個數組;np.amax()方法與np.max()方法相同 array([98, 99, 99, 97, 99]) #對應語文、數學、化學、物理和外語的最高成績 >>> np.amin(score,0) #可自行驗證np.amin()方法與np.min()方法相同 array([46, 47, 46, 48, 47]) #對應語文、數學、化學、物理和外語的最低成績
查看總成績排在前三的同學的各門課程最高、最低成績。
>>> np.max(score,axis=1)[:3] #np.amax()和np.max()是同一個方法,可混用 array([96, 97, 97]) >>> np.min(score,axis=1)[:3] #np.amin()和np.min()是同一個方法,可混用 array([68, 53, 55])
再總結一下,np.amax(score)是求出整個數組中的最大值。np.amax(score,0)是沿著axis=0軸(按列)比較的最大值。np.amax(score,1)是沿著axis=1軸(按行)比較的最大值。
2.統計最大值與最小值之差
np.ptp()即極差函數,極差是一組數據的最大值與最小值之差。
將成績差值進行分析,可以發現班級中同學總的學習差距、各門課程的差距,以及各位同學的偏科程度。
【動動手練習1-7】 使用極差函數
>>> np.ptp(score) #求出所有成績的最高值與最低值的差 53 >>> np.ptp(score,axis=0) #求出各門課程的最高成績與最低成績的差 Out[49]: array([52, 52, 53, 49, 52]) >>> np.ptp(score,axis=1) #求出每位同學各門課程最高成績與最低成績的差
3.統計數組的分位數(百分位數)
np.percentile()函數的作用是求百分位數,從而能夠讓用戶知道數字大致的分布。
np.percentile()函數原型:np.percentile(a, q, axis=None)。
各參數說明如下。
● a:原始數組,可以是多維數組。
● q:要計算的百分位數,取值范圍為0~100,多個值時要使用列表方式。
● axis:在a的軸上計算百分位數。
查看學生整體成績的分布情況,從最低成績(0%),處于10%、25%、50%、75%位置上的成績,最高成績(100%)查詢,即批量查詢。
【動動手練習1-8】 使用分位數函數
>>>np.percentile(score,[0,10,25,50,75,100]) array([46. , 51.9, 60. , 75.5, 87. , 99. ])
查看每門課程的成績分布情況。
>>> n=np.percentile(score,[0,10,25,50,75,100],axis=0) >>> n array([[46. , 47. , 46. , 48. , 47. ], [49.8 , 50.9 , 50.7 , 52.9 , 55.8 ], [56. , 65. , 60.25, 61.25, 61.5 ], [70.5 , 80.5 , 73. , 71. , 80. ], [87.75, 89. , 79.5 , 86. , 86.75], [98. , 99. , 99. , 97. , 99. ]])
可以發現,數組的列是每門課程的成績分布數據,列出的是處于不同百分數位置上的成績,實際上,處于50%位置上的數據就是相應的中位數,不是平均數。
可以通過T轉置,將列轉換為行的形式展示(原來的行自然就轉為列)。
>>> n.T #每一行分別對應語文、數學、化學、物理和外語的成績情況
4.統計數組中的中位數
中位數又稱中值,是統計學中的專有名詞,代表一個樣本、種群或概率分布中的數值,是把所有觀察值(數組)按從高到低排序后找出的正中間的數。如果數組數據的個數是奇數,則中間那個數就是這組數據的中位數;如果數據的個數是偶數,則中間2個數的算術平均值就是這組數據的中位數。
下面使用np.median()函數分別查找所有課程成績的中位數、每門課程的中位數和每一位同學成績的中位數。
【動動手練習1-9】 使用中位數函數
>>>np.median(score) 75.5 >>>np.percentile(score,50) 75.5 >>>np.median(score,axis=0) array([70.5, 80.5, 73. , 71. , 80. ]) >>> np.median(score,axis=1)[:3] #僅顯示總成績排在前三的同學成績的中位數 array([72., 65., 83.])
有時候,中位數可能比平均值更有說服力,比如,全社會的工資中位數比平均工資更能體現全社會大多數人的收入水平。
5.統計數組中的平均數、加權平均值
在NumPy中,np.mean()函數和np.average()函數都有取平均數的意思,在不考慮加權平均的前提下,兩者的輸出是一樣的。
求所有成績的平均值、各門課程的平均值。
【動動手練習1-10】 使用均值函數
>>>np.mean(score) 73.676 >>>np.average(score) 73.676 >>>np.mean(score,axis=0) #求各列的平均值 array([72.12, 76.16, 71.52, 73.12, 75.46]) >>>np.mean(score,axis=1)[-3:] #axis=1時,則求每位學生的平均成績 array([70.2, 78.6, 77.4])
當每門課程權重不一樣時,可以通過np.average()函數計算加權平均值,求出每一位學生成績的加權平均值和全部成績的加權平均值。
np.average()函數根據在另一個數組中給出的各自的權重,計算數組中元素的加權平均值。該函數可以接收一個軸參數。如果沒有指定軸參數,則數組會被展開。
加權平均值即將各數值乘以相應的權數,然后相加求和得到總體值,再除以總的單位數。
>>>w=np.array([120,120,100,100,120]) #定義語文、數學、化學、物理和外語的成績對應 重 >>>np.average(score, weights=w, axis=1)[:3] #顯示成績排在前三的值 array([79. , 70.10714286, 78.17857143]) #"79."后面的空表示未顯示部分 >>>np.average(score, weights=w, axis=1).mean() 73.77285714285715
6.統計數組中的方差和標準差
方差是概率論中最基礎的概念之一,是由統計學天才羅納德·費雪提出的。方差用于衡量數據離散程度,因為它能體現變量與其數學期望(均值)之間的偏離程度。
【例題1-2】 計算方差
計算方差,是指先求一組數據中各個數減去這組數據平均數的平方和,再對平方和求平均數。如求(1, 2, 3, 4, 5)這組數據的方差,就要先求出這組數據的平均數(1+2+3+4+5)÷5=3,再求各個數與平均數的差的平方和,(1?3)2+(2?3)2+(3?3)2+(4?3)2+(5?3)2=10,最后求平方和的平均數10÷5=2,即這組數據的方差為2。
標準差是方差的算術平方根(開根號)。由于方差是數據的平方,與檢測值本身相差太大,人們難以直觀衡量,所以常用方差開根號來衡量。標準差的公式:std=sqrt(mean((x - x.mean())**2))。
標準差和方差一樣反映了一個數據集的離散程度,但平均數相同,標準差未必相同。
【例題1-3】 計算標準差
A、B兩組各有6名學生參加同一次語文測驗,A組的分數為95、85、75、65、55、45,B組的分數為73、72、71、69、68、67。這兩組分數的平均數都是70,但A組的標準差為17.08,B組的標準差為2.16,說明A組學生成績之間的差距比B組學生成績之間的差距大得多。
下面通過NumPy提供的方差、標準差函數查看學生成績的離散程度。
【動動手練習1-11】 計算方差和標準差
使用NumPy計算標準差和方差的方法如下。
(1)np.std(a, axis = None):計算標準差。
(2)np.var(a, axis = None):計算方差。
>>>np.var(score) #未指定軸,計算全部成績的方差 241.891024 >>>np.std(score) #未指定軸,計算全部成績的標準差 15.55284617039595 #只有一個標準差并不能確定其離散程度的高低 >>>np.std(score,axis=0) #按列計算每門課程成績的標準差 array([16.97603016, 16.16955163, 14.43224168, 14.96882093, 14.51648718]) #計算語文、數學、化學、物理和外語的標準差,可以相互比較各科成績的差距 #計算每一位學生各科成績的離散程度(差距) >>>np.std(score,axis=1)[4:7] #顯示其中的3個標準差 array([17.14176187, 1.74355958, 14.81890684]) #數值大代表偏科嚴重
7.求和:一般求和與按軸累積求和
【動動手練習1-12】 sum()求和
>>>np.sum(score) #未指定軸,計算所有成績的和 18419 >>>np.sum(score, axis=0) #每門課程的成績和(按列) array([3606, 3808, 3576, 3656, 3773]) >>>np.sum(score, axis=1)[:3] #排在前三的學生的成績和(按行) array([392, 349, 385])
np.cumsum(score[,axis=0])是按軸累積求和,未指定軸則對所有元素累積求和。axis=0表示對多維數組按列累積求和,axis=1表示對數組按行累積求和。
>>>np.cumsum(score)[245:] #對所有成績累積求和,顯示最后5個,共有50*5個 array([18120, 18167, 18229, 18326, 18419], dtype=int32) >>>np.cumsum(score,axis=0)[:3] #按列對每門課程成績累積求和,顯示前3行 array([[ 69, 96, 72, 68, 87], [166, 161, 150, 121, 143], [249, 258, 216, 176, 227]], dtype=int32)
讀者可以自行試驗對行成績(每個同學的成績)累積求和。
1.3.2 邏輯函數
1.np.any()函數和np.all()函數
【例題1-4】 使用np.any()函數和np.all()函數
>>>a1=score[0] >>>a2=score[1] >>> print('第一行大于第二行:',a1>a2) 第一行大于第二行: [False True False True True] >>> print('第一行只要有大于第二行的元素:',np.any(a1>a2)) 第一行只要有大于第二行的元素: True >>> print('第一行的元素全部都大于第二行的元素:',np.all(a1>a2)) 第一行的元素全部都大于第二行的元素: False
使用np.any()函數時,只要結果中存在一個True,最后結果就為True。而使用np.all()函數時,只有結果中全為True,最后的結果才為True。
2.NumPy中的邏輯運算函數
Python中有and、or、not三個邏輯運算符,NumPy使用np.logical_and()、np.logical_or()、np.logical_not()三個函數來進行邏輯運算。
【動動手練習1-13】 數組邏輯運算綜合練習
將第一位同學的各門課程成績與其后的3位同學進行比較,獲取其成績均高于其他3位同學的課程名稱。
>>>a3=score[0]>score[1] >>>a4=score[0]>score[2] >>>a5=score[0]>score[3] >>>np.logical_and(a3,a4,a5) #與a3&a4&a5等價 array([False, False, False, True, True]) #對應語文、數學、化學、物理和外語成績;物理與外語的成績高于其他3位同學的相應成績 >>>score[0][a3&a4&a5] #查看高于其他3位同學的物理與外語成績 array([68, 87])
np.logical_and()函數的參數必須是2個及以上,可以是多個布爾表達式列表數組。
查看前3位同學每門課程成績有沒有大于90分的。
>>>np.logical_or(score[0]>90,score[1]>90,score[2]>90) #等價于(score[0]>90) | (score[1]>90) | (score[2]>90),布爾表達式要有括號 array([ True, True, False, False, False]) #可以判斷語文、數學成績有大于90分的
np.logical_or()函數的參數是2個及以上。
查看某同學的成績不在70~80分的課程。
>>>np.logical_not(score[0]>=70, score[0]<80) array([ True, False, False, True, False])
np.logical_not()函數的參數是1個及以上。
3.NumPy的np.where()函數
np.where()函數其實是一個三元運算符。函數滿足條件返回一個值,反之返回另一個值。
【動動手練習1-14】 數組條件運算
判斷前4位同學的前4門課程是否及格,成績大于60(及格)置為1,否則(不及格)置為0。
>>>temp = score[:4, :4] >>>np.where(temp > 60, 1, 0) array([[1, 1, 1, 1], [1, 1, 1, 0], [1, 1, 1, 0], [0, 1, 0, 1]])
復合邏輯運算則需要結合np.logical_and()函數和np.logical_or()函數使用,例如判斷前4名學生的前4門課程的成績,成績大于60且小于90置為1,否則置為0。
>>>np.where(np.logical_and(temp > 60, temp < 90), 1, 0) array([[1, 0, 1, 1], [0, 1, 1, 0], [1, 0, 1, 0], [0, 1, 0, 1]])
1.3.3 離散差分函數和梯度函數
1.離散差分(差值)函數np.diff()
np.diff()函數的原型:np.diff(a, n=1,axis=1),其作用是求矩陣數組中后一個元素減去前一個元素的差值。各個參數的說明如下。
● a:輸入的矩陣數組。
● n:可選,代表要執行幾次差值運算。默認是1。
● axis:默認axis=1,表示按列相減(后一列減前一列);axis=0時表示按行相減(后一行減前一行)。如此,每執行一次差值運算就比原有的列或行少一列或一行。
【例題1-5】 求差分
>>>import numpy as np >>>score=np.random.randint(46,100,(50,5)) >>>a=score[4:8,:] #取一個4行5列的矩陣數組 >>> a array([[97, 98, 78, 77, 95], [64, 70, 90, 98, 54], [99, 88, 68, 81, 91], [58, 59, 96, 91, 58]]) >>>np.diff(a) #按列相減,進行一次差值運算 array([[ 1, -20, -1, 18], #跨列相減,結果為4行4列(比原來少一列) [ 6, 20, 8, -44], [-11, -20, 13, 10], [ 1, 37, -5, -33]]) >>>np.diff(a,axis=0) #按行相減,進行一次差值運算 array([[-33, -28, 12, 21, -41], #跨行相減,結果為3行5列(比原來少一行) [ 35, 18, -22, -17, 37], [-41, -29, 28, 10, -33]]) >>>np.diff(a,n=2,axis=0) #按行相減,進行2次差值運算,就是對上一個結果再進行差值運算 array([[ 68, 46, -34, -38, 78], #結果為2行5列(比原來少2行) [-76, -47, 50, 27, -70]])
定義的參數n大于1時,表示將進行多次差值運算,就是在上一次差值運算的矩陣基礎上再進行差值運算,直到n次為止。讀者可以自行完成多次行差值操作。
2.梯度函數np.gradient()
np.gradient(f):用于計算數組f中元素的梯度,當f為多維時,返回每個維度的梯度。返回的結果和原始數組大小相同。
梯度的計算過程:對于一維的數組,兩個邊界的元素直接用后一個值減去前一個值,得到梯度,即b?a;對于中間的元素,取相鄰兩個元素差的一半,即(c?a)/2。
【例題1-6】 求梯度
>>>score[0] #得到一個一維數組 array([69, 96, 72, 68, 87]) >>>np.gradient(score[0]) array([ 27. , 1.5, -14. , 7.5, 19. ])
對于二維數組:分別計算2個維度上的梯度,每個維度上的梯度和上面的一維數組梯度求法相同。對于二維數組,任意一個元素的梯度存在兩個方向,所以求得的梯度為兩個數組對象,第一個數組表示最外層維度的梯度值,第二個數組表示第二層維度的梯度值。即二維數組求梯度值的結果是包含兩個ndarray數組的列表,第一個列表是按列(維度)求梯度獲得,第二個列表是按行(維度)求梯度獲得。不論按列還是按行求梯度,其方法與一維求梯度一致。
>>>score[:4,:4] array([[69, 96, 72, 68], [97, 65, 78, 53], [83, 97, 66, 55], [55, 81, 58, 80]]) >>>np.gradient(score[:4,:4]) #返回一個列表,列表中有兩個數組 [array([[ 28. , -31. , 6. , -15. ], #按列求梯度獲得的數組 [ 7. , 0.5, -3. , -6.5], [-21. , 8. , -10. , 13.5], [-28. , -16. , -8. , 25. ]]), array([[ 27. , 1.5, -14. , -4. ], #按行求梯度獲得的數組 [-32. , -9.5, -6. , -25. ], [ 14. , -8.5, -21. , -11. ], [ 26. , 1.5, -0.5, 22. ]])]
對于n維數組,np.gradient()函數會生成n個數組,每個數組代表元素在第n個維度的梯度變化值。梯度反映了元素的變化率,尤其是在進行圖像、聲音等數據處理時,梯度有助于我們發現圖像和聲音的邊緣。
1.3.4 隨機函數
1.np.random.rand()函數
np.random.rand()函數表示根據給定維度生成[0,1)的數據,包含0,不包含1。該函數的一般格式:np.random.rand(d0,d1,…,dn)。其中,dn表示表格的每個維度。
該函數的返回值為指定維度的數組。
【動動手練習1-15】 使用隨機函數
np.random.rand() #沒有參數時,返回單個數據 0.49622070976935806 np.random.rand(4) #shape:4,生成一維數組 Out[20]: array([0.73473476, 0.91185891, 0.25690118, 0.15300424]) np.random.rand(4,2) #shape:4*2,生成二維數組 array([[0.22766791, 0.44004844], [0.77363055, 0.41738285], [0.4954431 , 0.94661826], [0.98884195, 0.66583906]]) np.random.rand(4,3,2) #shape: 4*3*2,生成三維數組 array([[[0.13606573, 0.75197037], [0.10787889, 0.56756818], [0.05749478, 0.21269762]], [[0.16066188, 0.77395856], [0.21734109, 0.8403221 ], [0.15336456, 0.08972729]], [[0.48081287, 0.65475862], [0.8804478 , 0.56230535], [0.5931349 , 0.61528502]], [[0.3535239 , 0.76732365], [0.12317966, 0.6788728 ], [0.84390425, 0.0316394 ]]])
2.np.random.randn()函數
np.random.randn()函數表示返回一個或一組樣本,其具有標準正態分布。該函數的一般格式:np.random.randn(d0, d1,…,dn)。其中,dn表示表格的每個維度。
該函數返回值為指定維度的數組。
標準正態分布是以0為均值、以1為標準差的正態分布,記為N(0,1)。
np.random.randn() #沒有參數時,返回單個數據 -1.1241580894939212 np.random.randn(3) array([ 1.2128837 , 1.13688113, -0.13342453]) np.random.randn(2,4) array([[-1.61193815, -0.75167637, 0.72141234, -1.19118825], [-1.11790307, 0.11534838, 0.51955485, -2.15917405]])
隨機生成的值基本是?3~+3,但這也不絕對,主要是結果滿足標準差的正態分布。
3.np.random.randint()
np.random.randint()函數表示隨機生成整數(或浮點數)數據。該函數的一般格式:np.random.randint(low, high=None, size=None, dtype='l'),取值范圍為[low,high),包含low,不包含high。各參數說明如下。
● low為最小值,high為最大值。
● size為數組維度的大小。
● dtype為數據類型,默認的數據類型是np.int。
沒有填寫high時,默認生成隨機數的范圍是[0,low)。
np.random.randint(1,5) #返回1個[1,5)的隨機整數 4 np.random.randint(1,5,3) #返回3個[1,5)隨機整數的數組 array([1, 1, 3]) np.random.randint(-5,5,size=(2,2)) #返回一個二維數組 array([[ 2, -1], [ 2, 0]])
4.偽隨機數生成器
在機器學習中,生成隨機數通常使用偽隨機數生成器np.random. RandomState(),要想復現具備隨機性的代碼的最終結果,需要設置相同的種子值。
import numpy as np rng = np.random.RandomState(0) #設定隨機種子值,此時設置為0,也可以是任意整數 rng.rand(4) #產生4個隨機數,空括號則表示產生一個隨機數 Out[377]: array([0.5488135 , 0.71518937, 0.60276338, 0.54488318]) rng = np.random.RandomState(0) #隨機種子數相同,結果相同 rng.rand(4) Out[379]: array([0.5488135 , 0.71518937, 0.60276338, 0.54488318])
上面的代碼生成了一樣的隨機數組。下面是另一種順序的操作。
rng = np.random.RandomState(100) #隨機種子數為100 rng.rand(4) Out[35]: array([0.54340494, 0.27836939, 0.42451759, 0.84477613]) rng.rand(4) Out[36]: array([0.00471886, 0.12156912, 0.67074908, 0.82585276]) rng = np.random.RandomState(100) rng.rand(4) Out[38]: array([0.54340494, 0.27836939, 0.42451759, 0.84477613]) rng.rand(4) Out[39]: array([0.00471886, 0.12156912, 0.67074908, 0.82585276])
因為np.random.RandomState()是偽隨機數,所以必須在rng這個變量下使用,如果不這樣做,那么就不能得到相同的隨機數組。在使用rng這個變量前要先定義,定義之后生成隨機數的結果才有順序關系。
1.3.5 其他常用函數
其他常用函數還包括數學函數、統計函數等,見表1-2。
表1-2 其他常用函數

續表
