Pandas入門
pandas的數據結構介紹
我們將使用下面的方式導入pandas:
import pandas as pdfrom pandas importSeries,DataFrame
Series
Series是一種類似於一維數組的對象,它由一組數據(各種NumPy數據類型)以及一組與之相關的數據標籤(即索引)組成。由一組數據就可產生最簡單的Series:
In[6]: obj = pd.Series([4,7,-5,3])In[7]: objOut[7]:04172-533dtype: int64
Series的字元串表現為:索引在左邊,值在右邊。由於沒有為數據指定索引,於是會自動創建一個0到N-1(N為數據的長度)的整數索引。可以通過Series的values和index屬性獲取其數組表示形式和索引對象:
In[8]: obj.valuesOut[8]: array([4,7,-5,3], dtype=int64)In[9]: obj.indexOut[9]:RangeIndex(start=0, stop=4, step=1)
通常,我們希望創建的Series帶有一個可以對各個數據點進行標記的索引:
In[10]: obj2 = pd.Series([4,7,-5,3],index=[d,b,a,c])In[12]: obj2Out[12]:d 4b 7a -5c 3dtype: int64
與普通NumPy數組相比,可以通過索引的方式選取Series中的單個或一組值:
In[13]: obj2[a]Out[13]:-5In[15]: obj2[d]=7In[18]: obj2[[c,a,d]]Out[18]:c 3a -5d 7dtype: int64
NumPy數組運算(如根據布爾型數組進行過濾、標量乘法、應用數學函數等)都會保留索引和值之間的連接:
In[19]: obj2Out[19]:d 7b 7a -5c 3dtype: int64In[21]: obj2[obj2>0]Out[21]:d 7b 7c 3dtype: int64In[22]: obj2*2Out[22]:d 14b 14a -10c 6dtype: int64In[23]: np.exp(obj2)Out[23]:d 1096.633158b 1096.633158a 0.006738c 20.085537dtype: float64
還可以將Series看成是一個定長的有序字典,因為它是索引值到數據值的一個映射。
In[24]:bin obj2Out[24]:TrueIn[25]:ein obj2Out[25]:False
如果數據放在一個字典中,也可以通過這個字典來創建Series,索引就是原字典的鍵:
In[26]: sdata ={Ohio:35000,Texas:71000,Oregon:16000,Utah:5000}In[27]: obj3 = pd.Series(sdata)In[28]: obj3Out[28]:Ohio35000Oregon16000Texas71000Utah5000dtype: int64
再看一個例子:
In[30]: states =[California,Ohio,Oregon,Texas]In[31]: obj4 = pd.Series(sdata,index=states)In[32]: obj4Out[32]:CaliforniaNaNOhio35000.0Oregon16000.0Texas71000.0dtype: float64
在這個例子中,sdata跟states索引相匹配的那3個值會被找出來並放到相應的位置上,但由於「California」所對應的sdata值找不到,所以其結果就為NaN(即「非數字」,在pandas中,它用於表示缺失或NA值)。pandas的 isnulll和 notnull函數可用於檢測缺失數據:
In[33]: pd.isnull(obj4)Out[33]:CaliforniaTrueOhioFalseOregonFalseTexasFalsedtype:boolIn[34]: pd.notnull(obj4)Out[34]:CaliforniaFalseOhioTrueOregonTrueTexasTruedtype:bool
對於許多應用而言,Series最重要的一個功能是:它在算術運算中會自動對齊不同索引的數據。
In[35]: obj3Out[35]:Ohio35000Oregon16000Texas71000Utah5000dtype: int64In[36]: obj4Out[36]:CaliforniaNaNOhio35000.0Oregon16000.0Texas71000.0dtype: float64In[37]: obj3 + obj4Out[37]:CaliforniaNaNOhio70000.0Oregon32000.0Texas142000.0UtahNaNdtype: float64
Series對象本身及其索引都有一個name屬性,該屬性跟pandas其他的關鍵功能關係非常密切:
In[38]: obj4.name =populationIn[39]: obj4.index.name =stateIn[40]: obj4Out[40]:stateCaliforniaNaNOhio35000.0Oregon16000.0Texas71000.0Name: population, dtype: float64
Series的索引可以通過賦值的方式就地修改:
In[43]: obj.index =[Bob,Steve,Jeff,Ryan]In[44]: objOut[44]:Bob4Steve7Jeff-5Ryan3dtype: int64
DataFrame
DataFrame是一個表格型的數據結構,它含有一組有序的列,每列可以是不同的值類型(數值、字元串、布爾值等)。DataFrame既有行索引也有列索引,它可以被看作由Series組成的字典(共用同一個索引)。
構造DataFrame的方法有很多,最常用的一種是直接傳入一個由等長列表或NumPy數組組成的字典:
In[49]: data ={state:[Ohio,Ohio,Ohio,Nevada,Nevada],...:...:year:[2000,2001,2002,2001,2002],...:...:pop:[1.5,1.7,3.6,2.4,2.9]}In[50]: frame = pd.DataFrame(data)
DataFrame會自動加上索引(和Series一樣),且全部列會被有序排列:
In[51]: frameOut[51]:pop state year01.5Ohio200011.7Ohio200123.6Ohio200232.4Nevada200142.9Nevada2002
如果指定了列序列,則DataFrame的列就會按照指定順序進行排列:
In[52]: pd.DataFrame(data,columns=[year,state,pop])Out[52]:year state pop02000Ohio1.512001Ohio1.722002Ohio3.632001Nevada2.442002Nevada2.9
和Series一樣,如果傳入的列在數據中找不到,就會產生NA值:
In[56]: frame2 = pd.DataFrame(data,columns=[year,state,pop,...:debt],index=[one,two,three,four,five])In[57]: frame2Out[57]:year state pop debtone 2000Ohio1.5NaNtwo 2001Ohio1.7NaNthree 2002Ohio3.6NaNfour 2001Nevada2.4NaNfive 2002Nevada2.9NaNIn[58]: frame2.columnsOut[58]:Index([year,state,pop,debt], dtype=object)
通過類似字典標記的方式或屬性的方式,可以將DataFrame的列獲取為一個Series:
In[59]: frame2[state]Out[59]:one Ohiotwo Ohiothree Ohiofour Nevadafive NevadaName: state, dtype:objectIn[60]: frame2.yearOut[60]:one 2000two 2001three 2002four 2001five 2002Name: year, dtype: int64
返回的Series擁有原DataFrame相同的索引,且其name屬性也已經被相應地設置好了。行也可以通過位置或名稱地方式進行獲取、比如用索引欄位loc。
In[62]: frame2.loc[three]Out[62]:year 2002state Ohiopop 3.6debt NaNName: three, dtype:objectIn[64]: frame2.iloc[0]Out[64]:year 2000state Ohiopop 1.5debt NaNName: one, dtype:object
列可以通過賦值的方式進行修改。例如,我們可以給空的"debt"列賦上一個標量值或一組值:
In[65]: frame2[debt]=16.5In[66]: frame2Out[66]:year state pop debtone 2000Ohio1.516.5two 2001Ohio1.716.5three 2002Ohio3.616.5four 2001Nevada2.416.5five 2002Nevada2.916.5In[67]: frame2[debt]= np.arange(5)In[68]: frame2Out[68]:year state pop debtone 2000Ohio1.50two 2001Ohio1.71three 2002Ohio3.62four 2001Nevada2.43five 2002Nevada2.94
將列表或數組賦值給某個列時,其長度必須跟DataFrame的長度相匹配。若賦值的是一個Series,就會精確匹配DataFrame的索引,所有的空位都會被填上缺失值:
In[71]: val = pd.Series([-1.2,-1.5,-1.7],index=[two,four,five])In[72]: frame2[debt]= valIn[73]: frame2Out[73]:year state pop debtone 2000Ohio1.5NaNtwo 2001Ohio1.7-1.2three 2002Ohio3.6NaNfour 2001Nevada2.4-1.5five 2002Nevada2.9-1.7
為不存在的列賦值會創建出一個新列。關鍵字del用於刪除列:
In[82]: frame2[eastern]= frame2.state ==OhioIn[83]: frame2Out[83]:year state pop debt easternone 2000Ohio1.5NaNTruetwo 2001Ohio1.7-1.2Truethree 2002Ohio3.6NaNTruefour 2001Nevada2.4-1.5Falsefive 2002Nevada2.9-1.7FalseIn[84]:del frame2[eastern]In[85]: frame2.columnsOut[85]:Index([year,state,pop,debt], dtype=object)
通過索引方式返回的列是相應數據的視圖,不是副本。
另一種常見的數據形式是嵌套字典:
In[86]: pop ={Nevada:{2001:2.4,2002:2.9},...:Ohio:{2000:1.5,2001:1.7,2002:3.6}}In[87]: frame3 = pd.DataFrame(pop)In[88]: frame3Out[88]:NevadaOhio2000NaN1.520012.41.720022.93.6
外層字典的鍵作為列,內層鍵作為行索引。
由Series組成的字典差不多也是一樣的用法:
In[95]: pdata ={Ohio:frame3[Ohio][:-1],...:Nevada:frame3[Nevada][:2]}In[96]: pd.DataFrame(pdata)Out[96]:NevadaOhio2000NaN1.520012.41.7
可以輸入給DataFrame構造器的數據:

如果設置了DataFrame的index和columns的name屬性,這些信息也會被顯示出來:
In[97]: frame3.index.name =yearIn[98]: frame3.columns.name =stateIn[99]: frame3Out[99]:state NevadaOhioyear2000NaN1.520012.41.720022.93.6
跟Series一樣,values屬性也會以二維ndarray的形式返回DataFrame中的數據。
索引對象
pandas的索引對象負責管理軸標籤和其他元數據(比如軸名稱等)。構建Series或DataFrame時,所用到的任何數組或其他序列的標籤都會被轉換成一個Index:
In[4]: obj = pd.Series(range(3),index=[a,b,c])In[5]: index = obj.indexIn[6]: indexOut[6]:Index([a,b,c], dtype=object)In[7]: index[1:]Out[7]:Index([b,c], dtype=object)
Index對象時不可修改的,因此用戶不能對其進行修改。

除了長得像數組,Index的功能也類似一個固定大小的集合。
Index的方法和屬性:

基本功能
介紹操作Series和DataFrame中的數據的基本手段。
重新索引
pandas對象的一個重要方法是reindex,其作用是創建一個適應新索引的新對象。
In[11]: obj = pd.Series([-4.5,7.2,-5.3,3.6],index=[d,b,a,c])In[12]: objOut[12]:d -4.5b 7.2a -5.3c 3.6dtype: float64In[13]: obj2 = obj.reindex([a,b,c,d,e])In[14]: obj2Out[14]:a -5.3b 7.2c 3.6d -4.5e NaNdtype: float64In[15]: obj.reindex([a,b,c,d,e],fill_value=0)Out[15]:a -5.3b 7.2c 3.6d -4.5e 0.0dtype: float64
如果某個索引值當前不存在,就引入缺失值。
對於時間序列這樣的有序數據,重新索引時可能需要做一些插值處理,method選項即可達到此目的。
In[16]: obj3 = pd.Series([blue,purple,yellow],index=[0,2,4])In[17]: obj3.reindex(range(6),method=ffill)Out[17]:0 blue1 blue2 purple3 purple4 yellow5 yellowdtype:object
reindex的(插值)method選項:
參數說明ffill或pad前向填充(或搬運)值bfill或backfill後向填充(或搬運)值
對於DataFrame,reindex可以修改(行)索引、列,或兩個都修改。如果僅傳入一個序列則會重新索引行:
In[25]: frame2 = frame.reindex([a,b,c,d])In[26]: frame = pd.DataFrame(np.arange(9).reshape((3,3)),index=[a,c,d],...: columns=[Ohio,Texas,California])In[27]: frame2 = frame.reindex([a,b,c,d])In[29]: frame2Out[29]:OhioTexasCaliforniaa 0.01.02.0b NaNNaNNaNc 3.04.05.0d 6.07.08.0
用columns關鍵字即可重新索引列,也可同時對行和列進行重新索引,而插值則只能按行應用(即軸0)。
利用loc的標籤索引功能,重新索引任務可以變得更簡潔:
In[33]: states =[Texas,Utah,California]In[34]: frame.loc[[a,b,c,d],states]Out[34]:TexasUtahCaliforniaa 1.0NaN2.0b NaNNaNNaNc 4.0NaN5.0d 7.0NaN8.0
reindex函數的參數:

丟棄指定軸上的項
丟棄某條軸上一個或多個項很簡單,只要一個索引數組或列表即可。使用drop方法返回的是一個在指定軸上刪除了指定值得新對象:
In[37]: obj = pd.Series(np.arange(5),index=[a,b,c,d,e])In[38]: objOut[38]:a 0b 1c 2d 3e 4dtype: int32In[39]: new_obj = obj.drop(c)In[40]: new_objOut[40]:a 0b 1d 3e 4dtype: int32In[41]: obj.drop([d,c])Out[41]:a 0b 1e 4dtype: int32
對於DataFrame,可以刪除任意軸上的索引值:
In[42]: data = pd.DataFrame(np.arange(16).reshape((4,4)),...: index=[Ohio,Colorado,Utah,New York],...: columns=[one,two,three,four])In[43]: dataOut[43]:one two three fourOhio0123Colorado4567Utah891011NewYork12131415In[44]: data.drop([Colorado,Ohio])Out[44]:one two three fourUtah891011NewYork12131415In[45]: data.drop(two,axis=1)Out[45]:one three fourOhio023Colorado467Utah81011NewYork121415In[46]: data.drop([two,four],axis=1)Out[46]:one threeOhio02Colorado46Utah810NewYork1214
函數應用和映射
NumPy的ufuncs(元素級數組方法)也可以用於pandas對象:
In[254]:frame = pd.DataFrame(np.random.randn(4,3),columns=list(bde),index=[Utah,Ohio,Texas,Oregon])In[255]:frameOut[255]:b d eUtah0.990385-0.544831-1.963969Ohio1.031441-0.072482-1.041419Texas-0.1522131.202226-2.117903Oregon-0.2657970.1997251.618044In[255]:np.abs(frame)Out[256]:b d eUtah0.9903850.5448311.963969Ohio1.0314410.0724821.041419Texas0.1522131.2022262.117903Oregon0.2657970.1997251.618044
另一個常見的操作是,將函數應用到由列或行形成的一維數組上。DataFrame的apply方法即可實現此功能。
In[257]:f =lambda x:x.max()- x.min()In[258]:frame.apply(f)Out[258]:b 1.297238d 1.747057e 3.735947dtype: float64In[259]:frame.apply(f,axis=1)Out[259]:Utah2.954354Ohio2.072860Texas3.320129Oregon1.883841dtype: float64
許多常見的數組統計功能都被實現成DataFrame的方法(如sum和mean),因此無需使用apply方法。
除標量值外,傳遞給apply的函數還可以返回由多個值組成的Series:
In[260]:def f(x):...:return pd.Series([x.max(), x.min()],index=[max,min])...:In[261]: frame.apply(f)Out[261]:b d emax 1.0314411.2022261.618044min -0.265797-0.544831-2.117903
元素級Python函數也是可以用的。假如你想得到frame中各個浮點值的格式化字元串,使用applymap即可:
In[262]: format =lambda x:%.2f% xIn[263]: frame.applymap(format)Out[263]:b d eUtah0.99-0.54-1.96Ohio1.03-0.07-1.04Texas-0.151.20-2.12Oregon-0.270.201.62
之所以叫applymap是因為Series有一個應用於元素級函數的map方法:
In[265]: frame[e].map(format)Out[265]:Utah-1.96Ohio-1.04Texas-2.12Oregon1.62Name: e, dtype:object
排序和排名
根據條件對數據集排序,要對行或列索引進行排序(按字典排序)可使用sort_index方法,其返回一個已排序的新對象:
In[266]: obj = pd.Series(np.arange(4),index=[d,a,b,c])In[267]: objOut[267]:d 0a 1b 2c 3dtype: int32In[268]: obj.sort_index()Out[268]:a 1b 2c 3d 0dtype: int32
對於DataFrame,則可以根據任意一個軸上的索引進行排序:
In[273]: frame = pd.DataFrame(np.arange(8).reshape(2,4),index=[three,one],columns=[d,a,b,c])In[274]: frameOut[274]:d a b cthree 0123one 4567In[275]: frame.sort_index()Out[275]:d a b cone 4567three 0123In[276]: frame.sort_index(axis=1)Out[276]:a b c dthree 1230one 5674
數據默認是按升序排序,但也可以降序排序:
In[277]: frame.sort_index(axis=1,ascending=False)Out[277]:d c b athree 0321one 4765
若要按值對Series進行排序,可使用sort_values方法:
In[285]: obj = pd.Series([4,7,-3,2])In[286]: obj.sort_values()Out[286]:2-3320417dtype: int64
排序時,缺失值默認會被放到Series的末尾:
In[287]: obj = pd.Series([4,7,np.nan,-3,2])In[288]: obj.sort_values()Out[288]:3-3.042.004.017.02NaNdtype: float64
在DataFrame上,你可能希望根據一個或多個列中的值進行排序。將一個或多個列的名字傳給by選項即可達到目的:
In[289]: frame = pd.DataFrame({b:[4,7,-3,2],a:[0,1,0,1]})In[290]: frameOut[290]:a b00411720-3312In[291]: frame.sort_values(by=b)Out[291]:a b20-3312004117
要給多個列進行排序,傳入名稱列表即可:
In[292]: frame.sort_values(by=[a,b])Out[292]:a b20-3004312117
排名(ranking)跟排序關係密切,它會增設一個排名值(從1開始,一直到數組中有效數據的數量)。Series和DataFrame的rank方法。默認情況是通過「為各組分配一個平均排名」的方式破壞平級關係的。
In[300]: obj = pd.Series([7,-5,7,4,2,0,4])In[301]: obj.rank()Out[301]:06.511.026.534.543.052.064.5dtype: float64
也可以根據值在原數據中出現的順序給出排名:
In[304]: obj.rank(method=first)Out[304]:06.011.027.034.043.052.065.0dtype: float64
method選項
method說明average默認:在相等分組中,為各個值分配平均排名min使用整個分組的最小排名max使用整個分組的最大排名first按值在原始數據中的出現順序分配排名
帶有重複值的軸索引
雖然許多pandas函數(如reindex)都要求標籤唯一,但並不是強制性的。
In[306]: objOut[306]:a 0a 1b 2b 3c 4dtype: int32
索引的is_unique屬性可以告訴你它的值是否是唯一的:
obj.index.is_uniqueOut[307]:False
對於帶有重複值索引,數據選取的行為將會有些不同。如果某個索引對應多個值,則返回一個Series,而對應單個值得,則返回一個標量值。
In[308]: obj[a]Out[308]:a 0a 1dtype: int32In[309]: obj[c]Out[309]:4
對DataFram的行進行索引亦是如此:
df = pd.DataFrame(np.random.randn(4,3),index=[a,a,b,b])In[315]: dfOut[315]:012a 1.003668-2.0841790.230573a 0.4053760.677472-0.489013b 0.6746490.3666570.026477b -1.1289480.6643320.792995In[316]: df.loc[a]Out[316]:012a 1.003668-2.0841790.230573a 0.4053760.677472-0.489013
匯總和計算描述統計
方法說明count非NA值的數量describe針對Series或各DataFrame列計算匯總統計max,min計算最小值和最大值argmin,argmax計算能夠獲取到最小值和最大值的索引位置(整數)idxmin,idxmax計算能夠獲取到最小值和最大值的索引值quantile計算樣本的分位數(0到1)sum值的總和mean值的平均數median值的算術中位數mad根據平均值計算平均絕對離差var樣本值的方差std樣本值得標準差skew樣本值的偏度(三階矩)kurt樣本值得峰度(四階矩)cumsum樣本值的累計和cummin,cummax樣本值的累計最大值和累計最小值cumprod樣本的累計積diff計算一階差分pct_change計算百分數變化
唯一值、值計數以及成員資格
還有一類方法可以從一維Series的值中抽取信息。以下面這個Series為例:
In[8]: obj = pd.Series([c,a,d,a,a,b,b,c,c])
第一個函數是 unique,可以得到Series中的唯一值數組:
In[9]: uniques = obj.unique()In[10]: uniquesOut[10]: array([c,a,d,b], dtype=object)
返回的唯一值是未排序的,需要的話,可以對結果再次進行排序( uniques.sort()原地排序)。 value_counts()用於計算一個Series中各值出現的頻率:
In[13]: obj.value_counts()Out[13]:c 3a 3b 2d 1dtype: int64
value_counts是一個頂級pandas方法,可用於任何數組或序列:
In[14]: pd.value_counts(obj.values,sort=False)Out[14]:b 2d 1a 3c 3dtype: int64
最後是 isin,用於判斷矢量化集合的成員資格,可用於選取Series中或DataFrame列中數據的子集:
In[18]: mask = obj.isin([b,c])In[19]: maskOut[19]:0True1False2False3False4False5True6True7True8Truedtype:boolIn[20]: obj[mask]Out[20]:0 c5 b6 b7 c8 cdtype:object
唯一值、值計數、成員資格方法
方法說明isin計算一個表示「Series各值是否包含於傳入的值序列中」的布爾型數組unique計算Series中的唯一值數組,按發現的順序返回value_counts返回一個Series,其索引為唯一值,其值為頻率,按計數值降序排列
有時,你可能希望得到DataFrame中多個相關列的一張柱狀圖,例如:
In[21]: data = pd.DataFrame({Qu1:[1,3,4,3,4],...:Qu2:[2,3,1,2,3],...:Qu3:[1,5,2,4,4]})In[22]: dataOut[22]:Qu1Qu2Qu301211335241233244434
將 pandas.value_counts傳給該DataFrame的apply函數,就會出現:
In[23]: result = data.apply(pd.value_counts).fillna(0)In[24]: resultOut[24]:Qu1Qu2Qu311.01.01.020.02.01.032.02.00.042.00.02.050.00.01.0
處理缺失數據
pandas使用浮點值NaN(Not a Number)表示浮點和非浮點數組中的缺失數據。它只是一個便於被檢測出來的標記而已:
In[26]: string_data = pd.Series([aardvark,artichoke,np.nan,avocado])In[27]: string_dataOut[27]:0 aardvark1 artichoke2NaN3 avocadodtype:objectIn[28]: string_data.isnull()Out[28]:0False1False2True3Falsedtype:bool
Python內置的None值也會被當做NA處理:
In[30]: string_data[0]=NoneIn[31]: string_data.isnull()Out[31]:0True1False2True3Falsedtype:bool
NA處理方法
方法說明dropna根據各標籤的值中是否存在缺失數據對軸標籤進行過濾,可通過閾值調節對缺失值的容忍度fillna用指定值或者插值法(如ffill或bfill)填充缺失數據isnull返回一個含有布爾值的對象,這些布爾值表示哪些值是缺失值/NA,該對象類型與源類型一樣notnullisnull的否定式
濾除缺失數據
過濾掉缺失數據的辦法由很多種,純手工操作永遠都是一個辦法,但dropna可能會更實用一些。對於一個Series,dropna返回一個僅含非空數據和索引值的Series:
In[32]:from numpy import nan as NA...:In[33]: data = pd.Series([1,NA,3.5,NA,7])In[34]: dataOut[34]:01.01NaN23.53NaN47.0dtype: float64In[35]: data.dropna()Out[35]:01.023.547.0dtype: float64
也可以通過布爾型索引達到這個目的:
In[36]: data[data.notnull()]Out[36]:01.023.547.0dtype: float64
而對於DataFrame對象,事情就有點複雜了。你可能希望丟棄全NA或含有NA的行或列。 dropna默認丟棄任何含有缺失值的行:
In[37]: data = pd.DataFrame([[1,6.5,3],[1,NA,NA],[NA,NA,NA],...:[NA,6.5,3]])In[38]: cleaned = data.dropna()In[39]: cleanedOut[39]:01201.06.53.0In[40]: dataOut[40]:01201.06.53.011.0NaNNaN2NaNNaNNaN3NaN6.53.0
傳入 how=all將只丟棄全為NA的那些行:
In[41]: data.dropna(how=all)Out[41]:01201.06.53.011.0NaNNaN3NaN6.53.0
要用這種方式丟棄列,只需傳入axis=1即可:
In[42]: data[4]= NAIn[43]: dataOut[43]:012401.06.53.0NaN11.0NaNNaNNaN2NaNNaNNaNNaN3NaN6.53.0NaNIn[44]: data.dropna(axis=1,how=all)Out[44]:01201.06.53.011.0NaNNaN2NaNNaNNaN3NaN6.53.0
另一個濾除DataFrame行的問題涉及時間序列數據。假設你只想留下一部分觀測數據,可以用thresh參數實現此目的:
In[45]: df = pd.DataFrame(np.random.randn(7,3))In[46]: df.iloc[:4,1]= NAIn[47]: df.iloc[:2,2]= NAIn[48]: dfOut[48]:01200.104567NaNNaN10.518986NaNNaN2-0.142659NaN1.0491383-0.384427NaN-0.31382140.2987930.428673-0.5042815-1.7082730.550135-0.57324860.9393680.9317891.381717In[49]: df.dropna(thresh=3)Out[49]:01240.2987930.428673-0.5042815-1.7082730.550135-0.57324860.9393680.9317891.381717
填充缺失數據
你可能不想過濾缺失數據(有可能會捨棄與它相關的其他數據),而希望補填那些「空洞」。 fillna函數就是最主要的函數,通過一個常數調用 fillna就會將缺失值替換為那個常數值:
In[52]: df.fillna(0)Out[52]:01200.1045670.0000000.00000010.5189860.0000000.0000002-0.1426590.0000001.0491383-0.3844270.000000-0.31382140.2987930.428673-0.5042815-1.7082730.550135-0.57324860.9393680.9317891.381717
若是通過一個字典調用fillna,就可以實現對不同列填充不同的值:
In[53]: df.fillna({1:0.5,3:-1})Out[53]:01200.1045670.500000NaN10.5189860.500000NaN2-0.1426590.5000001.0491383-0.3844270.500000-0.31382140.2987930.428673-0.5042815-1.7082730.550135-0.57324860.9393680.9317891.381717
fillna默認會返回新對象,也可以對現有對象進行就地修改:
In[59]: _ = df.fillna(0,inplace=True)In[60]: dfOut[60]:01200.1045670.0000000.00000010.5189860.0000000.0000002-0.1426590.0000001.0491383-0.3844270.000000-0.31382140.2987930.428673-0.5042815-1.7082730.550135-0.57324860.9393680.9317891.381717
對 reindex有效的那些插值方法也可用於 fillna:
In[64]: df = pd.DataFrame(np.random.randn(6,3))In[65]: df.iloc[2:,1]= NAIn[66]: df.iloc[4:,2]= NAIn[67]: dfOut[67]:01201.2717952.1995520.0132191-0.976690-0.1398200.0845072-0.757627NaN-1.9865183-0.169319NaN0.91279140.488452NaNNaN50.870533NaNNaNIn[68]: df.fillna(method=ffill)Out[68]:01201.2717952.1995520.0132191-0.976690-0.1398200.0845072-0.757627-0.139820-1.9865183-0.169319-0.1398200.91279140.488452-0.1398200.91279150.870533-0.1398200.912791In[69]: df.fillna(method=ffill,limit=2)Out[69]:01201.2717952.1995520.0132191-0.976690-0.1398200.0845072-0.757627-0.139820-1.9865183-0.169319-0.1398200.91279140.488452NaN0.91279150.870533NaN0.912791
fillna函數的參數
參數說明value用於填充缺失值的標量值或字典對象method插值方式。默認為「ffill」axis待填充的軸,默認axis=0inplace修改調用者而不產生副本limit(對於前向和後向填充)可以連續填充的最大數量
層次化索引
層次化索引是pandas一項重要功能,它使你能在一個軸上擁有多個(兩個以上)索引級別。抽象點說,它使你能以低維度形式處理高緯度數據。先看一個簡單的例子:創建一個Series,並用一個由列表或數組組成列表作為索引。
In[70]: data = pd.Series(np.random.randn(10),...: index=[[a,a,a,b,b,b,c,c,d,...:d],[1,2,3,1,2,3,1,2,2,3]])In[71]: dataOut[71]:a 1-0.7743082-1.11640430.956191b 1-0.7445952-1.80608630.471932c 10.98931320.532067d 20.96423830.129724dtype: float64
這就是帶有MultiIndex索引的Series的格式化輸出形式。索引之間的「間隔」表示「直接使用上面的標籤」:
In[72]: data.indexOut[72]:MultiIndex(levels=[[a,b,c,d],[1,2,3]],labels=[[0,0,0,1,1,1,2,2,3,3],[0,1,2,0,1,2,0,1,1,2]])
對於也給層次化索引的對象,選取數據子集的操作很簡單:
In[73]: data[b]Out[73]:1-0.7445952-1.80608630.471932dtype: float64In[74]: data[b:c]Out[74]:b 1-0.7445952-1.80608630.471932c 10.98931320.532067dtype: float64In[75]: data.loc[[b,d]]Out[75]:b 1-0.7445952-1.80608630.471932d 20.96423830.129724dtype: float64
有時甚至還可以在「內層」中進行選取:
In[76]: data[:,2]Out[76]:a -1.116404b -1.806086c 0.532067d 0.964238dtype: float64
層次化索引在數據重塑和基於分組的操作(如透視表生成)中扮演著重要的角色。比如說,這段數據可以通過 unstack方法被重新安排到一個DataFrame中:
In[78]: data.unstack()Out[78]:123a -0.774308-1.1164040.956191b -0.744595-1.8060860.471932c 0.9893130.532067NaNd NaN0.9642380.129724
unstack的逆運算是 stack:
In[80]: data.unstack().stack()Out[80]:a 1-0.7743082-1.11640430.956191b 1-0.7445952-1.80608630.471932c 10.98931320.532067d 20.96423830.129724dtype: float64
對於也給DataFrame,每條軸都可以有分層索引:
In[81]: frame = pd.DataFrame(np.arange(12).reshape(4,3),...: index=[[a,a,b,b],[1,2,1,2]],...: columns =[[Ohio,Ohio,Colorado],...:[Green,Red,Green]])In[82]: frameOut[82]:OhioColoradoGreenRedGreena 10122345b 1678291011
各層都可以有名字(可以是字元串,也可以是別的Python對象)。如果指定了名稱,就會顯示在控制台輸出中:
In[83]: frame.index.names =[key1,key2]In[84]: frame.columns.names =[state,color]In[85]: frameOut[85]:state OhioColoradocolor GreenRedGreenkey1 key2a 10122345b 1678291011
有了分部的列索引,就可以輕鬆選取分組:
In[86]: frame[Ohio]Out[86]:color GreenRedkey1 key2a 101234b 1672910
以及:
In[88]: frame.loc[a]Out[88]:state OhioColoradocolor GreenRedGreenkey210122345In[89]: frame.loc[a,Ohio]Out[89]:color GreenRedkey2101234
可以單獨創建MultiIndex然後復用。上面那個DataFrame中的(分級的)可以這樣創建:
In[94]:from pandas importMultiIndexIn[95]:MultiIndex.from_arrays([[Ohio,Ohio,Colorado],...:[Green,Red,Green]],names=[state,color])Out[95]:MultiIndex(levels=[[Colorado,Ohio],[Green,Red]],labels=[[1,1,0],[0,1,0]],names=[state,color])In[96]: frameOut[96]:state OhioColoradocolor GreenRedGreenkey1 key2a 10122345b 1678291011
重排分級順序
有時,你需要重新調整某條軸上各級別的順序,或根據指定級別上的值對數據進行排序。 swaplevel接受兩個級別編號或名稱,並返回一個互換了級別的新對象(但數據不會發生變化):
In[98]: frame.swaplevel(key1,key2)Out[98]:state OhioColoradocolor GreenRedGreenkey2 key11 a 0122 a 3451 b 6782 b 91011
而 sort_index則根據單個級別中的值對數據進行排序(穩定的)。交換級別時,常常也會用到 sort_index,這樣最終結果就是有序的了:
In[104]: frame.sort_index(level=1)Out[104]:state OhioColoradocolor GreenRedGreenkey1 key2a 1012b 1678a 2345b 291011In[105]: frame.swaplevel(0,1).sort_index(level=0)Out[105]:state OhioColoradocolor GreenRedGreenkey2 key11 a 012b 6782 a 345b 91011
根據級別匯總統計
許多對DataFrame和Series的描述和匯總統計都有一個level選項,用於指定在某條軸上求和級別。以上面那個DataFrame為例,我們可以根據行或列上的級別來進行求和,如下所示:
In[106]: frameOut[106]:state OhioColoradocolor GreenRedGreenkey1 key2a 10122345b 1678291011In[107]: frame.sum(level=key2)Out[107]:state OhioColoradocolor GreenRedGreenkey2168102121416In[108]: frame.sum(level=color,axis=1)Out[108]:color GreenRedkey1 key2a 121284b 114722010
這其實利用了pandas的groupby功能。
使用DataFrame的列
人們經常想要將DataFrame的一個或多個列當作行索引來用,或者可能希望將行索引變成DataFrame的列,舉個例子:
In[113]: frame = pd.DataFrame({a:np.arange(7),b:range(7,0,-1),...:c:[one,one,one,two,two,two,two],...:d:[0,1,2,0,1,2,3]})In[114]: frameOut[114]:a b c d007 one 0116 one 1225 one 2334 two 0443 two 1552 two 2661 two 3
DataFrame的 set_index函數會將其一個或多個列轉換為行索引,並創建一個新DataFrame:
In[115]: frame2 = frame.set_index([c,d])In[116]: frame2Out[116]:a bc done 007116225two 034143252361
默認情況下,那些列會從DataFrame中移除,但也可以保留下來:
In[117]: frame.set_index([c,d],drop=False)Out[117]:a b c dc done 007 one 0116 one 1225 one 2two 034 two 0143 two 1252 two 2361 two 3
reset_index的功能和 set_index剛好相反,層次化索引的級別會被轉移到列裡面:
In[119]: frame2.reset_index()Out[119]:c d a b0 one 0071 one 1162 one 2253 two 0344 two 1435 two 2526 two 361
推薦閱讀:
※擴散方程
※Python有哪些可以做帶約束的二次線性規劃的包?
※如何正確地/有趣地使用Matlab手機版?
※Windows下有什麼辦法提高conda install的速度?
※Python裡面的scipy庫如何計算線性規劃問題呢?
