前面知道NumPy是 Python 語言的一個擴展程式庫,支持大量的維度數組與矩陣運算,也針對數組運算提供大量的數學函數庫。numpy是基於c語言開發,所以這使得numpy的運行速度很快,高效率運行就是numpy的一大優勢。但numpy的特長並不是在於數據處理,而是在於能非常方便地實現科學計算,所以 ...
前面知道NumPy是 Python 語言的一個擴展程式庫,支持大量的維度數組與矩陣運算,也針對數組運算提供大量的數學函數庫。numpy是基於c語言開發,所以這使得numpy的運行速度很快,高效率運行就是numpy的一大優勢。但numpy的特長並不是在於數據處理,而是在於能非常方便地實現科學計算,所以對數據進行處理時用的numpy情況並不是很多,因為需要處理的數據一般都是帶有列標簽和index索引的,而numpy並不支持這些,這時就需要pandas了,Pandas的主要工作就是做數據分析,pandas繼承了numpy 我們要使用的是pandas而不是numpy。Pandas是基於Numpy構建的庫,在數據處理方面可以把它理解為numpy加強版 。
數據分析中:樣本是(行) 特征是(列)。
pandas的優缺點。優點:pandas相比於Excel,matlab,tableau等更加的靈活,處理大數據的問題上更加有優勢,讀取excel文件的時候,pandas更加快,處理速度快。缺點:操控方面相對比較僵硬,pandas當中的函數要清晰使用,statsmodels統計庫(bug百出,官網提供的文檔大部分不友好),scipy高數(stats,使用方法太繁瑣)。
pandas的處理速度。為什麼不用mysql? 慢:文件操作慢;pandas:快在於將數據載入到記憶體了。
數據分析使用的庫:numpy作為依賴庫;pandas數據分析庫;matplotlib直觀的數據可視化庫;seaborn輔助庫(庫中含有調色板),圖形更加豐富;pyecharts:簡易的數據可視化庫,電商中比較常用;,,,。
pandas中有兩大數據類型。Series 級數(索引是有序的,一維的);DataFrame 結構化數據(二維的表)。
1. Series級數
Series是一種類似一維數組的數據結構,由一組數據和與之相關的index組成,即由values:一組數據(ndarray類型) 和 key:相關的數據索引標簽兩個部分組成。這個結構一看似乎與dict字典差不多,我們知道字典是一種無序的數據結構,而pandas中的Series的數據結構不一樣,它相當於定長有序的字典,並且它的index和value之間是獨立的,兩者的索引還是有區別的,Series的index是可變的,而dict字典的key值是不可變的。Series是將 序列 和 hash 融合在一起了。序列:索引有序,索引是枚舉類型;hash:鍵是無序的,鍵是關聯類型的。pandas中的兩大數據類型都可以使用對象和屬性的方式來獲取值和賦值,在pandas中,string也是object。
Series的創建 :
可由列表或numpy數組創建:預設索引為0到N-1的整數型索引。(list,tuple,dict,ndarry)強制轉換為Series類型 。
1 # 由列表創建,預設索引為0到4的整數型索引 2 s0 = Series([1,2,3,4,5]) 3 s0[1] # 2
4 # 由numpy數組創建 5 s1 = Series(np.array(list('ABCD'))) 6 7 # 由字典(hash)創建,字典的key會被Series當作是index 8 s2 = Series({'A':1,"B":2,"C":3}) 9 10 # 通過設置index參數指定索引 --> {a:甲,b:乙,c:} 11 s3 = Series(data=list('甲乙丙丁'),index=list('abcd'))
Series的索引和切片:
1). 常規索引:可以使用中括弧取單個索引(此時返回的是元素類型),或者中括弧里一個列表取多個索引(此時返回的仍然是一個Series類型)。
2). 顯式索引:
- 使用index中的關聯類型作為索引值;- 使用.loc[](推薦)。可以理解為pandas是ndarray的升級版,但是Series也是dict的升級版
3). 隱式索引:
- 使用整數作為索引值;- 使用.iloc[](推薦)
1 # 常規索引 2 s3[0] # ‘甲’ 3 s3['a'] # ‘甲’ 4 5 # 顯式索引 6 s3.loc['a'] # ‘甲’ 7 8 # 隱式索引 9 s3.iloc[0] # ‘甲’
4). 切片:
1 # 常規切片,左閉右開 2 s3[0:-1] 3 # a 甲 4 # b 乙 5 # c 丙 6 # Name: username, dtype: object 7 8 # 顯式切片,全閉區間 9 s3.loc['a':'d'] 10 # a 甲 11 # b 乙 12 # c 丙 13 # d 丁 14 # Name: username, dtype: object 15 16 # 隱式切片,左閉右開 17 s3.iloc[0:-1] 18 # a 甲 19 # b 乙 20 # c 丙 21 # Name: username, dtype: object
Series的屬性:
可以把Series看成一個定長的有序字典。
1 ''' 2 ndim:維度 3 shape:形狀 4 size:獲取元素的長度 5 dtype:數據類型 6 index:獲取所有的索引 7 values:獲取所有的值 8 name:獲取名稱 9 head():快速查看Series對象的樣式,獲取前5條數據 10 tail():快速查看Series對象的樣式,獲取最後5條數據 11 '''
代碼演示示例:
1 s3.shape # (4,) 2 s3.size # 4 3 s3.ndim # 1 4 s3.name # 'username' 5 s3.dtype # dtype('O') 表示字元串類型 6 s3.index # Index(['a', 'b', 'c', 'd'], dtype='object') 7 s3.keys() # Index(['a', 'b', 'c', 'd'], dtype='object') 8 s3.valuse # array(['甲', '乙', '丙', '丁'], dtype=object) 9 s3.head(n=5) 10 s3.tail(n=5)
檢測缺失數據:
當索引沒有對應的值時,可能出現缺失數據顯示NaN(not a number)的情況。註意:np.NaN !== np.NaN;可以使用pd.isnull(),pd.notnull(),或自帶isnull(),notnull()函數檢測缺失數據。
1 # 造一含有NaN值的Series數據 2 s5 = Series(data=range(4),index=list('abcd')) # NaN是float 3 s5['c'] = np.nan # 將索引c 的值變為nan 4 s5 5 # a 0.0 6 # b 1.0 7 # c NaN 8 # d 3.0 9 # dtype: float64 10 11 # 檢測缺失數據 12 cond = pd.isnull(s5) # 相當於s5.isnull() 13 cond 14 # a False 15 # b False 16 # c True 17 # d False 18 # dtype: bool 19 # 檢查到NaN值之後,將nan值的數據變成 0 20 s5[cond]= 0 21 # a 0.0 22 # b 1.0 23 # c 0.0 24 # d 3.0 25 # dtype: float64 26 27 s5['c'] = np.nan # 將索引c 的值變為nan 28 29 # 檢測缺失數據 30 cond_fa = s5.notnull() # 相當於pd.notnull(s5) 31 cond_fa 32 # a True 33 # b True 34 # c False 35 # d True 36 # dtype: bool 37 # 檢查到NaN值之後,將nan值篩選掉 38 s5[cond_fa] 39 # a 0.0 40 # b 1.0 41 # d 3.0 42 # dtype: float64
Series之間的運算:
NaN+任何值都是NaN。在運算中自動對齊不同索引的數據,如果索引不對應,則補NaN。
1 s5 * 3 2 # a 0.0 3 # b 3.0 4 # c 0.0 5 # d 9.0 6 # dtype: float64 7 8 s6 = Series(range(5),list('bcdef')) 9 10 s5.add(s6) # 相當於 s5+s6 11 # a NaN 12 # b 1.0 13 # c 1.0 14 # d 5.0 15 # e NaN 16 # f NaN 17 # dtype: float64
2. DataFrame
DataFrame是一個【表格型】的數據結構,可以看做是【由Series組成的字典】(共用同一個索引)。DataFrame由按一定順序排列的多列數據組成。設計初衷是將Series的使用場景從一維拓展到多維。DataFrame既有行索引,也有列索引。行索引:index;列索引:columns;值:values(numpy的二維數組)。我們的 訓練集(一些二維的數據)都是二維的,那麼Series滿足不了這個條件,xy軸,軸上的一點(0,0)。DataFrame每一列可以是不同類型的值集合,所以DataFrame你也可以把它視為不同數據類型同一index的Series集合。
DataFrame的創建:
最常用的方法是傳遞一個字典來創建。DataFrame以字典的鍵作為每一【列】的名稱,以字典的值(一個數組)作為每一列的值。此外,DataFrame會自動加上每一行的索引(和Series一樣)。同Series一樣,若傳入的列與字典的鍵不匹配,則相應的值為NaN。
1 df1 = DataFrame(data={'數學':[10,20,30,40,50], 2 '語文':[1,2,3,4,5], 3 '英語':[10,11,12,13,14]}, 4 index=['Tom','Jhon','Jack','Marry','Jurray'], 5 columns=['英語','數學','語文']) 6
# 英語 數學 語文 7 # Tom 10 10 1 8 # Jhon 11 20 2 9 # Jack 12 30 3 10 # Marry 13 40 4 11 # Jurray 14 50 5
DataFrame屬性:
values、columns、index、shape、ndim、dtypes。
1 # 行索引 2 df1.index # Index(['雷軍', '不知妻美', '不知爹富', '馬雲', '羅太軍'], dtype='object') 3 4 # 列索引 5 df1.columns # Index(['英語', '數學', '語文'], dtype='object') 6 7 df1.dtypes 8 # 英語 int64 9 # 數學 int64 10 # 語文 int64 11 # dtype: object 12 13 df1.size # 15
14 df1.ndim # 2
DataFrame的索引:
1). 對列進行索引(獲取某一列): [ ] 預設只能取列索引。- 通過類似字典的方式;- 通過屬性的方式。可以將DataFrame的列獲取為一個Series。返回的Series擁有原DataFrame相同的索引,且name屬性也已經設置好了,就是相應的列名。
df1['語文'] ---> 獲取‘語文’列
2). 對行進行索引(獲取某一行):- 使用.loc[]加index來進行行索引;- 使用.iloc[]加整數來進行行索引。同樣返回一個Series,index為原來的columns。
df1.loc['Tom'] ---> 獲取‘Tom’行
df1.iloc[0] ---> 獲取第0行,等於‘Tom’行
3). 對元素進行索引(獲取某一個元數/值):- 使用列索引;- 使用行索引(iloc[3,1]相當於兩個參數;iloc[[3,3]] 裡面的[3,3]看做一個參數);- 使用values屬性(二維numpy數組)
df1.loc['Tom','英語'] ---> 獲取‘Tom’行,‘英語’列的這個元素的值
df1.iloc[0,0] ---> 獲取第0行,第0列的這個元素的值,和df1.loc['Tom','英語']結果一樣
1 # 對列進行索引, [ ] 預設只能取列索引 2 df1['語文'] # 獲取為一個Series ,相當於【 df1.語文 】 3 # Tom 1 4 # Jhon 2 5 # Jack 3 6 # Marry 4 7 # Jurray 5 8 # Name: 語文, dtype: int64 9 10 df1.語文 # 不建議這樣獲取列 11 df1['Tom'] # 會報錯 12 13 14 # 對行進行索引 15 df1.loc['Tom'] # 顯式loc 16 # 英語 10 17 # 數學 10 18 # 語文 1 19 # Name: Tom, dtype: int64 20 21 df1.iloc[0] # 隱式iloc 22 # 英語 10 23 # 數學 10 24 # 語文 1 25 # Name: Tom, dtype: int64 26 27 # 對元素進行索引 28 df1.loc['Tom','英語'] # 10 29 30 df1.iloc[0,0] # 10
4). 切片操作:
獲取某些行和某些列的值,可以是多個值
1 # 使用行索引顯式loc切片,全閉區間 2 df1.loc['Tom':'Jack'] # 獲取Tom到Jack行的數據,針對行 3 # 英語 數學 語文 4 # Tom 10 10 1 5 # Jhon 11 20 2 6 # Jack 12 30 3 7 8 df1.loc['Tom':'Jack','英語':'數學'] # 獲取Tom到Jack行,英語到數學列的數據 9 # 英語 數學 10 # Tom 10 10 11 # Jhon 11 20 12 # Jack 12 30 13 14 15 # 使用行索引隱式iloc切片,左開右閉 16 df1.iloc[1:2] # 獲取第1行到第2行的數據(不包含第2行),針對行 17 # 英語 數學 語文 18 # Jhon 11 20 2 19 20 df1.iloc[0:2 , 0:2] # 獲取第0行到第2行,第0列到第2列的數據(不包含第2行和第2列) 21 # 英語 數學 22 # Tom 10 10 23 # Jhon 11 20
DataFrame的運算:
Dataframe的運算同Series一樣。
下圖是Python 操作符與pandas操作函數的對應表:
Series與DataFrame之間的運算:
使用pandas操作函數:axis=0:以列為單位操作(參數必須是列),對所有列都有效;axis=1:以行為單位操作(參數必須是行),對所有行都有效。
列方向:df1.add(s) #預設列相加;行方向: (df1.T + s).T。
處理丟失的數據:
df1.loc['Tom','英語'] = np.NaN
df1.loc['Jack','數學'] = np.NaN
pandas 中對於空的操作:
isnull():是空值,notnull():不是空值,dropna() :過濾空值,fillna() :填充空值。
數據分析:刪除行比較合適,行代表的是一條數據,列會影響到所有的數據。機器學習:如果是行當中的空值比較多那就刪行,列中空值比較多就刪列。
1 # 判斷是否為空值 2 df1.loc[:,'英語'].isnull() 3 # Tom True 4 # Jhon True 5 # Jack True 6 # Marry True 7 # Jurray True 8 # Name: 英語, dtype: bool 9 10 # 當該行中所有的元素都為空則刪除 11 df1.dropna(how='all') 12 13 # 當該行中所有的元素都為空則刪除 14 df1.dropna(how='any',axis=1,inplace=True) 15 16 # 填充空值 17 df1.fillna(value=None, method=None, axis=None, inplace=False, limit=None, #downcast=None, **kwargs)
聚合操作:
所謂的聚合操作:平均數,標準方差,最大值,最小值……
1 df1.sum() # 預設是對列進行操作 2 df1.mean() # 預設是對列進行操作 3 df1.max() # 求列的最大值 4 df1.var() # 樣本方差,表示的數據的波動性 5 df1.std() # 樣本標準差
pandas的拼接操作:
pandas的拼接分為兩種:級聯:pd.concat, pd.append;合併:pd.merge, pd.join。
回顧numpy的級聯:
1 np.concatenate([np.random.randint(0,100,(5,4)),np.random.rand(5,4),np.random.randn(5,4)],axis=1)
1). 簡單級聯:
行合併:pd.concat([df1,df2],axis=0)。和np.concatenate一樣,優先增加行數(預設axis=0)。註意index在級聯時可以重覆。
列合併:pd.concat([df1,df2],axis=1)。不建議用,concat它不是聯表查詢,只擅長當union(垂直的 axis=0),水平合併一定不要用。
1 # 垂直的內連接,join='inner' ,會刪除含有NaN的行或列 2 pd.concat([df1,df2],axis=0,join='inner') # index在級聯時可以重覆 3 4 # 水平內連接 5 pd.concat([df1,df2],axis=1,join='inner') 6 7 # 外連接,不匹配的項補NaN 8 pd.concat([df1,df2],axis=0,join='outer') 9 10 # ignore_index=True忽略重覆索引 11 pd.concat([df1,df2],axis=0,join='outer',ignore_index=True) 12 13 # 使用多層索引 keys ,解決重覆問題 14 pd.concat([df1,df2],axis=0,join='outer',keys=['df1','df2']) 15 # a b c 16 # df1 0 a0 b0 c0 17 # 1 a1 b1 c1 18 # 2 a2 b2 c2 19 # df2 2 a2 b2 c2 20 # 3 a3 b3 c3 21 # 4 a4 b4 c4
2). 不匹配級聯:
不匹配指的是級聯的維度的索引不一致。例如縱向級聯時列索引不一致,橫向級聯時行索引不一致;有3種連接方式:
- 外連接:補NaN(預設模式)
- 內連接:只連接匹配的項
-連接指定軸 join_axes 顯示某一格dataframe 中的列
3).使用append()函數添加:
由於在後面級聯的使用非常普遍,因此有一個函數append專門用於在後面添加,append 和 concat 相似,只能直接做垂直:df1.append(df2)
4). 使用pd.merge()合併:
merge與concat的區別在於,merge需要依據某一共同的行或列來進行合併,使用pd.merge()合併時,會自動根據兩者相同column名稱的那一列,作為key來進行合併。註意每一列元素的順序不要求一致
pd.merge(DataFrame1,DataFrame2, how=‘inner’, on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=True, suffixes=(’_x’, ‘_y’))
pd.merge(DataFrame1,DataFrame2) == DataFrame1.merge(DataFrame2)
參數:
how:預設為inner,可設為inner/outer/left/right
on:根據某個欄位進行連接,必須存在於兩個DateFrame中(若未同時存在,則需要分別使用left_on和right_on來設置)
left_on:左連接,以DataFrame1中用作連接鍵的列
right_on:右連接,以DataFrame2中用作連接鍵的列
left_index:將DataFrame1行索引用作連接鍵
right_index:將DataFrame2行索引用作連接鍵
sort:根據連接鍵對合併後的數據進行排列,預設為True
suffixes:對兩個數據集中出現的重覆列,新數據集中加上尾碼_x,_y進行區別
代碼演示區別:
1 pd.DataFrame({'lkey':['foo','bar','baz','foo'], 'value':[1,2,3,4]}) 2 # lkey value 3 # 0 foo 1 4 # 1 bar 2 5 # 2 baz 3 6 # 3 foo 4 7 8 pd.DataFrame({'rkey':['foo','bar','qux','bar'], 'value':[5,6,7,8]}) 9 # rkey value 10 # 0 foo 5 11 # 1 bar 6 12 # 2 qux 7 13 # 3 bar 8 14 15 # inner鏈接 16 dataDf1.merge(dataDf2, left_on='lkey',right_on='rkey') 17 # lkey value_x rkey value_y 18 # 0 foo 1 foo 5 19 # 1 foo 4 foo 5 20 # 2 bar 2 bar 6 21 # 3 bar 2 bar 8 22 23 # Outer鏈接 24 dataDf1.merge(dataDf2, left_on='lkey', right_on='rkey', how='outer') 25 # lkey value_x rkey value_y 26 # 0 foo 1.0 foo 5.0 27 # 1 foo 4.0 foo 5.0 28 # 2 bar 2.0 bar 6.0 29 # 3 bar 2.0 bar 8.0 30 # 4 baz 3.0 NaN NaN 31 # 5 NaN NaN qux 7.0 32 33 # left鏈接 34 dataDf1.merge(dataDf2, left_on='lkey', right_on='rkey',how='left') 35 # lkey value_x rkey value_y 36 # 0 foo 1 foo 5.0 37 # 1 bar 2 bar 6.0 38 # 2 bar 2 bar 8.0 39 # 3 baz 3 NaN NaN 40 # 4 foo 4 foo 5.0 41
41 # right鏈接 42 dataDf1.merge(dataDf2, left_on='lkey', right_on='rkey',how='right') 43 # lkey value_x rkey value_y 44 # 0 foo 1.0 foo 5 45 # 1 foo 4.0 foo 5 46 # 2 bar 2.0 bar 6 47 # 3 bar 2.0 bar 8 48 # 4 NaN NaN qux 7
【註意】1).當有多個key相同時使用,使用on=顯式指定哪一列為key;當左右兩邊的key都不相等時,使用left_on和right_on指定左右兩邊的列作為key。
2).內合併:只保留兩者都有的key(預設模式);外合併 how='outer':補NaN;左合併、右合併:how='left',how='right'。
列衝突的解決:
當列衝突時,即有多個列名稱相同時,需要使用on=來指定哪一個列作為key,配合suffixes指定衝突列名,可以使用suffixes=自己指定尾碼。
1 dataDf1.merge(dataDf2, left_on='lkey', right_on='rkey', how='right', suffixes=('_df1', '_df2')) 2 # lkey value_df1 rkey value_df2 3 # 0 foo 1.0 foo 5 4 # 1 foo 4.0 foo 5 5 # 2 bar 2.0 bar 6 6 # 3 bar 2.0 bar 8 7 # 4 NaN NaN qux 7
pandas刪除操作:
Dataframe.drop(labels=0,axis=0,inplace=True):labels=0表示 第0行 ,inplace=True表示對原數據 產生影響。
1 df1.drop(labels=0,axis=0,inplace=True) # 刪除第0行 2 df1.drop(0) # 刪除第0行 3 df1.drop([0,1]) # 刪除第0,1行
行重新設定:
Dataframe.set_index('id',inplace=True)
1 dataDf1 2 # lkey value 3 # 0 foo 1 4 # 1 bar 2 5 # 2 baz 3 6 # 3 foo 4 7 8 dataDf1.set_index(['value'],inplace=True) # 將'value'設置為index 9 dataDf1 10 # lkey 11 # value 12 # 1 foo 13 # 2 bar 14 # 3 baz 15 # 4 foo 16 17 dataDf1.reset_index(inplace=True) # 將index返回回dataframe中 18 dataDf1 19 # value lkey 20 #