作者:趙志強(qiáng) 劉志偉 來源:華章科技 在使用Pandas之前,需要導(dǎo)入Pandas包。慣例是將pandas簡寫為pd,命令如下: import pandas as pd Pandas包含兩個主要的數(shù)據(jù)結(jié)構(gòu):Series和DataFrame。其中最常用的是DataFrame,下面我們先來學(xué)習(xí)一下DataFrame。 01 DataFrame入門DataFrame是一個表格型的數(shù)據(jù)結(jié)構(gòu)。每列都可以是不同的數(shù)據(jù)類型(數(shù)值、字符串、布爾值等)。 DataFrame既有行索引也有列索引,這兩種索引在DataFrame的實(shí)現(xiàn)上,本質(zhì)上是一樣的。但在使用的時(shí)候,往往是將列索引作為區(qū)分不同數(shù)據(jù)的標(biāo)簽。DataFrame的數(shù)據(jù)結(jié)構(gòu)與SQL數(shù)據(jù)表或者Excel工作表的結(jié)構(gòu)非常類似,可以很方便地互相轉(zhuǎn)換。 下面先來創(chuàng)建一個DataFrame,一種常用的方式是使用字典,這個字典是由等長的list或者ndarray組成的,示例代碼如下:
運(yùn)行結(jié)果如圖3-2所示。 ▲圖3-2 我們可以看到,DataFrame主要由如下三個部分組成。
下文列出了DataFrame函數(shù)常用的參數(shù)。其中,“類似列表”代表類似列表的形式,比如列表、元組、ndarray等。一般來說,data、index、columns這三個參數(shù)的使用頻率是最高的。
其中data的數(shù)據(jù)類型有很多種。 下文列舉了可以作為data傳給DataFrame函數(shù)的數(shù)據(jù)類型。 可以傳給DataFrame構(gòu)造器的數(shù)據(jù):
前面生成了一個DataFrame,變量名為df。下面我們來查看一下df的各個屬性值。 獲取df數(shù)據(jù)的示例代碼如下: df.values 輸出結(jié)果如下:
獲取df行索引的示例代碼如下: df.index 輸出結(jié)果如下:
獲取df列索引(列標(biāo)簽)的示例代碼如下: df.columns 輸出結(jié)果如下:
可以看到,行索引和列標(biāo)簽都是Index數(shù)據(jù)類型。 創(chuàng)建的時(shí)候,如果指定了列標(biāo)簽,那么DataFrame的列也會按照指定的順序進(jìn)行排列,示例代碼如下: df=pd.DataFrame(data,columns=['C','B','A'],index=['a','b','c'])df 運(yùn)行結(jié)果如圖3-3所示。 ▲圖3-3 如果某列不存在,為其賦值,會創(chuàng)建一個新列。我們可以用這種方法來添加一個新的列:
運(yùn)行結(jié)果如圖3-4所示。 ▲圖3-4 使用del命令可以刪除列,示例代碼如下: del df['D']df 運(yùn)行結(jié)果如圖3-5所示。 ▲圖3-5 添加行的一種方法是先創(chuàng)建一個DataFrame,然后再使用append方法,代碼如下:
運(yùn)行結(jié)果如圖3-6所示。 ▲圖3-6 或者也可以使用loc方法來添加行,示例代碼如下: df.loc['e']=['new2',5000,50]df 運(yùn)行結(jié)果如圖3-7所示。 ▲圖3-7 loc方法將在后面的內(nèi)容中詳細(xì)介紹。 索引的存在,使得Pandas在處理缺漏信息的時(shí)候非常靈活。下面的示例代碼會新建一個DataFrame數(shù)據(jù)df2。
運(yùn)行結(jié)果如圖3-8所示。 ▲圖3-8 如果現(xiàn)在想要合并df和df2,使得df有一個新的列E,那么可以使用join方法,代碼如下: df.join(df2) 運(yùn)行結(jié)果如圖3-9所示。 ▲圖3-9 可以看到,df只接受索引已經(jīng)存在的值。由于df2中沒有索引e,所以是NaN值,而且df2索引為z的值已經(jīng)丟失了。為了保留df2中索引為z的值,我們可以提供一個參數(shù),告訴Pandas如何連接。示例代碼如下:
運(yùn)行結(jié)果如圖3-10所示。 ▲圖3-10 在上述代碼中,how='outer'表示使用兩個索引中所有值的并集。連接操作的其他選項(xiàng)還有inner(索引的交集)、left(默認(rèn)值,調(diào)用方法的對象的索引值)、right(被連接對象的索引值)等。 在金融數(shù)據(jù)分析中,我們要分析的往往是時(shí)間序列數(shù)據(jù)。下面介紹一下如何基于時(shí)間序列生成DataFrame。為了創(chuàng)建時(shí)間序列數(shù)據(jù),我們需要一個時(shí)間索引。這里先生成一個DatetimeIndex對象的日期序列,代碼如下: dates=pd.date_range('20160101',periods=8)dates 輸出結(jié)果如下:
可以看到,使用Pandas的date_range函數(shù)生成的是一個DatetimeIndex對象。date_range函數(shù)的參數(shù)及說明如下所示:
date_range函數(shù)頻率的參數(shù)及說明如下所示:
接下來,我們再基于dates來創(chuàng)建DataFrame,代碼如下: df=pd.DataFrame(np.random.randn(8,4),index=dates,columns=list('ABCD'))df 運(yùn)行結(jié)果如圖3-11所示。 ▲圖3-11 有了df,我們就可以使用多個基于DataFrame的內(nèi)建方法了,下面來看看相關(guān)的示例。 按列求總和,代碼如下:
輸出結(jié)果如下: A 0.241727B -0.785350C -0.547433D -1.449231dtype: float64 按列求均值,代碼如下:
輸出結(jié)果如下: A 0.030216B -0.098169C -0.068429D -0.181154dtype: float64 按列求累計(jì)總和,代碼如下:
運(yùn)行結(jié)果如圖3-12所示。 ▲圖3-12 使用describe一鍵生成多種統(tǒng)計(jì)數(shù)據(jù),代碼如下: df.describe() 運(yùn)行結(jié)果如圖3-13所示。 ▲圖3-13 可以根據(jù)某一列的值進(jìn)行排序,代碼如下:
運(yùn)行結(jié)果如圖3-14所示。 ▲圖3-14 根據(jù)索引(日期)排序(這里是倒序),代碼如下: df.sort_index(ascending=False) 運(yùn)行結(jié)果如圖3-15所示。 ▲圖3-15 選取某一列,返回的是Series對象,可以使用df.A,代碼如下:
輸出結(jié)果如下: 2016-01-01 -1.1423502016-01-02 -0.8161782016-01-03 0.0302062016-01-04 1.9301752016-01-05 0.5715122016-01-06 0.2204452016-01-07 0.2921762016-01-08 -0.844260Freq: D, Name: A, dtype: float64 使用[]選取某幾行,代碼如下:
運(yùn)行結(jié)果如圖3-16所示。 ▲圖3-16 根據(jù)標(biāo)簽(Label)選取數(shù)據(jù),使用的是loc方法,代碼如下: df.loc[dates[0]] 輸出結(jié)果如下:
再來看兩個示例代碼。 df.loc[:,['A','C']] 運(yùn)行結(jié)果如圖3-17所示。 ▲圖3-17
運(yùn)行結(jié)果如圖3-18所示。 ▲圖3-18 需要注意的是,如果只有一個時(shí)間點(diǎn),那么返回的值是Series對象,代碼如下: df.loc['20160102',['A','C']] 輸出結(jié)果如下:
如果想要獲取DataFrame對象,需要使用如下命令: df.loc['20160102':'20160102',['A','C']] 運(yùn)行結(jié)果如圖3-19所示。 ▲圖3-19 上面介紹的是loc方法,是按標(biāo)簽(索引)來選取數(shù)據(jù)的。有時(shí)候,我們會希望按照DataFrame的絕對位置來獲取數(shù)據(jù),比如,如果想要獲取第3行第2列的數(shù)據(jù),但不想按標(biāo)簽(索引)獲取,那么這時(shí)候就可以使用iloc方法。 根據(jù)位置選取數(shù)據(jù),代碼如下:
輸出結(jié)果如下: A 0.030206B 0.759953C -1.446549D -0.874364Name: 2016-01-03 00:00:00, dtype: float64 再來看一個示例:
運(yùn)行結(jié)果如圖3-20所示。 ▲圖3-20
有時(shí),我們需要選取滿足一定條件的數(shù)據(jù)。這個時(shí)候可以使用條件表達(dá)式來選取數(shù)據(jù)。這時(shí)傳給df的既不是標(biāo)簽,也不是絕對位置,而是布爾數(shù)組(Boolean Array)。下面來看一下示例。 例如,尋找A列中值大于0的行。首先,生成一個布爾數(shù)組,代碼如下: df.A>0 輸出結(jié)果如下:
可以看到,這里生成了一個Series類型的布爾數(shù)組??梢酝ㄟ^這個數(shù)組來選取對應(yīng)的行,代碼如下: df[df.A>0] 運(yùn)行結(jié)果如圖3-21所示。 ▲圖3-21 從結(jié)果可以看到,A列中值大于0的所有行都被選擇出來了,同時(shí)也包括了BCD列。 現(xiàn)在我們要尋找df中所有大于0的數(shù)據(jù),先生成一個全數(shù)組的布爾值,代碼如下:
運(yùn)行結(jié)果如圖3-22所示。 ▲圖3-22 下面來看一下使用df>0選取出來的數(shù)據(jù)效果。由圖3-23可以看到,大于0的數(shù)據(jù)都能顯示,其他數(shù)據(jù)顯示為NaN值。 df[df>0] 運(yùn)行結(jié)果如圖3-23所示。 ▲圖3-23 再來看一下如何改變df的值。首先我們?yōu)閐f添加新的一列E,代碼如下:
運(yùn)行結(jié)果如圖3-24所示。 ▲圖3-24 使用loc改變一列值,代碼如下: df.loc[:,'E']=1df 運(yùn)行結(jié)果如圖3-25所示。 ▲圖3-25 使用loc改變單個值,代碼如下:
運(yùn)行結(jié)果如圖3-26所示。 ▲圖3-26 使用loc改變一列值,代碼如下: df.loc[:,'D'] = np.array([2] * len(df))df 運(yùn)行結(jié)果如圖3-27所示。 ▲圖3-27 可以看到,使用loc的時(shí)候,x索引和y索引都必須是標(biāo)簽值。對于這個例子,使用日期索引明顯不方便,需要輸入較長的字符串,所以使用絕對位置會更好。這里可以使用混合方法,DataFrame可以使用ix來進(jìn)行混合索引。比如,行索引使用絕對位置,列索引使用標(biāo)簽,代碼如下:
運(yùn)行結(jié)果如圖3-28所示。 ▲圖3-28 ix的處理方式是,對于整數(shù),先假設(shè)為標(biāo)簽索引,并進(jìn)行尋找;如果找不到,就作為絕對位置索引進(jìn)行尋找。所以運(yùn)行效率上會稍差一些,但好處是這樣操作比較方便。 對于ix的用法,需要注意如下兩點(diǎn)。
總的來說,除非想用混合索引,否則建議只使用loc或者iloc來進(jìn)行索引,這樣可以避免很多問題。 02 SeriesSeries類似于一維數(shù)組,由一組數(shù)據(jù)以及相關(guān)的數(shù)據(jù)標(biāo)簽(索引)組成。示例代碼如下: import pandas as pds=pd.Series([1,4,6,2,3])s Out:
在這段代碼中,我們首先導(dǎo)入pandas并命名為pd,然后向Series函數(shù)傳入一個列表,生成一個Series對象。在輸出Series對象的時(shí)候,左邊一列是索引,右邊一列是值。由于沒有指定索引,因此會自動創(chuàng)建0到(N-1)的整數(shù)索引。也可以通過Series的values和index屬性獲取其值和索引。示例代碼如下: s.values Out:
s.index Out:
當(dāng)然,我們也可以對索引進(jìn)行定義,代碼如下: s=pd.Series([1,2,3,4],index=['a','b','c','d'])s Out:
在這里,我們將索引定義為a、b、c、d。這時(shí)也可以用索引來選取Series的數(shù)據(jù),代碼如下: s['a'] Out:
s[['b','c']] Out:
對Series進(jìn)行數(shù)據(jù)運(yùn)算的時(shí)候也會保留索引。示例代碼如下: s[s>1] Out:
s*3 Out:
Series最重要的功能之一是在不同索引中對齊數(shù)據(jù)。示例代碼如下: s1=pd.Series([1,2,3],index=['a','b','c'])s2=pd.Series([4,5,6],index=['b','c','d'])s1+s2 Out:
Series的索引可以通過賦值的方式直接修改,示例代碼如下: s.index Out:
s.index=['w','x','y','z']s.index Out:
s Out:
|
|