前面一篇文章咱們介紹了numpy,但numpy的特長並非在於數據處理,而是在它能很是方便地實現科學計算,因此咱們平常對數據進行處理時用的numpy狀況並非不少,咱們須要處理的數據通常都是帶有列標籤和index索引的,而numpy並不支持這些,這時咱們就須要pandas上場啦!html
Pandas是基於Numpy構建的庫,在數據處理方面能夠把它理解爲numpy增強版,同時Pandas也是一項開源項目 。不一樣於numpy的是,pandas擁有種數據結構:Series和DataFrame:python
下面咱們就來生成一個簡單的series對象來方便理解:git
In [1]: from pandas import Series,DataFrame In [2]: import pandas as pd In [3]: data = Series([1,2,3,4],index = ['a','b','c','d']) In [4]: data Out[4]: a 1 b 2 c 3 d 4 dtype: int64
Series是一種相似一維數組的數據結構,由一組數據和與之相關的index組成,這個結構一看彷佛與dict字典差很少,咱們知道字典是一種無序的數據結構,而pandas中的Series的數據結構不同,它至關於定長有序的字典,而且它的index和value之間是獨立的,二者的索引仍是有區別的,Series的index是可變的,而dict字典的key值是不可變的。github
下面照例生成一個簡單的DataFrame對象:數據庫
In [8]: data = {'a':[1,2,3],'b':['we','you','they'],'c':['btc','eos','ae']} In [9]: df = DataFrame(data) In [10]: df Out[10]: a b c 0 1 we btc 1 2 you eos 2 3 they ae
DataFrame這種數據結構咱們能夠把它看做是一張二維表,DataFrame長得跟咱們平時使用的Excel表格差很少,DataFrame的橫行稱爲columns,豎列和Series同樣稱爲index,DataFrame每一列能夠是不一樣類型的值集合,因此DataFrame你也能夠把它視爲不一樣數據類型同一index的Series集合。數組
科學計算方面numpy是優點,但在數據處理方面DataFrame就更勝一籌了,事實上DataFrame已經覆蓋了一部分的數據操做了,對於數據挖掘來講,工做可大概分爲讀取數據-數據清洗-分析建模-結果展現:數據結構
先說說讀取數據,Pandas提供強大的IO讀取工具,csv格式、Excel文件、數據庫等均可以很是簡便地讀取,對於大數據,pandas也支持大文件的分塊讀取;工具
接下來就是數據清洗,面對數據集,咱們遇到最多的狀況就是存在缺失值,Pandas把各類類型數據類型的缺失值統一稱爲NaN(這裏要多說幾句,None==None這個結果是true,但np.nan==np.nan這個結果是false,NaN在官方文檔中定義的是float類型,有關於NaN和None的區別以及使用,有位博主已經作好整理:None vs NaN),Pandas提供許多方便快捷的方法來處理這些缺失值NaN。post
最重要的分析建模階段,Pandas自動且明確的數據對齊特性,很是方便地使新的對象能夠正確地與一組標籤對齊,有了這個特性,Pandas就能夠很是方便地將數據集進行拆分-重組操做。大數據
最後就是結果展現階段了,咱們都知道Matplotlib是個數據視圖化的好工具,Pandas與Matplotlib搭配,不用複雜的代碼,就能夠生成多種多樣的數據視圖。
Series的兩種生成方式:
In [19]: data = Series([222,'btc',234,'eos']) In [20]: data Out[20]: 0 222 1 btc 2 234 3 eos dtype: object
雖然咱們在生成的時候沒有設置index值,但Series仍是會自動幫咱們生成index,這種方式生成的Series結構跟list列表差很少,能夠把這種形式的Series理解爲豎起來的list列表。
In [21]: data = Series([1,2,3,4],index = ['a','b','c','d']) In [22]: data Out[22]: a 1 b 2 c 3 d 4 dtype: int64
這種形式的Series能夠理解爲numpy的array外面披了一件index的馬甲,因此array的相關操做,Series一樣也是支持的。結構很是類似的dict字典一樣也是能夠轉化爲Series格式的:
In [29]: dic = {'a':1,'b':2,'c':'as'} In [30]: dicSeries = Series(dic)
查看Series的相關信息:
In [32]: data.index Out[32]: Index(['a', 'b', 'c', 'd'], dtype='object') In [33]: data.values Out[33]: array([1, 2, 3, 4], dtype=int64) In [35]: 'a' in data #in方法默認判斷的是index值 Out[35]: True
Series的NaN生成:
In [46]: index1 = [ 'a','b','c','d'] In [47]: dic = {'b':1,'c':1,'d':1} In [48]: data2 = Series(dic,index=index1) In [49]: data2 Out[49]: a NaN b 1.0 c 1.0 d 1.0 dtype: float64
從這裏咱們能夠看出Series的生成依據的是index值,index‘a’在字典dic的key中並不存在,Series天然也找不到’a’的對應value值,這種狀況下Pandas就會自動生成NaN(not a number)來填補缺失值,這裏還有個有趣的現象,本來dtype是int類型,生成NaN後就變成了float類型了,由於NaN的官方定義就是float類型。
NaN的相關查詢:
In [58]: data2.isnull() Out[58]: a True b False c False d False dtype: bool In [59]: data2.notnull() Out[59]: a False b True c True d True dtype: bool In [60]: data2[data2.isnull()==True] #嵌套查詢NaN Out[60]: a NaN dtype: float64 In [64]: data2.count() #統計非NaN個數 Out[64]: 3
切記切記,查詢NaN值切記不要使用np.nan==np.nan這種形式來做爲判斷條件,結果永遠是False,==是用做值判斷的,而NaN並無值,若是你不想使用上方的判斷方法,你可使用is做爲判斷方法,is是對象引用判斷,np.nan is np.nan,結果就是你要的True。
Series自動對齊:
In [72]: data1 Out[72]: a 1 asd 1 b 1 dtype: int64 In [73]: data Out[73]: a 1 b 2 c 3 d 4 dtype: int64 In [74]: data+data1 Out[74]: a 2.0 asd NaN b 3.0 c NaN d NaN dtype: float64
從上面兩個Series中不難看出各自的index所處位置並不徹底相同,這時Series的自動對齊特性就發揮做用了,在算術運算中,Series會自動尋找匹配的index值進行運算,若是index不存在匹配則自動賦予NaN,值得注意的是,任何數+NaN=NaN,你能夠把NaN理解爲吸取一切的黑洞。
Series的name屬性:
In [84]: data.index.name = 'abc' In [85]: data.name = 'test' In [86]: data Out[86]: abc a 1 b 2 c 3 d 4 Name: test, dtype: int64
Series對象自己及其索引index都有一個name屬性,name屬性主要發揮做用是在DataFrame中,當咱們把一個Series對象放進DataFrame中,新的列將根據咱們的name屬性對該列進行命名,若是咱們沒有給Series命名,DataFrame則會自動幫咱們命名爲0。
DataFrame的生成:
In [87]: data = {'name': ['BTC', 'ETH', 'EOS'], 'price':[50000, 4000, 150]} In [88]: data = DataFrame(data) In [89]: data Out[89]: name price 0 BTC 50000 1 ETH 4000 2 EOS 150
DataFrame的生成與Series差很少,你能夠本身指定index,也可不指定,DataFrame會自動幫你補上。
查看DataFrame的相關信息:
In [95]: data.index Out[95]: RangeIndex(start=0, stop=3, step=1) In [96]: data.values Out[96]: array([['BTC', 50000], ['ETH', 4000], ['EOS', 150]], dtype=object) In [97]: data.columns #DataFrame的列標籤 Out[97]: Index(['name', 'price'], dtype='object')
DataFrame的索引:
In [92]: data.name Out[92]: 0 BTC 1 ETH 2 EOS Name: name, dtype: object In [93]: data['name'] Out[93]: 0 BTC 1 ETH 2 EOS Name: name, dtype: object In [94]: data.iloc[1] #loc['name']查詢的是行標籤 Out[94]: name ETH price 4000 Name: 1, dtype: object
其實行索引,除了iloc,loc還有個ix,ix既能夠進行行標籤索引,也能夠進行行號索引,但這也大大增長了它的不肯定性,有時會出現一些奇怪的問題,因此pandas在0.20.0版本的時候就把ix給棄用了。
簡單地增長行、列:
In [105]: data['type'] = 'token' #增長列 In [106]: data Out[106]: name price type 0 BTC 50000 token 1 ETH 4000 token 2 EOS 150 token In [109]: data.loc['3'] = ['ae',200,'token'] #增長行 In [110]: data Out[110]: name price type 0 BTC 50000 token 1 ETH 4000 token 2 EOS 150 token 3 ae 200 token
刪除行、列操做:
In [117]: del data['type'] #刪除列 In [118]: data Out[118]: name price 0 BTC 50000 1 ETH 4000 2 EOS 150 3 ae 200 In [120]: data.drop([2]) #刪除行 Out[120]: name price 0 BTC 50000 1 ETH 4000 3 ae 200 In [121]: data Out[121]: name price 0 BTC 50000 1 ETH 4000 2 EOS 150 3 ae 200
這裏須要注意的是,使用drop()方法返回的是Copy而不是視圖,要想真正在原數據裏刪除行,就要設置*inplace=True*:
In [125]: data.drop([2],inplace=True) In [126]: data Out[126]: name price 0 BTC 50000 1 ETH 4000 3 ae 200
設置某一列爲index:
In [131]: data.set_index(['name'],inplace=True) In [132]: data Out[132]: price name BTC 50000 ETH 4000 ae 200 In [133]: data.reset_index(inplace=True) #將index返回回dataframe中 In [134]: data Out[134]: name price 0 BTC 50000 1 ETH 4000 2 ae 200
處理缺失值:
In [149]: data Out[149]: name price 0 BTC 50000.0 1 ETH 4000.0 2 ae 200.0 3 eos NaN In [150]: data.dropna() #丟棄含有缺失值的行 Out[150]: name price 0 BTC 50000.0 1 ETH 4000.0 2 ae 200.0 In [151]: data.fillna(0) #填充缺失值數據爲0 Out[151]: name price 0 BTC 50000.0 1 ETH 4000.0 2 ae 200.0 3 eos 0.0
仍是須要注意:這些方法返回的是copy而不是視圖,若是想在原數據上改變,別忘了inplace=True。
數據合併:
In [160]: data Out[160]: name price 0 BTC 50000.0 1 ETH 4000.0 2 ae 200.0 3 eos NaN In [161]: data1 Out[161]: name other 0 BTC 50000 1 BTC 4000 2 EOS 150 In [162]: pd.merge(data,data1,on='name',how='left') #以name爲key進行左鏈接 Out[162]: name price other 0 BTC 50000.0 50000.0 1 BTC 50000.0 4000.0 2 ETH 4000.0 NaN 3 ae 200.0 NaN 4 eos NaN NaN
平時進行數據合併操做,更多的會出一種狀況,那就是出現重複值,DataFrame也爲咱們提供了簡便的方法:
data.drop_duplicates(inplace=True)
數據的簡單保存與讀取:
In [165]: data.to_csv('test.csv') In [166]: pd.read_csv('test.csv') Out[166]: Unnamed: 0 name price 0 0 BTC 50000.0 1 1 ETH 4000.0 2 2 ae 200.0 3 3 eos NaN
爲何會出現這種狀況呢,從頭看到尾的同窗可能就看出來了,增長第三行時,我用的是loc[‘3’]行標籤來增長的,而read_csv方法是默認index是從0開始增加的,此時只須要咱們設置下index參數就ok了:
In [167]: data.to_csv('test.csv',index=None) #不保存行索引 In [168]: pd.read_csv('test.csv') Out[168]: name price 0 BTC 50000.0 1 ETH 4000.0 2 ae 200.0 3 eos NaN
其餘的還有header參數, 這些參數都是咱們在保存數據時須要注意的。