目錄:
5.1 pandas 的數(shù)據(jù)結(jié)構(gòu)介紹
5.1.1 Series
5.1.2 DataFrame
5.1.3索引對象
5.2基本功能
5.2.1重新索引
5.2.2丟棄指定軸上的項(xiàng)
5.2.3索引、選取和過濾
5.2.4算術(shù)運(yùn)算和數(shù)據(jù)對齊
5.2.4.1在算術(shù)方法中填充值
5.2.4.2 DataFrame和Series之間的運(yùn)算
5.2.5函數(shù)應(yīng)用和映射
5.2.6排序和排名
5.2.7帶有重復(fù)的軸索引
5.3匯總和計(jì)算描述性統(tǒng)計(jì)
5.3.1相關(guān)系數(shù)和協(xié)方差
5.3.2唯一值、值計(jì)數(shù)以及成員資格
5.4處理缺失數(shù)據(jù)
5.4.1濾除缺失數(shù)據(jù)
5.4.2填充缺失數(shù)據(jù)
5.5層次化索引
5.5.1重排分級順序
5.5.2根據(jù)級別匯總統(tǒng)計(jì)
5.5.3使用DataFrame的列
5.6其他有關(guān)pandas的話題
5.6.1整數(shù)索引
第5章 pandas入門
pandas 引入約定
In [1]: from pandas import Series,DataFrame
In [2]: import pandas as pd
5.1 pandas 的數(shù)據(jù)結(jié)構(gòu)介紹
要使用pandas,首先要熟悉他的兩個(gè)主要的數(shù)據(jù)結(jié)構(gòu):Series和DataFrame。
5.1.1 Series
Series 是一種類似于一維數(shù)組的對象,由一組數(shù)據(jù)(各種numpy數(shù)據(jù)類型)以及一組與之相關(guān)的數(shù)據(jù)標(biāo)簽(即索引)組成。
僅由一組數(shù)據(jù)即可產(chǎn)生最簡單的Series:
In [3]: obj=Series([4,7,-5,3])
In [4]: obj
Out[4]:
0? ? 4
1? ? 7
2? -5
3? ? 3
dtype: int64
serice 的字符串表現(xiàn)形式為:索引在左邊,值在右邊。
由于我們沒有為數(shù)據(jù)指定索引,于是會自動(dòng)創(chuàng)建一個(gè)0到N-1(N位數(shù)據(jù)的長度)的整數(shù)的索引。
可以通過series的values和index屬性獲取其數(shù)組表現(xiàn)形式和索引對象。
In [6]: obj.values #表現(xiàn)形式
Out[6]: array([ 4,? 7, -5,? 3], dtype=int64)
In [7]: obj.index #索引對象
Out[7]: RangeIndex(start=0, stop=4, step=1)
通常我們希望所創(chuàng)建的Series帶有一個(gè)可以對各個(gè)數(shù)據(jù)點(diǎn)進(jìn)行標(biāo)記的索引:
In [11]: obj2['a']
Out[11]: -5
In [12]: obj2['d']=6
In [13]: obj2[['c','a','d']]
Out[13]:
c? ? 3
a? -5
d? ? 6
dtype: int64
NumPy數(shù)組運(yùn)算(若根據(jù)布爾型數(shù)組進(jìn)行過濾,標(biāo)量乘法,應(yīng)用數(shù)學(xué)函數(shù)等)都會保留索引和值之間的鏈接:
In [14]: obj2
Out[14]:
d? ? 6
b? ? 7
a? -5
c? ? 3
dtype: int64
In [15]: obj2[obj2>0]
Out[15]:
d? ? 6
b? ? 7
c? ? 3
dtype: int64
In [16]: obj2*2
Out[16]:
d? ? 12
b? ? 14
a? -10
c? ? 6
dtype: int64
In [19]: np.exp(obj2)
Out[19]:
d? ? 403.428793
b? ? 1096.633158
a? ? ? 0.006738
c? ? ? 20.085537
dtype: float64
我們也可以將Serice看成一個(gè)定長的有序字典,因?yàn)樗撬饕档綌?shù)據(jù)值的一個(gè)映射??梢杂迷谠S多原本需要字典參數(shù)的函數(shù)中:
In [20]: 'b' in obj2
Out[20]: True
In [21]: 'e' in obj2
Out[21]: False
如果數(shù)據(jù)被存放在一個(gè)python字典中,可以直接通過這個(gè)字典來創(chuàng)建Series
In [4]: sdata={'Ohio':35000,'Texas':71000,'Oregon':16000,'Utah':5000}
In [5]: obj3=Series(sdata)
In [6]: obj3
Out[6]:
Ohio? ? ? 35000
Oregon? ? 16000
Texas? ? 71000
Utah? ? ? 5000
dtype: int64
只傳入一個(gè)字典,則結(jié)果Series中索引就是原字典的鍵(有序排列)
In [7]: states=['California','Ohio','Oregon','Texas']
In [8]: obj4=Series(sdata,index=states)
In [9]: obj4
Out[9]:
California? ? ? ? NaN? ? #“California ”的值找不到,結(jié)果用NaN來代替。
Ohio? ? ? ? ? 35000.0
Oregon? ? ? ? 16000.0
Texas? ? ? ? 71000.0
dtype: float64
pandas的isnull和notnull函數(shù)可以用于檢測缺失數(shù)據(jù):
In [10]: pd.isnull(obj4)
Out[10]:
California? ? True
Ohio? ? ? ? ? False
Oregon? ? ? ? False
Texas? ? ? ? False
dtype: bool
In [11]: pd.notnull(obj4)
Out[11]:
California? ? False
Ohio? ? ? ? ? True
Oregon? ? ? ? True
Texas? ? ? ? ? True
dtype: bool
Series也有類似的實(shí)例方法:
In [12]: obj4.isnull()
Out[12]:
California? ? True
Ohio? ? ? ? ? False
Oregon? ? ? ? False
Texas? ? ? ? False
dtype: bool
Series重要的一個(gè)功能是:它在算術(shù)中會自動(dòng)對齊不同索引的數(shù)據(jù)。
In [13]: obj3
Out[13]:
Ohio? ? ? 35000
Oregon? ? 16000
Texas? ? 71000
Utah? ? ? 5000
dtype: int64
In [14]: obj4
Out[14]:
California? ? ? ? NaN
Ohio? ? ? ? ? 35000.0
Oregon? ? ? ? 16000.0
Texas? ? ? ? 71000.0
dtype: float64
In [15]: obj3+obj4
Out[15]:
California? ? ? ? NaN
Ohio? ? ? ? ? 70000.0
Oregon? ? ? ? 32000.0
Texas? ? ? ? 142000.0
Utah? ? ? ? ? ? ? NaN
dtype: float64
Series對象本身及其索引都有一個(gè)name屬性,該屬性跟pandas其他關(guān)鍵功能關(guān)系非常密切:
In [16]: obj4.name='population'
In [17]: obj4.index.name='state'
In [18]: obj4
Out[18]:
state
California? ? ? ? NaN
Ohio? ? ? ? ? 35000.0
Oregon? ? ? ? 16000.0
Texas? ? ? ? 71000.0
Name: population, dtype: float64
Series 的索引可以通過賦值的方式就地修改:
In [20]: obj=Series([4,7,-5,3])
In [21]: obj.index=['Bob','Steve','Jeff','Ryan']
In [22]: obj
Out[22]:
Bob? ? ? 4
Steve? ? 7
Jeff? ? -5
Ryan? ? 3
dtype: int64
5.1.2 DataFrame
DataFrame是一個(gè)表格型的數(shù)據(jù)結(jié)構(gòu),含有一組有序的列,每列可以是不同的值類型(數(shù)值,字符串,布爾值等)
DataFrame既有行索引也有列索引,可以被看做是由Series組成的字典。
跟其他的類似的數(shù)據(jù)結(jié)構(gòu)相比(如R的data.frame),DataFrame中面向行和列的操作基本是平衡的。
DataFrame中的數(shù)據(jù)是以一個(gè)或多個(gè)二維塊存放的。
構(gòu)建DataFrame的辦法有很多,最常用的一種是直接傳入一個(gè)由等長列表或numpy組成的數(shù)組組成的字典:
In [5]: from pandas import Series,DataFrame
In [6]: import pandas as pd
In [7]: 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 [8]: frame=DataFrame(data)
結(jié)果DataFrame'會自動(dòng)加上索引(跟Series一樣),且全部列會被有序排列:
In [10]: frame
Out[10]:
pop? state? year
0? 1.5? ? Ohio? 2000
1? 1.7? ? Ohio? 2001
2? 3.6? ? Ohio? 2002
3? 2.4? Nevada? 2001
4? 2.9? Nevada? 2002
指定列序列,DataFrame的列就會按照指定順序進(jìn)行排列:
In [11]: DataFrame(data,columns=['year','state','pop'])
Out[11]:
year? state? pop
0? 2000? ? Ohio? 1.5
1? 2001? ? Ohio? 1.7
2? 2002? ? Ohio? 3.6
3? 2001? Nevada? 2.4
4? 2002? Nevada? 2.9
跟Series一樣,如果傳入的列在數(shù)據(jù)中找不到,就會產(chǎn)生NA值:
In [11]:? frame2=DataFrame(data,columns=['year','state','pop','debt']
...: ,index=['one','two','three','four','five'])
In [12]: frame2
Out[12]:
year? state? pop debt
one? ? 2000? ? Ohio? 1.5? NaN
two? ? 2001? ? Ohio? 1.7? NaN
three? 2002? ? Ohio? 3.6? NaN
four? 2001? Nevada? 2.4? NaN
five? 2002? Nevada? 2.9? NaN
In [26]: frame2.columns
Out[26]: Index([u'years', u'state', u'pop', u'debt'], dtype='object')
通過類似于字典標(biāo)記的方式或?qū)傩缘姆绞剑梢詫ataFrame的列獲取為一個(gè)Series:
In [27]: frame2['state']
Out[27]:
one? ? ? ? Ohio
two? ? ? ? Ohio
three? ? ? Ohio
four? ? Nevada
five? ? Nevada
Name: state, dtype: object
In [18]: frame2.year
Out[18]:
one? ? ? 2000
two? ? ? 2001
three? ? 2002
four? ? 2001
five? ? 2002
Name: year, dtype: int64
注意,返回的Series擁有原DataFrame相同的索引,且其name屬性也已經(jīng)被相應(yīng)的設(shè)置好了。
行也可以通過位置或名稱的方式來進(jìn)行獲取。
In [19]: frame2.ix['three']
Out[19]:
year? ? 2002
state? ? Ohio
pop? ? ? 3.6
debt? ? ? NaN
Name: three, dtype: object
列可以通過賦值的方式進(jìn)行修改。如下,我們可以給空的”debt“列賦值一個(gè)標(biāo)量或一組值。
In [20]: frame2['debt']=16.5
In [21]: frame2
Out[21]:
year? state? pop? debt
one? ? 2000? ? Ohio? 1.5? 16.5
two? ? 2001? ? Ohio? 1.7? 16.5
three? 2002? ? Ohio? 3.6? 16.5
four? 2001? Nevada? 2.4? 16.5
five? 2002? Nevada? 2.9? 16.5
In [24]: frame2['debt']=np.arange(5.)
In [25]: frame2
Out[25]:
year? state? pop? debt
one? ? 2000? ? Ohio? 1.5? 0.0
two? ? 2001? ? Ohio? 1.7? 1.0
three? 2002? ? Ohio? 3.6? 2.0
four? 2001? Nevada? 2.4? 3.0
five? 2002? Nevada? 2.9? 4.0
將列表或數(shù)組賦值給某個(gè)列的時(shí)候,其長度必須要跟DataFrame的長度向匹配。如果賦值的是一個(gè)個(gè)Series ,就會精確的匹配DataFrame的索引,所有的空位都將被填上的缺失值。
In [26]: val=Series([-1.2,-1.5,-1.7],index=['two','four','five'])
In [27]: frame2['debt']=val
In [28]: frame2
Out[28]:
year? state? pop? debt
one? ? 2000? ? Ohio? 1.5? NaN
two? ? 2001? ? Ohio? 1.7? -1.2
three? 2002? ? Ohio? 3.6? NaN
four? 2001? Nevada? 2.4? -1.5
five? 2002? Nevada? 2.9? -1.7
為不存在的列賦值會創(chuàng)建一個(gè)新列。關(guān)鍵字del用于刪除列:
In [29]: frame2['eastern']=frame2.state=='Ohio'
In [30]: frame2
Out[30]:
year? state? pop? debt eastern
one? ? 2000? ? Ohio? 1.5? NaN? ? True
two? ? 2001? ? Ohio? 1.7? -1.2? ? True
three? 2002? ? Ohio? 3.6? NaN? ? True
four? 2001? Nevada? 2.4? -1.5? False
five? 2002? Nevada? 2.9? -1.7? False
In [31]: del frame2['eastern']
In [32]: frame2.columns
Out[32]: Index([u'year', u'state', u'pop', u'debt'], dtype='object')
另一種常見的數(shù)據(jù)形式是嵌套字典(也就是字典的字典):
In [33]: pop={'Nevada':{2001:2.4,2002:2.9},'Ohio':{2000:1.5,2001:1.7,
...: 2002:3.6}}
將它傳給DataFrame,就會被解釋為:外層字典的鍵作為列,內(nèi)層鍵作為行索引。
In [34]: frame3=DataFrame(pop)
In [35]: frame3
Out[35]:
Nevada? Ohio
2000? ? NaN? 1.5
2001? ? 2.4? 1.7
2002? ? 2.9? 3.6
也可以對結(jié)果進(jìn)行轉(zhuǎn)置:
In [36]: frame3.T
Out[36]:
2000? 2001? 2002
Nevada? NaN? 2.4? 2.9
Ohio? ? 1.5? 1.7? 3.6
內(nèi)層字典的鍵會被合并、排序以及形成最終的索引。若指定了顯式索引,則不會這樣:
In [37]: DataFrame(pop,index=[2001,2002,2003])
Out[37]:
Nevada? Ohio
2001? ? 2.4? 1.7
2002? ? 2.9? 3.6
2003? ? NaN? NaN
由Series組成的字典差不多也是一樣的用法:
In [40]: pdata={'Ohio':frame3['Ohio'][:-1],'Nevada':frame3['Nevada'][:2]}
In [41]: DataFrame(pdata)
Out[41]:
Nevada? Ohio
2000? ? NaN? 1.5
2001? ? 2.4? 1.7
如果設(shè)置了Data.Frame的index屬性和columns的name屬性,
In [42]: frame3.index.name='year';frame3.columns.name='state'
In [43]: frame3
Out[43]:
state? Nevada? Ohio
year
2000? ? ? NaN? 1.5
2001? ? ? 2.4? 1.7
2002? ? ? 2.9? 3.6
In [44]: frame3.values
Out[44]:
array([[ nan,? 1.5],
[ 2.4,? 1.7],
[ 2.9,? 3.6]])
In [45]: frame3.values
Out[45]:
array([[ nan,? 1.5],
[ 2.4,? 1.7],
[ 2.9,? 3.6]])
5.1.3索引對象
pandas的索引對象負(fù)責(zé)管理標(biāo)簽和其他元數(shù)據(jù)(比如軸名稱等)。構(gòu)建Series或DataFrame時(shí),所用到的任何數(shù)組或其他序列的標(biāo)簽都會被轉(zhuǎn)換成一個(gè)Index:
In [2]: import numpy as np
In [3]: import pandas as pd
In [5]: from pandas import Series,DataFrame
In [6]: obj=Series(range(3),index=['a','b','c'])
In [7]: index=obj.index
In [8]: index
Out[8]: Index([u'a', u'b', u'c'], dtype='object')
In [9]: index[1:]
Out[9]: Index([u'b', u'c'], dtype='object')
Index對象是不可修改的,因此用戶不能對其修改:
In [10]: index[1]='d'
---------------------------------------------------------------------------
TypeError? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Traceback (most recent call last)
in ()
----> 1 index[1]='d'
H:\Anaconda2-4.3.0.1\lib\site-packages\pandas\indexes\base.pyc in __setitem__(self, key, value)
1402
1403? ? def __setitem__(self, key, value):
-> 1404? ? ? ? raise TypeError("Index does not support mutable operations")
1405
1406? ? def __getitem__(self, key):
TypeError: Index does not support mutable operations
不可修改性非常重要,因?yàn)檫@樣才能使得index對象在多個(gè)數(shù)據(jù)結(jié)構(gòu)之間安全共享:
In [12]: index=pd.Index(np.arange(3))
In [13]: obj2=Series([1.5,-2.5,0],index=index)
In [14]: obj2=Series([1.5,-2.5,0],index=index)
In [16]: obj2.index is index
Out[16]: True
除了長得像數(shù)組,index的功能也類似一個(gè)固定大小的集合:
In [43]: frame3
Out[43]:
state? Nevada? Ohio
year
2000? ? ? NaN? 1.5
2001? ? ? 2.4? 1.7
2002? ? ? 2.9? 3.6
In [46]: 'Ohio' in frame3.columns
Out[46]: True
In [47]: 2003 in frame3.index
Out[47]: False
5.2基本功能
介紹操作Series和DataFrame中的數(shù)據(jù)的基本手段。
5.2.1重新索引
pandas對象的一個(gè)重要的方法就是reindex,作用是創(chuàng)建一個(gè)適應(yīng)新索引的新對象。
In [33]:? import pandas as pd
from pandas import Series,DataFrame
In [34]: obj=Series([4.5,7.2,-5.3,3.6],index=['d','b','a','c'])
In [35]: obj
Out[35]:
d? ? 4.5
b? ? 7.2
a? -5.3
c? ? 3.6
dtype: float64
調(diào)用該Series的reindex將會根據(jù)新索引進(jìn)行重排。如果某個(gè)索引值當(dāng)前不存,就引入缺失值:
In [36]: obj2=obj.reindex(['a','b','c','d','e'])
In [37]: obj2
Out[37]:
a? -5.3
b? ? 7.2
c? ? 3.6
d? ? 4.5
e? ? NaN
dtype: float64
In [38]:? obj.reindex(['a','b','c','d','e'],fill_value=0)
Out[38]:
a? -5.3
b? ? 7.2
c? ? 3.6
d? ? 4.5
e? ? 0.0
dtype: float64
對于時(shí)間序列這樣的有序數(shù)據(jù),重新索引時(shí)可能需要做一些插值處理。method選項(xiàng)即可用達(dá)到此目的。例如:ffill可以實(shí)現(xiàn)向前值填充:
In [39]: obj3=Series(['blue','purple','yellow'],index=[0,2,4])
In [40]: obj3.reindex(range(6),method='ffill')
Out[40]:
0? ? ? blue
1? ? ? blue
2? ? purple
3? ? purple
4? ? yellow
5? ? yellow
dtype: object
下表中列出了可用的method選項(xiàng)。
參數(shù) 說明
fill或pad 前向填充(或搬運(yùn))值
bfill或backfill 后向填充(或搬運(yùn))值
對于DataFrame,reindex可以修改(行)索引,列,或兩個(gè)都修改。如果僅傳入一個(gè)序列,則會重新索引行:
In [41]: frame=DataFrame(np.arange(9).reshape((3,3)),index=['a','c','d'],columns=['Ohio','Texas','California',])
In [52]: frame
Out[53]:
Ohio? Texas? California
a? ? 0? ? ? 1? ? ? ? ? 2
c? ? 3? ? ? 4? ? ? ? ? 5
d? ? 6? ? ? 7? ? ? ? ? 8
In [54]: frame2=frame.reindex(['a','b','c','d'])
In [55]:frame2
Out[55]:
Ohio? Texas? California
a? 0.0? ? 1.0? ? ? ? 2.0
b? NaN? ? NaN? ? ? ? NaN
c? 3.0? ? 4.0? ? ? ? 5.0
d? 6.0? ? 7.0? ? ? ? 8.0
使用columns關(guān)鍵字即可以重新索引。
In [56]: states=['Texas','Utah','California']
frame.reindex(columns=states)
Out[57]:
Texas? Utah? California
a? ? ? 1? NaN? ? ? ? ? 2
c? ? ? 4? NaN? ? ? ? ? 5
d? ? ? 7? NaN? ? ? ? ? 8
也可以同時(shí)對行和列進(jìn)行重新索引,而插值則只能按行應(yīng)用(即軸0):
frame.reindex(index=['a','b','c','d'],method='ffill',columns=states)
Out[58]:
Texas? Utah? California
a? ? ? 1? NaN? ? ? ? ? 2
b? ? ? 1? NaN? ? ? ? ? 2
c? ? ? 4? NaN? ? ? ? ? 5
d? ? ? 7? NaN? ? ? ? ? 8
利用ix的標(biāo)簽的=索引功能,重新索引任務(wù)可以變得簡潔:
frame.ix[['a','b','c','d'],states]
Out[59]:
Texas? Utah? California
a? ? 1.0? NaN? ? ? ? 2.0
b? ? NaN? NaN? ? ? ? NaN
c? ? 4.0? NaN? ? ? ? 5.0
d? ? 7.0? NaN? ? ? ? 8.0
5.2.2丟棄指定軸上的項(xiàng)
丟棄某條軸上的一個(gè)或多個(gè)項(xiàng),只要有一個(gè)索引數(shù)組或列表即可。
由于需要執(zhí)行一些數(shù)據(jù)整理和集合邏輯,所以drop方法返回的是一個(gè)在指定軸上刪除了指定值的新對象:
In [60]: obj=Series(np.arange(5.),index=['a','b','c','d','e'])
In [61]: new_obj=obj.drop('c')
In [62]: new_obj
Out[62]:
a? ? 0.0
b? ? 1.0
d? ? 3.0
e? ? 4.0
dtype: float64
In[63]: obj.drop(['d','c'])
Out[63]:
a? ? 0.0
b? ? 1.0
e? ? 4.0
dtype: float64
對于DataFrame,可以刪除任意軸上的索引值:
In [66]: data=DataFrame(np.arange(16).reshape((4,4)),index=['Ohio','Colorado','Utah','New York'],columns=['one','two','three','four'])
In[67]: data.drop(['Colorado','Ohio'])
Out[67]:
one? two? three? four
Utah? ? ? ? 8? ? 9? ? 10? ? 11
New York? 12? 13? ? 14? ? 15
In [68]: data.drop('two',axis=1)
Out[68]:
one? three? four
Ohio? ? ? ? 0? ? ? 2? ? 3
Colorado? ? 4? ? ? 6? ? 7
Utah? ? ? ? 8? ? 10? ? 11
New York? 12? ? 14? ? 15
In [69]: data.drop(['two','four'],axis=1)
Out[69]:
one? three
Ohio? ? ? ? 0? ? ? 2
Colorado? ? 4? ? ? 6
Utah? ? ? ? 8? ? 10
New York? 12? ? 14
5.2.3索引、選取和過濾
Series索引 (obj[...])的工作方式類似于NumPy數(shù)組的索引,只不過Series的索引值不只是整數(shù)。例:
In [5]: obj=Series(np.arange(4.),index=['a','b','c','d'])
In [6]: obj['b']
Out[6]: 1.0
In [7]: obj[1]
Out[7]: 1.0
In [8]: obj[2:4]
Out[8]:
c? ? 2.0
d? ? 3.0
dtype: float64
In [10]: obj[['b','a','d']]
Out[10]:
b? ? 1.0
a? ? 0.0
d? ? 3.0
dtype: float64
In [11]: obj[[1,3]]
Out[11]:
b? ? 1.0
d? ? 3.0
dtype: float64
In [12]: obj[obj<2]
Out[12]:
a? ? 0.0
b? ? 1.0
dtype: float64
利用標(biāo)簽的切片運(yùn)算與普通的python切片運(yùn)算不同,其末端是包含的(inclusive)
In [19]: obj['b':'c']
Out[19]:
b? ? 1.0
c? ? 2.0
dtype: float64
設(shè)置方式如下:
In [20]: obj['b':'c']=5
In [21]: obj
Out[21]:
a? ? 0.0
b? ? 5.0
c? ? 5.0
d? ? 3.0
dtype: float64
如你所見,對DataFrame進(jìn)行索引其實(shí)就是獲取一個(gè)或多個(gè)列:
In [24]: data=DataFrame(np.arange(16).reshape((4,4)),
index=['Ohio','Colorado','Utah','New York'],columns=['one','two','three','four'])
In [25]: data
Out[25]:
one? two? three? four
Ohio? ? ? ? 0? ? 1? ? ? 2? ? 3
Colorado? ? 4? ? 5? ? ? 6? ? 7
Utah? ? ? ? 8? ? 9? ? 10? ? 11
New York? 12? 13? ? 14? ? 15
In [26]: data['two']
Out[26]:
Ohio? ? ? ? 1
Colorado? ? 5
Utah? ? ? ? 9
New York? ? 13
Name: two, dtype: int32
In [28]: data[['three','one']]
Out[28]:
three? one
Ohio? ? ? ? ? 2? ? 0
Colorado? ? ? 6? ? 4
Utah? ? ? ? 10? ? 8
New York? ? 14? 12
In [30]: data[['three','one']]
Out[30]:
three? one
Ohio? ? ? ? ? 2? ? 0
Colorado? ? ? 6? ? 4
Utah? ? ? ? 10? ? 8
New York? ? 14? 12
這種索引方式有幾個(gè)特殊情況。首先通過切片或布爾數(shù)組進(jìn)行選取行:
In [29]: data[:2]
Out[29]:
one? two? three? four
Ohio? ? ? ? 0? ? 1? ? ? 2? ? 3
Colorado? ? 4? ? 5? ? ? 6? ? 7
In [31]: data[data['three']>5]
Out[31]:
one? two? three? four
Colorado? ? 4? ? 5? ? ? 6? ? 7
Utah? ? ? ? 8? ? 9? ? 10? ? 11
New York? 12? 13? ? 14? ? 15
另一種用法使通過布爾型DataFrame進(jìn)行索引:
In [32]: data<5
Out[32]:
one? ? two? three? four
Ohio? ? ? True? True? True? True
Colorado? True? False? False? False
Utah? ? ? False? False? False? False
New York? False? False? False? False
In [33]: data[data<5]=0
In [34]: data
Out[34]:
one? two? three? four
Ohio? ? ? ? 0? ? 0? ? ? 0? ? 0
Colorado? ? 0? ? 5? ? ? 6? ? 7
Utah? ? ? ? 8? ? 9? ? 10? ? 11
New York? 12? 13? ? 14? ? 15
這段代碼使得DataFrame在語法上像ndarray
為了在DataFrame的行上進(jìn)行標(biāo)簽索引,我們引入專門的索引字段ix。使得你通過numpy式的標(biāo)記法以及軸標(biāo)簽的從DataFrame中選取行和列的子集。這是重現(xiàn)索引的簡單手段:
In [35]: data.ix['Colorado',['two','three']]
Out[35]:
two? ? ? 5
three? ? 6
Name: Colorado, dtype: int32
In [36]: data.ix[['Colorado','Utah'],[3,0,1]]
Out[36]:
four? one? two
Colorado? ? 7? ? 0? ? 5
Utah? ? ? ? 11? ? 8? ? 9
In [37]: data.ix[2]
Out[37]:
one? ? ? 8
two? ? ? 9
three? ? 10
four? ? 11
Name: Utah, dtype: int32
In [38]: data.ix[:'Utah','two']
Out[38]:
Ohio? ? ? ? 0
Colorado? ? 5
Utah? ? ? ? 9
Name: two, dtype: int32
In [39]: data.ix[data.three>5,:3]
Out[39]:
one? two? three
Colorado? ? 0? ? 5? ? ? 6
Utah? ? ? ? 8? ? 9? ? 10
New York? 12? 13? ? 14
5.2.4算術(shù)運(yùn)算和數(shù)據(jù)對齊
In [5]: s1=Series([7.3,-2.5,3.4,1.5],index=['a','c','d','e'])
In [6]: s2=Series([-2.1,3.6,-1.5,4,3.1],index=['a','c','e','f','g'])
In [7]: s1
Out[7]:
a 7.3
c -2.5
d 3.4
e 1.5
dtype: float64
In [8]: s2
Out[8]:
a -2.1
c 3.6
e -1.5
f 4.0
g 3.1
dtype: float64
把他們相加:
In [9]: s1+s2
Out[9]:
a 5.2
c 1.1
d NaN
e 0.0
f NaN
g NaN
dtype: float64
自動(dòng)的數(shù)據(jù)對其操作在不重疊的索引處引入了NA值。缺失值會在算術(shù)運(yùn)算過程中傳播。
對于DataFrame,對齊操作會同時(shí)發(fā)生在行和列上:
In [6]: df1=DataFrame(np.arange(9.).reshape((3,3)),columns=list('bcd'),index=['Ohio','Texas','Colorado'])
In [7]: df2=DataFrame(np.arange(12.).reshape((4,3)),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon'])
In [8]: df1
Out[8]:
b c d
Ohio 0.0 1.0 2.0
Texas 3.0 4.0 5.0
Colorado 6.0 7.0 8.0
In [9]: df2
Out[9]:
b d e
Utah 0.0 1.0 2.0
Ohio 3.0 4.0 5.0
Texas 6.0 7.0 8.0
Oregon 9.0 10.0 11.0
將他們相加后,會返回一個(gè)新的DataFrame,其索引和列為原來的那兩個(gè)DataFrame的并集:
In [10]: df1+df2
Out[10]:
b c d e
Colorado NaN NaN NaN NaN
Ohio 3.0 NaN 6.0 NaN
Oregon NaN NaN NaN NaN
Texas 9.0 NaN 12.0 NaN
Utah NaN NaN NaN NaN
5.2.4.1在算術(shù)方法中填充值
在不同索引的對象進(jìn)行算術(shù)運(yùn)算時(shí),你可能希望當(dāng)一個(gè)對象中某個(gè)軸標(biāo)簽在另一個(gè)對象張找不到時(shí)填充一個(gè)特殊值:
In [20]: df1=DataFrame(np.arange(12.).reshape((3,4)),columns=list('abcd'))
In [21]: df2=DataFrame(np.arange(20.).reshape((4,5)),columns=list('abcde'))
In [22]: df1
Out[22]:
a b c d
0 0.0 1.0 2.0 3.0
1 4.0 5.0 6.0 7.0
2 8.0 9.0 10.0 11.0
In [23]: df2
Out[23]:
a b c d e
0 0.0 1.0 2.0 3.0 4.0
1 5.0 6.0 7.0 8.0 9.0
2 10.0 11.0 12.0 13.0 14.0
3 15.0 16.0 17.0 18.0 19.0
將他們相加時(shí),沒有重疊的位置就會產(chǎn)生NA值:
In [24]: df1+df2
Out[24]:
a b c d e
0 0.0 2.0 4.0 6.0 NaN
1 9.0 11.0 13.0 15.0 NaN
2 18.0 20.0 22.0 24.0 NaN
3 NaN NaN NaN NaN NaN
使用df1的add方法,傳入df2以及一個(gè)fill_value參數(shù):
In [26]: df1.add(df2,fill_value=0)
Out[26]:
a b c d e
0 0.0 2.0 4.0 6.0 4.0
1 9.0 11.0 13.0 15.0 9.0
2 18.0 20.0 22.0 24.0 14.0
3 15.0 16.0 17.0 18.0 19.0
對Series或DataFrame重新索引時(shí),也可以指定一個(gè)填充值:
In [28]: df1.reindex(columns=df2.columns,fill_value=0)
Out[28]:
a b c d e
0 0.0 1.0 2.0 3.0 0
1 4.0 5.0 6.0 7.0 0
2 8.0 9.0 10.0 11.0 0
表5-7 靈活的算術(shù)方法
方法 說明
add 用于加法(+)的方法
sub 用于減法(-)的方法
div 用于乘法(*)的方法
mul 用于除法(/)的方法
5.2.4.2 DataFrame和Series之間的運(yùn)算
跟NumPy數(shù)組一樣,DataFrame和Series的=之間的算術(shù)運(yùn)算也是有明確規(guī)定的。
下面來計(jì)算一個(gè)二維數(shù)組與其某行之間的差:
In [29]: arr=np.arange(12.).reshape((3,4))
In [30]: arr
Out[30]:
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
In [31]: arr[0]
Out[31]: array([ 0., 1., 2., 3.])
In [32]: arr-arr[0]
Out[32]:
array([[ 0., 0., 0., 0.],
[ 4., 4., 4., 4.],
[ 8., 8., 8., 8.]])
上面的運(yùn)算就叫做,廣播。
DataFrame和Series之間的運(yùn)算差不多也是如此:
In [33]: frame=DataFrame(np.arange(12.).reshape((4,3)),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon'])
In [34]: series=frame.ix[0]
In [35]: frame
Out[35]:
b d e
Utah 0.0 1.0 2.0
Ohio 3.0 4.0 5.0
Texas 6.0 7.0 8.0
Oregon 9.0 10.0 11.0
In [36]: series
Out[36]:
b 0.0
d 1.0
e 2.0
Name: Utah, dtype: float64
默認(rèn)情況下,DataFrame和Series之間的算術(shù)運(yùn)算符將Series的索引匹配到DataFrame的列,然后沿著行一直向下廣播:
In [37]: frame - series
Out[37]:
b d e
Utah 0.0 0.0 0.0
Ohio 3.0 3.0 3.0
Texas 6.0 6.0 6.0
Oregon 9.0 9.0 9.0
如果某個(gè)索引值在DataFrame的列或Series的索引中找不到,則參與運(yùn)算的兩個(gè)對象就會被重新索引以形成并集:
In [38]: series2=Series(range(3),index=['b','e','f'])
In [39]: frame+series2
Out[39]:
b d e f
Utah 0.0 NaN 3.0 NaN
Ohio 3.0 NaN 6.0 NaN
Texas 6.0 NaN 9.0 NaN
Oregon 9.0 NaN 12.0 NaN
如果你希望匹配行且在列上廣播,則必須使用算術(shù)運(yùn)算方法:
In [40]: series3=frame['d']
In [41]: frame
Out[41]:
b d e
Utah 0.0 1.0 2.0
Ohio 3.0 4.0 5.0
Texas 6.0 7.0 8.0
Oregon 9.0 10.0 11.0
In [42]: series3
Out[42]:
Utah 1.0
Ohio 4.0
Texas 7.0
Oregon 10.0
Name: d, dtype: float64
In [43]: frame.sub(series3,axis=0)
Out[43]:
b d e
Utah -1.0 0.0 1.0
Ohio -1.0 0.0 1.0
Texas -1.0 0.0 1.0
Oregon -1.0 0.0 1.0
傳入的軸號就是希望匹配的軸。
5.2.5函數(shù)應(yīng)用和映射
Numpy的ufuncs(元素級數(shù)組方法)也可以用于操作pandas對象:
In [44]: frame=DataFrame(np.random.randn(4,3),columns=list('bde'),index=['Utah','Ohio','Texas','Oregon'])
In [45]: frame
Out[45]:
b d e
Utah -0.172344 1.823441 -0.067380
Ohio -0.338604 -0.189082 -0.145676
Texas 1.310289 -0.518146 -0.231740
Oregon -1.880954 -0.400772 0.228320
In [46]: np.abs(frame)
Out[46]:
b d e
Utah 0.172344 1.823441 0.067380
Ohio 0.338604 0.189082 0.145676
Texas 1.310289 0.518146 0.231740
Oregon 1.880954 0.400772 0.228320
另一個(gè)常見的操作,將函數(shù)應(yīng)用到由各列或行所形成的一維數(shù)組上。DataFrame的apply方法即可實(shí)現(xiàn)此功能:
In [47]: f=lambda x:x.max() - x.min()
In [48]: frame.apply(f)
Out[48]:
b 3.191243
d 2.341587
e 0.460059
dtype: float64
In [49]: frame.apply(f,axis=1)
Out[49]:
Utah 1.995785
Ohio 0.192928
Texas 1.828435
Oregon 2.109274
dtype: float64
除標(biāo)量外,傳遞給apply的函數(shù)還可以返回由多個(gè)值組成的Series:
In [52]: def f(x):
...: return Series([x.min(),x.max()],index=['min','max'])
...:
In [53]: frame.apply(f)
Out[53]:
b d e
min -1.880954 -0.518146 -0.23174
max 1.310289 1.823441 0.22832
此外,元素級的python函數(shù)也是可以用的。
假如想得到frame中各個(gè)浮點(diǎn)數(shù)的格式化字符串,使用applymap即可:
In [54]: format=lambda x:'%.2f' %x
In [55]: frame.applymap(format)
Out[55]:
b d e
Utah -0.17 1.82 -0.07
Ohio -0.34 -0.19 -0.15
Texas 1.31 -0.52 -0.23
Oregon -1.88 -0.40 0.23
之所以叫做applymap,是因?yàn)镾eries有一個(gè)用于應(yīng)用元素級函數(shù)的map的方法:
In [56]: frame['e'].map(format)
Out[56]:
Utah -0.07
Ohio -0.15
Texas -0.23
Oregon 0.23
Name: e, dtype: object
5.2.6排序和排名
根據(jù)條件對數(shù)據(jù)集排序也是一種重要的內(nèi)置運(yùn)算。要對行或列索引進(jìn)行排序(按字典順序),可以使用sort_index方法,它將返回一個(gè)已經(jīng)排序的新對象:
In [57]: obj=Series(range(4),index=['d','a','b','c'])
In [58]: obj.sort_index()
Out[58]:
a 1
b 2
c 3
d 0
dtype: int64
而對于DataFrame,則可以根據(jù)任意一個(gè)軸上的索引進(jìn)行排序:
In [59]: frame=DataFrame(np.arange(8).reshape((2,4)),index=['three','one'],columns=['d','a','b','c'])
In [60]: frame.sort_index()
Out[60]:
d a b c
one 4 5 6 7
three 0 1 2 3
In [61]: frame.sort_index(axis=1)
Out[61]:
a b c d
three 1 2 3 0
one 5 6 7 4
數(shù)據(jù)默認(rèn)是按升序排列的,但也可以降序排序:
In [64]: frame.sort_index(axis=1,ascending=False)
Out[64]:
d c b a
three 0 3 2 1
one 4 7 6 5
若要按值對Series進(jìn)行排序,可以使用order方法:
In [65]: obj=Series([4,7,-3,2])
In [66]: obj.order()
Out[66]:
2 -3
3 2
0 4
1 7
dtype: int64
在排序的時(shí)候,缺失值默認(rèn)都會被放在了Series的末尾:
In [67]: obj=Series([4,np.nan,7,np.nan,-3,2])
In [68]: obj.order()
Out[68]:
4 -3.0
5 2.0
0 4.0
2 7.0
1 NaN
3 NaN
dtype: float64
在DataFrame上,你可能希望根據(jù)一個(gè)或多個(gè)列中的值進(jìn)行排序。將一個(gè)或多個(gè)列的名字傳遞給by選項(xiàng)即可達(dá)到該目的:
In [69]: frame=DataFrame({'b':[4,7,-3,2],'a':[0,1,0,1]})
In [70]: frame
Out[70]:
a b
0 0 4
1 1 7
2 0 -3
3 1 2
In [71]: frame.sort_index(by='b')
Out[71]:
a b
2 0 -3
3 1 2
0 0 4
1 1 7
要根據(jù)多個(gè)列進(jìn)行排序,傳入名稱的列表即可:
In [73]: frame.sort_index(by=['a','b'])
Out[73]:
a b
2 0 -3
0 0 4
3 1 2
1 1 7
排名(ranking)跟排序關(guān)系密切,且會增設(shè)一個(gè)排名值(從1開始,一直到數(shù)組中有效數(shù)據(jù)的數(shù)量),跟numpy.argsort產(chǎn)生的間接排序索引差不多,只不過它可以根據(jù)某種規(guī)則破壞平級關(guān)系。
下面介紹Series和DataFrame的rank方法。默認(rèn)下:rank是通過“為各組分配一個(gè)平均排名”的方式來破壞平級關(guān)系。
In [75]: obj=Series([7,-5,7,4,2,0,4])
In [76]: obj.rank()
Out[76]:
0 6.5
1 1.0
2 6.5
3 4.5
4 3.0
5 2.0
6 4.5
dtype: float64
也可以根據(jù)值在原數(shù)據(jù)中出現(xiàn)的順序給出排名:
In [77]: obj.rank(method='first')
Out[77]:
0 6.0
1 1.0
2 7.0
3 4.0
4 3.0
5 2.0
6 5.0
dtype: float64
也可以按降序進(jìn)行排名:
In [78]: obj.rank(ascending=False,method='max')
Out[78]:
0 2.0
1 7.0
2 2.0
3 4.0
4 5.0
5 6.0
6 4.0
dtype: float64
表5-8 列出了所有用于破壞平級關(guān)系的method選項(xiàng)。DataFrame可以在行或列上計(jì)算排名:
In [79]: frame=DataFrame({'b':[4.3,7,-3,2],'a':[0,1,0,1],'c':[-2,5,8,-2.5]})
In [80]: frame
Out[80]:
a b c
0 0 4.3 -2.0
1 1 7.0 5.0
2 0 -3.0 8.0
3 1 2.0 -2.5
In [81]: frame.rank(axis=1)
Out[81]:
a b c
0 2.0 3.0 1.0
1 1.0 3.0 2.0
2 2.0 1.0 3.0
3 2.0 3.0 1.0
表5-8 :排名時(shí)用于破壞平級關(guān)系的method選項(xiàng)
method 說明
‘a(chǎn)verage’ 默認(rèn):在相等分組中,為各個(gè)值分配平均排‘’
‘min’ 使用整個(gè)分組的最小排名
‘max’ 使用整個(gè)分組的最大排名
‘first’ 按值在原始數(shù)據(jù)中的出現(xiàn)順序分配排名
5.2.7帶有重復(fù)的軸索引
我們看看下面這個(gè)簡單的帶有重復(fù)索引值的Series:
In [82]: obj=Series(range(5),index=['a','a','b','b','c'])
In [83]: obj
Out[83]:
a 0
a 1
b 2
b 3
c 4
dtype: int64
索引的is_unique屬性可以告訴你他的值是否是唯一的:
In [84]: obj.index.is_unique
Out[84]: False
對于重復(fù)的索引,數(shù)據(jù)選取的行為將會有些不同。如果某個(gè)索引對應(yīng)的多個(gè)值,則返回一個(gè)Series,而對應(yīng)單個(gè)值,則返回一個(gè)標(biāo)量:
In [85]: obj['a']
Out[85]:
a 0
a 1
dtype: int64
In [86]: obj['c']
Out[86]: 4
對DataFrame的行進(jìn)行索引時(shí)候也是如此:
In [87]: df=DataFrame(np.random.randn(4,3),index=['a','a','b','b'])
In [88]: df
Out[88]:
0 1 2
a 0.056598 1.592208 -0.576368
a 0.842511 -0.085418 0.818032
b 1.347421 -0.239196 -0.543597
b -0.598395 0.966395 0.285722
In [89]: df.ix['b']
Out[89]:
0 1 2
b 1.347421 -0.239196 -0.543597
b -0.598395 0.966395 0.285722