pandas是本書後續內容的首選庫。pandas能夠知足如下需求:html
一、pandas數據結構介紹python
兩個數據結構:Series和DataFrame。Series是一種相似於覺得NumPy數組的對象,它由一組數據(各類NumPy數據類型)和與之相關的一組數據標籤(即索引)組成的。能夠用index和values分別規定索引和值。若是不規定索引,會自動建立 0 到 N-1 索引。web
#-*- encoding:utf-8 -*- import numpy as np import pandas as pd from pandas import Series,DataFrame #Series能夠設置index,有點像字典,用index索引 obj = Series([1,2,3],index=['a','b','c']) #print obj['a'] #也就是說,能夠用字典直接建立Series dic = dict(key = ['a','b','c'],value = [1,2,3]) dic = Series(dic) #下面注意能夠利用一個字符串更新鍵值 key1 = ['a','b','c','d'] #注意下面的語句能夠將 Series 對象中的值提取出來,不過要知道的字典是不能這麼作提取的 dic1 = Series(obj,index = key1) #print dic #print dic1 #isnull 和 notnull 是用來檢測缺失數據 #print pd.isnull(dic1) #Series很重要的功能就是按照鍵值自動對齊功能 dic2 = Series([10,20,30,40],index = ['a','b','c','e']) #print dic1 + dic2 #name屬性,能夠起名字 dic1.name = 's1' dic1.index.name = 'key1' #Series 的索引能夠就地修改 dic1.index = ['x','y','z','w']
DataFrame是一種表格型結構,含有一組有序的列,每一列能夠是不一樣的數據類型。既有行索引,又有列索引,能夠被看作由Series組成的字典(使用共同的索引)。跟其餘相似的數據結構(好比R中的data.frame),DataFrame面向行和列的操做基本是平衡的。其實,DataFrame中的數據是以一個或者多個二維塊存放的(不是列表、字典或者其餘)。數據庫
#-*- encoding:utf-8 -*- import numpy as np import pandas as pd from pandas import Series,DataFrame #構建DataFrame能夠直接傳入等長的列表或Series組成的字典 #不等長會產生錯誤 data = {'a':[1,2,3], 'c':[4,5,6], 'b':[7,8,9] } #注意是按照列的名字進行列排序 frame = DataFrame(data) #print frame #指定列以後就會按照指定的進行排序 frame = DataFrame(data,columns=['a','c','b']) print frame #能夠有空列,index是說行名 frame1 = DataFrame(data,columns = ['a','b','c','d'],index = ['one','two','three']) print frame1 #用字典方式取列數據 print frame['a'] print frame.b #列數據的修改直接選出來從新賦值便可 #行,能夠用行名或者行數來進行選取 print frame1.ix['two'] #爲列賦值,若是是Series,規定了index後能夠精確賦值 frame1['d'] = Series([100,200,300],index = ['two','one','three']) print frame1 #刪除列用del 函數 del frame1['d'] #警告:經過列名選出來的是Series的視圖,並非副本,可用Series copy方法獲得副本
另外一種常見的結構是嵌套字典,即字典的字典,這樣的結構會默認爲外鍵爲列,內列爲行。數組
#-*- encoding:utf-8 -*- import numpy as np import pandas as pd from pandas import Series,DataFrame #內層字典的鍵值會被合併、排序以造成最終的索引 pop = {'Nevada':{2001:2.4,2002:2.9}, 'Ohio':{2000:1.5,2001:1.7,2002:3.6}} frame3 = DataFrame(pop) #rint frame3 #Dataframe也有行和列有name屬性,DataFrame有value屬性 frame3.index.name = 'year' frame3.columns.name = 'state' print frame3 print frame3.values
下面列出了DataFrame構造函數可以接受的各類數據。安全
索引對象網絡
#-*- encoding:utf-8 -*- import numpy as np import pandas as pd from pandas import Series,DataFrame #pandas索引對象負責管理軸標籤和其餘元數據,構建Series和DataFrame時,所用到的任何數組或其餘序列的標籤都被轉換爲Index obj = Series(range(3),index = ['a','b','c']) index = obj.index #print index #索引對象是沒法修改的,這很是重要,由於這樣纔會使得Index對象在多個數據結構之間安全共享 index1 = pd.Index(np.arange(3)) obj2 = Series([1.5,-2.5,0],index = index1) print obj2.index is index1 #除了長得像數組,Index的功能也相似一個固定大小的集合 print 'Ohio' in frame3.columns print 2003 in frame3.index
pandas中的Index是一個類,pandas中主要的Index對象(何時用到)。數據結構
下面是Index的方法與屬性,值得注意的是:index並非數組。app
二、基本功能dom
下面介紹基本的Series 和 DataFrame 數據處理手段。首先是索引:
#-*- encoding:utf-8 -*- import numpy as np import pandas as pd import matplotlib.pyplot as plt from pandas import Series,DataFrame #Series有一個reindex函數,能夠將索引重排,以至元素順序發生變化 obj = Series([1,2,3,4],index=['a','b','c','d']) #注意這裏的reindex並不改變obj的值,獲得的是一個「副本」 #fill_value 顯然是填充空的index的值 #print obj.reindex(['a','c','d','b','e'],fill_value = 0) #print obj obj2 = Series(['red','blue'],index=[0,4]) #method = ffill,意味着前向值填充 obj3 = obj2.reindex(range(6),method='ffill') #print obj3 #DataFrame 的reindex能夠修改行、列或者兩個都改 frame = DataFrame(np.arange(9).reshape((3,3)),index = ['a','c','d'],columns = ['Ohio','Texas','California']) #只是傳入一列數,是對行進行reindex,由於...frame的行參數叫index...(我這麼猜的) frame2 = frame.reindex(['a','b','c','d']) #print frame2 #當傳入原來沒有的index是,固然返回的是空NaN #frame3 = frame.reindex(['e']) #print frame3 states = ['Texas','Utah','California'] #這是對行、列重排 #注意:這裏的method是對index 也就是行進行的填充,列是不能填充的(無論method的位置如何) frame4 = frame.reindex(index = ['a','b','c','d'],columns=states,method = 'ffill') #print frame4 #使用ix的標籤索引功能,從新索引變得比較簡潔 print frame.ix[['a','d','c','b'],states]
關於ix,是DataFrame的一個方法,http://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.DataFrame.ix.html。
丟棄指定軸上的項
#-*- encoding:utf-8 -*- import numpy as np import pandas as pd import matplotlib.pyplot as plt from pandas import Series,DataFrame #drop函數能夠丟棄軸上的列、行值 obj = Series(np.arange(3.),index = ['a','b','c']) #原Series並不丟棄 obj.drop('b') #print obj #注意下面,行能夠隨意丟棄,列須要加axis = 1 print frame.drop(['a']) print frame.drop(['Ohio'],axis = 1)
下面說索引、選取和過濾
#-*- encoding:utf-8 -*- import numpy as np import pandas as pd import matplotlib.pyplot as plt from pandas import Series,DataFrame obj = Series([1,2,3,4],index=['a','b','c','d']) frame = DataFrame(np.arange(9).reshape((3,3)),index = ['a','c','d'],columns = ['Ohio','Texas','California']) #Series切片和索引 #print obj[obj < 2] #注意:利用標籤的切片與python的切片不一樣,兩端都是包含的(有道理) print obj['b':'c'] #對於DataFrame,列能夠直接用名稱 print frame['Ohio'] #特殊狀況:經過切片和bool型索引,獲得的是行(有道理) print frame[:2] print frame[frame['Ohio'] != 0] #下面的方式是對frame全部元素都適用,不是行或者列,下面的獲得的是numpy.ndarray類型的數據 print frame[frame < 5],type(frame[frame < 5]) frame[frame < 5] = 0 print frame #對於DataFrame上的標籤索引,用ix進行 print frame.ix[['a','d'],['Ohio','Texas']] print frame.ix[2] #注意這裏默認取行 #注意下面默認取行 print frame.ix[frame.Ohio > 0] #注意下面的逗號後面是列標 print frame.ix[frame.Ohio > 0,:2]
下面是經常使用的索引選項:
算術運算和數據對齊
#pandas 有一個重要的功能就是可以根據索引自動對齊,其中索引不重合的部分值爲NaN s1 = Series([1,2,3],['a','b','c']) s2 = Series([4,5,6],['b','c','d']) #print s1 + s2 df1 = DataFrame(np.arange(12.).reshape(3,4),columns=list('abcd')) df2 = DataFrame(np.arange(20.).reshape(4,5),columns=list('abcde')) #print df1 + df2 #使用add方法,並傳入填充值,注意下面的fill_value函數是先對應填充再進行加和,而不是加和獲得NaN以後再填充 #print df1.add(df2,fill_value = 1000) #df1.reindex(columns = df2.columns,fill_value=0)
除了add以外,還有其餘的方法:
DataFrame和Series之間的運算
#下面看一下DataFrame和Series之間的計算過程 arr = DataFrame(np.arange(12.).reshape((3,4)),columns = list('abcd')) #下面的結果標明,就是按行分別相減便可,叫作 broadcasting #注意:默認狀況下,DataFrame和Series的計算會將Series的索引匹配到DataFrame的列,而後進行計算,再沿着行一直向下廣播 #注意:下面的式子中,若是寫arr - arr[0]是錯的,由於只有標籤索引函數ix後面加數字才表示行 print arr - arr.ix[0] Series2 = Series(range(3),index = list('cdf')) #按照規則,在不匹配的列會造成NaN值 print arr + Series2 #若是想匹配行且在列上廣播,須要用到算術運算方法 Series3 = arr['d'] #axis就是但願匹配的軸 print arr.sub(Series3,axis = 0)
下面是函數應用和映射
#-*- encoding:utf-8 -*- import numpy as np import pandas as pd import matplotlib.pyplot as plt from pandas import Series,DataFrame #NumPy的元素級數組方法也適用於pandas對象 frame = DataFrame(np.random.randn(4,3),columns = list('abc'),index = ['Ut','Oh','Te','Or']) print frame #下面是求絕對值: #print np.abs(frame) #另外一種常見的作法是:將一個函數應用到行或者列上,用apply方法,與R語言相似 fun = lambda x:x.max() - x.min() #默認是應用在每一列上 print frame.apply(fun) #下面是應用在列上 print frame.apply(fun,axis = 1) #不少統計函數根本不用apply,直接調用方法就能夠了 print frame.sum() #除了標量值以外,apply函數後面還能夠接返回多個值組成的的Series的函數,有沒有很漂亮? def f(x): return Series([x.min(),x.max()],index = ['min','max']) #print frame.apply(f) #元素級的python函數也是能夠用的,可是要使用applymap函數 format = lambda x: '%.2f' % x print frame.applymap(format) #之因此要用applymap是由於Series有一個應用於元素級函數的map方法?? #這裏的map頗有用 print frame['b'].map(format)
排序與排名
#-*- encoding:utf-8 -*- import numpy as np import pandas as pd import matplotlib.pyplot as plt from pandas import Series,DataFrame #用sort_index函數對行、列的索引進行排序 obj = Series(range(4),index = ['d','a','b','c']) print obj.sort_index() frame = DataFrame(np.arange(8).reshape((2,4)),index = ['three','one'],columns = ['d','a','b','c']) #默認是對行 「索引」 進行排序,若是對列 「索引」 進行排序,axis = 1 便可 print frame.sort_index() print frame.sort_index(axis = 1) print frame.sort_index(axis = 1,ascending = False) #若是對值進行排序,用的是order函數,注意全部的缺失值會放到最後(若是有的話) print obj.order() #numpy中的sort也能夠用來排序 print np.sort(obj) #若是相對DataFrame的值進行排序,函數仍是sort_index,只不事後面須要加一個參數by frame = DataFrame({'b':[4,7,-3,2],'a':[0,1,0,1]}) print frame.sort_index(by = ['a','b']) #rank函數返回從小到大排序的下標,對於平級的數,rank是經過「爲各組分配一個平均排名」的方式破壞評級關係 #下標從1開始 obj = Series([7,-5,7,4,2,0,4]) print obj.rank() #而numpy中的argsort函數比較奇怪,返回的是把數據進行排序以後,按照值得順序對應的下標,下標從0開始 print np.argsort(obj) #打印結果爲:1,5,4,3,6,0,2 按照這個下標順序剛好能夠獲得從小打到的值,見下面 print obj[np.argsort(obj)] #rank函數中有一個method選項,用來規定下標的方式 print obj.rank(method = 'first',ascending=False) print obj.rank(method = 'max',ascending=False) print obj.rank(method = 'min',ascending=False) #對於DataFrame,rank函數默認把每一列排好並返回座標 print frame.rank() print frame.rank(axis = 1)
帶有重複值的軸索引
#-*- encoding:utf-8 -*- import numpy as np import pandas as pd import matplotlib.pyplot as plt from pandas import Series,DataFrame #雖然pandas的不少函數(如reindex)要求標籤惟一,可是並不具備強制性 obj = Series(range(5),index = list('aabbc')) print obj #索引是否惟一用is_unique看是否惟一 print obj.index.is_unique #對於重複值的索引,選取的話返回一個Series,惟一的索引返回一個標量 print obj['a'] #對於DataFrame也是如此 df = DataFrame(np.random.randn(4,3),index = list('aabb')) print df print df.ix['b'] #####本身導入數據的時候數據處理以前能夠作一下index惟一性等,本身建立DataFrame注意不能這樣
三、彙總和計算描述統計
#-*- encoding:utf-8 -*- import numpy as np import os import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt import time #pandas 對象擁有一組經常使用的數學和統計方法,大部分屬於簡約統計,用於從Series中提取一個值,或者 從DataFrame中提取一列或者一行Series #注意:與NumPy數組相比,這些函數都是基於沒有缺失數據的建設構建的,也就是說:這些函數會自動忽略缺失值。 df = DataFrame([[1.4,np.nan],[7.1,-4.5],[np.nan,np.nan],[0.75,-1.3]],index = list('abcd'),columns=['one','two']) print df.sum() print df.sum(axis = 1) #下面是一些函數,idxmin 和 idmax 返回的是達到最小或者最大的索引 print df.idxmin() print df.idxmin(axis=1) #關於累積型的函數 print df.cumsum() #describe函數,與R語言中的describe函數基本相同 print df.describe() #對於非數值型的數據,看看下面的結果 obj = Series(['c','a','a','b','d'] * 4) print obj.describe() ''' 結果爲: count 20 unique 4 top a freq 8 其中,freq是指字母出現的最高頻率 '''
#-*- encoding:utf-8 -*- import numpy as np import os import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt import time #下面看一下cummin函數 #注意:這裏的cummin函數是截止到目前爲止的最小值,而不是加和之後的最小值 frame = DataFrame([[1,2,3,4],[5,6,7,8],[-10,11,12,-13]],index = list('abc'),columns = ['one','two','three','four']) print frame.cummin() print frame
>>>
one two three four
a 1 2 3 4
b 1 2 3 4
c -10 2 3 -13
one two three four
a 1 2 3 4
b 5 6 7 8
c -10 11 12 -13
相關係數與協方差
有些彙總統計(如相關係數和協方差)是經過參數對計算出來的。這一節數據得不到?上不去網。
惟一值、值計數以及成員資格
#-*- encoding:utf-8 -*- import numpy as np import os import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt obj = Series(['a','a','b','f','e']) uniques = obj.unique() uniques.sort() #記住這是就地排序 #print uniques #下面進行計數統計,注意獲得的是按照出現的頻率降序排列 #print obj.value_counts() #value_counts仍是一個頂級的pandas方法。可用於任何是數組或者序列 #print obj.values #print pd.value_counts(obj.values,sort = False) #最後是isin 判斷矢量化集合的成員資格,可用於選取Series中或DataF列中的子集 mask = obj.isin(['b','c']) print mask print obj[mask] data = DataFrame({'Qu1':[1,3,4,3,4], 'Qu2':[2,3,1,2,3], 'Qu3':[1,5,2,4,4]}) print data print data.apply(pd.value_counts).fillna(0)
上面這幾個函數是真的很是實用!
四、處理缺失數據
#-*- encoding:utf-8 -*- import numpy as np import os import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt import time from numpy import nan as NA #pandas原本就被設計成自動忽略了缺失值、 #nan None 都看作缺失值 str_data = Series(['a',np.nan,'b','c']) str_data[0] = None print str_data.isnull() print str_data.notnull()
>>>
0 True
1 True
2 False
3 False
0 False
1 False
2 True
3 True
#NumPy的數據類型中缺乏真正的NA數據類型或位模式??
濾除缺失數據
#-*- encoding:utf-8 -*- import numpy as np import os import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt import time from numpy import nan as NA data = Series([1,NA,3.5,7,NA]) #注意返回的是不爲NA的值的原來的索引,不是移除以後的索引
#有一個函數 reset_index 這個函數(方法?)能夠從新設置index,其中drop = True選項會丟棄原來的索引而設置新的從0開始的索引,這個方法只對DataFrame有用貌似。
print data.dropna() #下面的結果同樣 print data[data.notnull()] data1 = DataFrame([[1,2,3],[NA,2.3,4],[NA,NA,NA]]) #注意:因爲DataFrame的設定,只要有NA的行就會捨棄 print data1.dropna() #傳入how = 'all' 則丟掉全爲NA的行,這裏的 how 的起名真的有點爲所欲爲了,哈哈 print data1.dropna(how = 'all') #丟棄列 print data1.dropna(how = 'all',axis = 1) #還有一個參數,thresh data2 = DataFrame(np.random.randn(7,3)) data2.ix[:4,1] = NA data2.ix[:2,2] = NA #print data2 #這裏的thresh函數是選取最少non-NA值個數的行選出來 print data2.dropna(thresh = 2) print data2.dropna(thresh = 4,axis = 1)
填充缺失數據
#-*- encoding:utf-8 -*- import numpy as np import os import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt import time from numpy import nan as NA #主要用fillna方法填充NA處的值 data2 = DataFrame(np.random.randn(7,3)) data2.ix[:4,1] = NA data2.ix[:2,2] = NA #fillna返回一個新對象,inplace = True 能夠就地填充 print data2.fillna(0) #print data2.fillna(0,inplace = True) #print data2 #爲不一樣的列填充要用到字典 print data2.fillna({1:0.5,3:-1}) #對reindex有效的的那些差值方法也可適用於fillna,請向上看,或者搜索 reindex 便可 df = DataFrame(np.random.randn(6,3)) df.ix[2:,1] = NA df.ix[4:,2] = NA print df.fillna(method = 'ffill',limit = 2) #只要稍微動動腦子,咱們就能夠知道向NA處能夠填充均值等其餘數 data = Series([1.2,NA,4,NA]) print data.fillna(data.mean())
fillna的參數以下:
五、層次化索引
層次化索引(hierarchical index)是pandas的重要功能,這能使在一個軸上擁有兩個以上的索引級別。抽象點說,它能使你以低維度形式處理高維度。
#-*- encoding:utf-8 -*- import numpy as np import os import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt import time data = 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]]) #print data #下面是索引的選取方式 print data.index print data['b'] print data['b':'c'] print data.ix[['b','d']] #下面是「內層」的選取方式 print data[:,2] #層次化索引在數據重塑和基於分組操做(如透視表生成)中扮演者重要的角色,好比用unstack方式重排DataFrame: print data.unstack() #stack是unstack的逆運算 print data.unstack().stack() #對於DataFrame,每一個軸均可以有分層索引 frame = DataFrame(np.arange(12).reshape((4,3)),index = [['a','a','b','b'],[1,2,1,2]],columns = [['Ohio','Ohio','Colorado'],['Green','Red','Green']]) #print frame #注意下面的方式:是爲每個軸規定名字,跟 frame.index.names = ['key1','key2'] frame.columns.names = ['state','color'] #print frame #print frame['Ohio'] #能夠單首創建MultiIndex而後複用 #下面的multiindex能夠這樣建立,注意下面的生成方式 columns = pd.MultiIndex.from_arrays([['Ohio','Ohio','Colorado'],['Green','Red','Green']],names = ['state','color']) frame1 = DataFrame(np.arange(12).reshape((4,3)),columns = columns) print frame1 #重排順序,調整索引級別 print frame.swaplevel('key1','key2') #sortlevel則根據但各級別中的值對數據進行排序,一般用swaplevel是也會用到sortlevel(很合理) #注意獲得的是副本,不是就地修改 print frame.sortlevel(1) print frame.swaplevel(0,1).sortlevel(0) print frame #許多對DataFrame和Series進行描述彙總的統計都有一個level選項,用於指定彙總方式 print frame.sum(level = 'key2') #不指定level的話,會按照列彙總出全部列名的和 print frame.sum() print frame.sum(level = 'color',axis = 1)
#-*- encoding:utf-8 -*- import numpy as np import os import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt import time #人們常常想將DataFrame的一個或者多個列看成行索引來用,或者可能須要將行索引變成DataFrame的列 frame = DataFrame({'a':range(7),'b':range(7,0,-1),'c':['one','one','one','two','two','two','two'],'d':[0,1,2,0,1,2,3]}) print frame #DataFrame中的set_index函數會將其一個或者多個列轉換爲行索引 frame2 = frame.set_index(['c','d']) print frame2 #其實就是利用第三、4列進行一次分類彙總 frame3 = frame.set_index(['c','d'],drop = False) #與set_index相反的是reset_index函數 print frame2.reset_index() #下面進行一次測試 frame4 = DataFrame([[0,7],[1,6],[2,5],[3,4],[4,3],[5,2],[6,1]],index = [['one','one','one','two','two','two','two'],[0,1,2,0,1,2,3]],columns=['a','b']) frame4.index.names = ['c','d'] print frame4 print frame4.reset_index().sort_index(axis = 1)
其餘有關pandas的話題
#-*- encoding:utf-8 -*- import numpy as np import os import pandas as pd from pandas import Series,DataFrame import matplotlib.pyplot as plt import pandas.io.data as web #這裏說的是一些蛋疼的問題:整數索引和整數標籤 ser = Series(np.arange(3.)) #print ser[-1] #報錯,由於整數索引的歧義性 ser2 = Series(np.arange(3.),index = ['a','b','c']) print ser2[-1] #正確 #ix函數老是面向標籤的 print ser.ix[:1] #若是須要可靠的、不考慮索引類型的、基於位置的索引,可使用Series的iget_value方法,Dataframe的irow 和 icol方法 ser3 = Series(range(3),index= [-5,1,3]) print ser3.iget_value(2) frame = DataFrame(np.arange(6).reshape(3,2),index = [2,0,1]) print frame.irow(0) #pandas 有一個Panel數據結構(不是主要內容),能夠看做是三維的DataFrame。pandas中的多維數據能夠利用多層索引進行處理 #能夠利用DataFrame對象組成的字典或者一個三維ndarray來建立Panel對象 pdata = pd.Panel(dict((stk,web.get_data_yahoo(stk,'1/1/2009','6/1/2012')) for stk in ['AAPL','GOOG','MSFT','DELL'])) #網絡錯誤,得不到數據 #Panel的每一項都是一個DataFrame.