最近在百奧智匯兼職,基本上比較重的工作就在數據處理,所以pandas和numpy用的比較多。
不知不覺中,pandas各種函數越用越熟練,但是總要靠結果來推算到底應該指定axis=0還是1,你有沒有這種經歷呢?
經過摸索,我找到了一種axis利於記憶也好解釋的理論。下面一起來看看吧!
核心內容axis是你要操作的軸。
pandas導入包,創建一個3X4的dataframe。
import pandas as pdimport numpy as npdata = pd.DataFrame(np.random.randn(4,3))out:
0 -0.4292781 0.4159852 1.5554183 3.364704dtype: float64axis=1,說明我們要對第二個軸進行操作。
操作中處理的是第二個軸一共3個值,3個值被消滅了,被1個和值取代,結果是長度為4的series。
out:
020-0.0026170.34558510.273499-0.38634522.6024320.28416931.5703471.656065同樣對第二個軸進行操作。
處理的是第二個軸3個值,3個值被drop掉1列後變為2個值,結果是4X2的dataframe。
data_ = pd.DataFrame(np.random.randn(4,3))pd.concat([data,data_],axis=1)out:
0120120-0.002617-0.7722460.345585-0.349359-0.033281-0.77437810.2734990.528832-0.386345-1.6307380.773259-0.95317722.602432-1.3311830.2841691.7144360.1155642.48048931.5703470.1382921.6560650.2291221.4896283.029022處理的是第二個軸,data二軸3個值,拼接的data_二軸也為3個值,所以結果是4X6的dataframe。
data.sort_values([0],axis=1)out:
1020-0.772246-0.0026170.34558510.5288320.273499-0.3863452-1.3311832.6024320.28416930.1382921.5703471.656065處理的是第二個軸3個值,對第一個軸name為0對應的3個值進行排序,從小到大,結果是4X3的dataframe。
來個更複雜的下面為常見的歸一化:
data.apply(lambda a:(a-np.min(a))/(np.max(a)-np.min(a)),axis=1)out:
01200.6885020.01.00000010.7210011.00.00000021.0000000.00.41065330.9435240.01.000000處理的是第二個軸3個值,對第一軸每一個name對應的三個值進行歸一化處理,結果是4X3的dataframe 。
強行輸出就會看的更清晰:
data.apply(lambda a:print(a),axis=1)0 -0.0026171 -0.7722462 0.345585Name: 0, dtype: float640 0.2734991 0.5288322 -0.386345Name: 1, dtype: float640 2.6024321 -1.3311832 0.284169Name: 2, dtype: float640 1.5703471 0.1382922 1.656065Name: 3, dtype: float64out:
0 None1 None2 None3 Nonedtype: objectlambda函數沒有指定返回值,所以默認返回None,結果是長度為4全為None的series。
apply函數可以實現非常多的自定義操作,也可以拿來自己實現sum, sort, drop等操作,每次輸入的都是n個值,返回1個值最後為series,返回n個值最後則為dataframe。
pandas中的axis是基於numpy的, 所以上面的概念在numpy中也適用。
numpy其實numpy難的地方在於多維,下面來看一個三維的例子:
import numpy as npdata = np.arange(0, 24).reshape((2,3,4)) print(data.shape)dataout:
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]]])
rollaxis是軸滾動的意思,axis=n,將n軸移到0軸。
data = np.arange(0, 24).reshape((2,3,4))data = np.rollaxis(data,axis=2) print(data.shape)dataout:
array([[[ 0, 4, 8], [12, 16, 20]],
[[ 1, 5, 9], [13, 17, 21]],
[[ 2, 6, 10], [14, 18, 22]],
[[ 3, 7, 11], [15, 19, 23]]])將最後一個軸移到最前面,其實就是挨個取最後一層的4個值,組成第一層,內部就是2X3的矩陣。
data = np.arange(0, 24).reshape((2,3,4))data = np.rollaxis(data,axis=1) print(data.shape)dataout:
array([[[ 0, 1, 2, 3], [12, 13, 14, 15]],
[[ 4, 5, 6, 7], [16, 17, 18, 19]],
[[ 8, 9, 10, 11], [20, 21, 22, 23]]])將倒數第二個軸移到最前面,其實就是把最後一層4個值當成一個對象進行處理,挨個取第二層3個值,組成第一層,最後內部就是2X4的矩陣。
swapaxes是軸交換的意思,m, n,將m軸與n軸交換。
data = np.arange(0, 24).reshape((2,3,4))data = np.swapaxes(data,0,1)print(data.shape)dataout:
array([[[ 0, 1, 2, 3], [12, 13, 14, 15]],
[[ 4, 5, 6, 7], [16, 17, 18, 19]],
[[ 8, 9, 10, 11], [20, 21, 22, 23]]])結果為3,2,4,把最後一層4個值當成一個對象,實現的其實就是前面3, 2的轉置。
data = np.arange(0, 24).reshape((2,3,4))data = np.swapaxes(data,0,2)print(data.shape)dataout:
array([[[ 0, 12], [ 4, 16], [ 8, 20]],
[[ 1, 13], [ 5, 17], [ 9, 21]],
[[ 2, 14], [ 6, 18], [10, 22]],
[[ 3, 15], [ 7, 19], [11, 23]]])結果為4,3,2,挨個取最後一層4個值,最後一層為第一層每次的2個值。
transpose 轉置
data = np.arange(0, 24).reshape((2,3,4))data = np.transpose(data,(1,2,0))print(data.shape)dataout:
array([[[ 0, 12], [ 1, 13], [ 2, 14], [ 3, 15]],
[[ 4, 16], [ 5, 17], [ 6, 18], [ 7, 19]],
[[ 8, 20], [ 9, 21], [10, 22], [11, 23]]])轉置,2,3,4經過1,2,0的取值後為3,4,2,第一層移到最後。
np.newaxis可以強行增加新軸。
data = np.arange(0, 24).reshape((2,3,4))data = data[:,np.newaxis,:,:]print(data.shape)dataout:
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]]]])思考遇到點有意思的結果,不如大家一起思考一下:
array = np.array([['hello world','sssimon yang']]) print(array.shape)np.apply_along_axis(lambda a:[i.split(' ')[0] for i in a],axis=0,arr=array)out:
array([['hello', 'sssim']], dtype='<U5')np.apply_along_axis(lambda a:[i.split(' ')[0] for i in a],axis=1,arr=array)out:
array([['hello', 'sssimon']], dtype='<U7')為什麼兩次的結果會不一樣呢?歡迎在評論區給出你的答案。
感謝大家原文使用jupyterlab,out為jupyterlab每個cell的默認輸出。謝謝大家!