《利用Python進(jìn)行數(shù)據(jù)分析·第2版》第5章 pandas入門(mén)


第1章 準(zhǔn)備工作
第2章 Python語(yǔ)法基礎(chǔ)热鞍,IPython和Jupyter
第3章 Python的數(shù)據(jù)結(jié)構(gòu)、函數(shù)和文件
第4章 NumPy基礎(chǔ):數(shù)組和矢量計(jì)算
第5章 pandas入門(mén)
第6章 數(shù)據(jù)加載着倾、存儲(chǔ)與文件格式
第7章 數(shù)據(jù)清洗和準(zhǔn)備
第8章 數(shù)據(jù)規(guī)整:聚合、合并和重塑
第9章 繪圖和可視化
第10章 數(shù)據(jù)聚合與分組運(yùn)算
第11章 時(shí)間序列
第12章 pandas高級(jí)應(yīng)用
第13章 Python建模庫(kù)介紹
第14章 數(shù)據(jù)分析案例
附錄A NumPy高級(jí)應(yīng)用
附錄B 更多關(guān)于IPython的內(nèi)容(完)


pandas是本書(shū)后續(xù)內(nèi)容的首選庫(kù)累魔。它含有使數(shù)據(jù)清洗和分析工作變得更快更簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)和操作工具蕴纳。pandas經(jīng)常和其它工具一同使用,如數(shù)值計(jì)算工具NumPy和SciPy妥曲,分析庫(kù)statsmodels和scikit-learn贾费,和數(shù)據(jù)可視化庫(kù)matplotlib。pandas是基于NumPy數(shù)組構(gòu)建的檐盟,特別是基于數(shù)組的函數(shù)和不使用for循環(huán)的數(shù)據(jù)處理。

雖然pandas采用了大量的NumPy編碼風(fēng)格导犹,但二者最大的不同是pandas是專(zhuān)門(mén)為處理表格和混雜數(shù)據(jù)設(shè)計(jì)的羡忘。而NumPy更適合處理統(tǒng)一的數(shù)值數(shù)組數(shù)據(jù)卷雕。

自從2010年pandas開(kāi)源以來(lái)节猿,pandas逐漸成長(zhǎng)為一個(gè)非常大的庫(kù)漫雕,應(yīng)用于許多真實(shí)案例蝎亚。開(kāi)發(fā)者社區(qū)已經(jīng)有了800個(gè)獨(dú)立的貢獻(xiàn)者躺彬,他們?cè)诮鉀Q日常數(shù)據(jù)問(wèn)題的同時(shí)為這個(gè)項(xiàng)目提供貢獻(xiàn)宪拥。

在本書(shū)后續(xù)部分中,我將使用下面這樣的pandas引入約定:

In [1]: import pandas as pd

因此缔刹,只要你在代碼中看到pd.亿扁,就得想到這是pandas从祝。因?yàn)镾eries和DataFrame用的次數(shù)非常多,所以將其引入本地命名空間中會(huì)更方便:

In [2]: from pandas import Series, DataFrame

5.1 pandas的數(shù)據(jù)結(jié)構(gòu)介紹

要使用pandas毒涧,你首先就得熟悉它的兩個(gè)主要數(shù)據(jù)結(jié)構(gòu):Series和DataFrame萌狂。雖然它們并不能解決所有問(wèn)題茫藏,但它們?yōu)榇蠖鄶?shù)應(yīng)用提供了一種可靠的凉当、易于使用的基礎(chǔ)。

Series

Series是一種類(lèi)似于一維數(shù)組的對(duì)象楼雹,它由一組數(shù)據(jù)(各種NumPy數(shù)據(jù)類(lèi)型)以及一組與之相關(guān)的數(shù)據(jù)標(biāo)簽(即索引)組成。僅由一組數(shù)據(jù)即可產(chǎn)生最簡(jiǎn)單的Series:

In [11]: obj = pd.Series([4, 7, -5, 3])

In [12]: obj
Out[12]: 
0    4
1    7
2   -5
3    3
dtype: int64

Series的字符串表現(xiàn)形式為:索引在左邊,值在右邊桂肌。由于我們沒(méi)有為數(shù)據(jù)指定索引昌跌,于是會(huì)自動(dòng)創(chuàng)建一個(gè)0到N-1(N為數(shù)據(jù)的長(zhǎng)度)的整數(shù)型索引。你可以通過(guò)Series 的values和index屬性獲取其數(shù)組表示形式和索引對(duì)象:

In [13]: obj.values
Out[13]: array([ 4,  7, -5,  3])

In [14]: obj.index  # like range(4)
Out[14]: RangeIndex(start=0, stop=4, step=1)

通常萍诱,我們希望所創(chuàng)建的Series帶有一個(gè)可以對(duì)各個(gè)數(shù)據(jù)點(diǎn)進(jìn)行標(biāo)記的索引:

In [15]: obj2 = pd.Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c'])

In [16]: obj2
Out[16]: 
d    4
b    7
a   -5
c    3
dtype: int64

In [17]: obj2.index
Out[17]: Index(['d', 'b', 'a', 'c'], dtype='object')

與普通NumPy數(shù)組相比,你可以通過(guò)索引的方式選取Series中的單個(gè)或一組值:

In [18]: obj2['a']
Out[18]: -5

In [19]: obj2['d'] = 6

In [20]: obj2[['c', 'a', 'd']]
Out[20]: 
c    3
a   -5
d    6
dtype: int64

['c', 'a', 'd']是索引列表,即使它包含的是字符串而不是整數(shù)整慎。

使用NumPy函數(shù)或類(lèi)似NumPy的運(yùn)算(如根據(jù)布爾型數(shù)組進(jìn)行過(guò)濾、標(biāo)量乘法、應(yīng)用數(shù)學(xué)函數(shù)等)都會(huì)保留索引值的鏈接:

In [21]: obj2[obj2 > 0]
Out[21]: 
d    6
b    7
c    3
dtype: int64

In [22]: obj2 * 2
Out[22]:
d    12
b    14
a   -10
c     6
dtype: int64

In [23]: np.exp(obj2)
Out[23]: 
d     403.428793
b    1096.633158
a       0.006738
c      20.085537
dtype: float64

還可以將Series看成是一個(gè)定長(zhǎng)的有序字典琉朽,因?yàn)樗撬饕档綌?shù)據(jù)值的一個(gè)映射。它可以用在許多原本需要字典參數(shù)的函數(shù)中:

In [24]: 'b' in obj2
Out[24]: True

In [25]: 'e' in obj2
Out[25]: False

如果數(shù)據(jù)被存放在一個(gè)Python字典中蝌蹂,也可以直接通過(guò)這個(gè)字典來(lái)創(chuàng)建Series:

In [26]: sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}

In [27]: obj3 = pd.Series(sdata)

In [28]: obj3
Out[28]: 
Ohio      35000
Oregon    16000
Texas     71000
Utah       5000
dtype: int64

如果只傳入一個(gè)字典,則結(jié)果Series中的索引就是原字典的鍵(有序排列)斥废。你可以傳入排好序的字典的鍵以改變順序:

In [29]: states = ['California', 'Ohio', 'Oregon', 'Texas']

In [30]: obj4 = pd.Series(sdata, index=states)

In [31]: obj4
Out[31]: 
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64

在這個(gè)例子中,sdata中跟states索引相匹配的那3個(gè)值會(huì)被找出來(lái)并放到相應(yīng)的位置上统锤,但由于"California"所對(duì)應(yīng)的sdata值找不到,所以其結(jié)果就為NaN(即“非數(shù)字”(not a number)逾雄,在pandas中,它用于表示缺失或NA值)。因?yàn)椤甎tah’不在states中誊垢,它被從結(jié)果中除去殃饿。

我將使用缺失(missing)或NA表示缺失數(shù)據(jù)遵蚜。pandas的isnull和notnull函數(shù)可用于檢測(cè)缺失數(shù)據(jù):

In [32]: pd.isnull(obj4)
Out[32]: 
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool

In [33]: pd.notnull(obj4)
Out[33]: 
California    False
Ohio           True
Oregon         True
Texas          True
dtype: bool

Series也有類(lèi)似的實(shí)例方法:

In [34]: obj4.isnull()
Out[34]: 
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool

我將在第7章詳細(xì)講解如何處理缺失數(shù)據(jù)。

對(duì)于許多應(yīng)用而言,Series最重要的一個(gè)功能是友扰,它會(huì)根據(jù)運(yùn)算的索引標(biāo)簽自動(dòng)對(duì)齊數(shù)據(jù):

In [35]: obj3
Out[35]: 
Ohio      35000
Oregon    16000
Texas     71000
Utah       5000
dtype: int64

In [36]: obj4
Out[36]: 
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64

In [37]: obj3 + obj4
Out[37]: 
California         NaN
Ohio           70000.0
Oregon         32000.0
Texas         142000.0
Utah               NaN
dtype: float64

數(shù)據(jù)對(duì)齊功能將在后面詳細(xì)講解。如果你使用過(guò)數(shù)據(jù)庫(kù)柬焕,你可以認(rèn)為是類(lèi)似join的操作。

Series對(duì)象本身及其索引都有一個(gè)name屬性,該屬性跟pandas其他的關(guān)鍵功能關(guān)系非常密切:

In [38]: obj4.name = 'population'

In [39]: obj4.index.name = 'state'

In [40]: obj4
Out[40]: 
state
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
Name: population, dtype: float64

Series的索引可以通過(guò)賦值的方式就地修改:

In [41]: obj
Out[41]: 
0    4
1    7
2   -5
3    3
dtype: int64

In [42]: obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']

In [43]: obj
Out[43]: 
Bob      4
Steve    7
Jeff    -5
Ryan     3
dtype: int64

DataFrame

DataFrame是一個(gè)表格型的數(shù)據(jù)結(jié)構(gòu)凌彬,它含有一組有序的列会钝,每列可以是不同的值類(lèi)型(數(shù)值先鱼、字符串焙畔、布爾值等)。DataFrame既有行索引也有列索引,它可以被看做由Series組成的字典(共用同一個(gè)索引)。DataFrame中的數(shù)據(jù)是以一個(gè)或多個(gè)二維塊存放的(而不是列表函喉、字典或別的一維數(shù)據(jù)結(jié)構(gòu))梳毙。有關(guān)DataFrame內(nèi)部的技術(shù)細(xì)節(jié)遠(yuǎn)遠(yuǎn)超出了本書(shū)所討論的范圍。

筆記:雖然DataFrame是以二維結(jié)構(gòu)保存數(shù)據(jù)的,但你仍然可以輕松地將其表示為更高維度的數(shù)據(jù)(層次化索引的表格型結(jié)構(gòu)廓奕,這是pandas中許多高級(jí)數(shù)據(jù)處理功能的關(guān)鍵要素,我們會(huì)在第8章討論這個(gè)問(wèn)題)。

建DataFrame的辦法有很多押逼,最常用的一種是直接傳入一個(gè)由等長(zhǎng)列表或NumPy數(shù)組組成的字典:

data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
        'year': [2000, 2001, 2002, 2001, 2002, 2003],
        'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
frame = pd.DataFrame(data)

結(jié)果DataFrame會(huì)自動(dòng)加上索引(跟Series一樣)表锻,且全部列會(huì)被有序排列:

In [45]: frame
Out[45]: 
   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
5  3.2  Nevada  2003

如果你使用的是Jupyter notebook,pandas DataFrame對(duì)象會(huì)以對(duì)瀏覽器友好的HTML表格的方式呈現(xiàn)。

對(duì)于特別大的DataFrame蕾域,head方法會(huì)選取前五行:

In [46]: frame.head()
Out[46]: 
   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的列就會(huì)按照指定順序進(jìn)行排列:

In [47]: pd.DataFrame(data, columns=['year', 'state', 'pop'])
Out[47]: 
   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
5  2003  Nevada  3.2

如果傳入的列在數(shù)據(jù)中找不到斧吐,就會(huì)在結(jié)果中產(chǎn)生缺失值:

In [48]: frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],
   ....:                       index=['one', 'two', 'three', 'four',
   ....:                              'five', 'six'])

In [49]: frame2
Out[49]: 
       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
six    2003  Nevada  3.2  NaN

In [50]: frame2.columns
Out[50]: Index(['year', 'state', 'pop', 'debt'], dtype='object')

通過(guò)類(lèi)似字典標(biāo)記的方式或?qū)傩缘姆绞剑梢詫ataFrame的列獲取為一個(gè)Series:

In [51]: frame2['state']
Out[51]: 
one        Ohio
two        Ohio
three      Ohio
four     Nevada
five     Nevada
six      Nevada
Name: state, dtype: object

In [52]: frame2.year
Out[52]: 
one      2000
two      2001
three    2002
four     2001
five     2002
six      2003
Name: year, dtype: int64

筆記:IPython提供了類(lèi)似屬性的訪問(wèn)(即frame2.year)和tab補(bǔ)全洋只。
frame2[column]適用于任何列的名端三,但是frame2.column只有在列名是一個(gè)合理的Python變量名時(shí)才適用妻献。

注意,返回的Series擁有原DataFrame相同的索引,且其name屬性也已經(jīng)被相應(yīng)地設(shè)置好了析蝴。

行也可以通過(guò)位置或名稱的方式進(jìn)行獲取,比如用loc屬性(稍后將對(duì)此進(jìn)行詳細(xì)講解):

In [53]: frame2.loc['three']
Out[53]: 
year     2002
state    Ohio
pop       3.6
debt      NaN
Name: three, dtype: object

列可以通過(guò)賦值的方式進(jìn)行修改盾沫。例如,我們可以給那個(gè)空的"debt"列賦上一個(gè)標(biāo)量值或一組值:

In [54]: frame2['debt'] = 16.5

In [55]: frame2
Out[55]: 
       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
six    2003  Nevada  3.2  16.5

In [56]: frame2['debt'] = np.arange(6.)

In [57]: frame2
Out[57]: 
       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
six    2003  Nevada  3.2   5.0

將列表或數(shù)組賦值給某個(gè)列時(shí)啊奄,其長(zhǎng)度必須跟DataFrame的長(zhǎng)度相匹配琼富。如果賦值的是一個(gè)Series,就會(huì)精確匹配DataFrame的索引,所有的空位都將被填上缺失值:

In [58]: val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])

In [59]: frame2['debt'] = val

In [60]: frame2
Out[60]: 
       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
six    2003  Nevada  3.2   NaN

為不存在的列賦值會(huì)創(chuàng)建出一個(gè)新列。關(guān)鍵字del用于刪除列唯咬。

作為del的例子刻获,我先添加一個(gè)新的布爾值的列厚柳,state是否為'Ohio':

In [61]: frame2['eastern'] = frame2.state == 'Ohio'

In [62]: frame2
Out[62]: 
       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
six    2003  Nevada  3.2   NaN    False

注意:不能用frame2.eastern創(chuàng)建新的列痒筒。

del方法可以用來(lái)刪除這列:

In [63]: del frame2['eastern']

In [64]: frame2.columns
Out[64]: Index(['year', 'state', 'pop', 'debt'], dtype='object')

注意:通過(guò)索引方式返回的列只是相應(yīng)數(shù)據(jù)的視圖而已移袍,并不是副本啡浊。因此喘先,對(duì)返回的Series所做的任何就地修改全都會(huì)反映到源DataFrame上。通過(guò)Series的copy方法即可指定復(fù)制列。

另一種常見(jiàn)的數(shù)據(jù)形式是嵌套字典:

In [65]: pop = {'Nevada': {2001: 2.4, 2002: 2.9},
....:        'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}

如果嵌套字典傳給DataFrame,pandas就會(huì)被解釋為:外層字典的鍵作為列,內(nèi)層鍵則作為行索引:

In [66]: frame3 = pd.DataFrame(pop)

In [67]: frame3
Out[67]: 
      Nevada  Ohio
2000     NaN   1.5
2001     2.4   1.7
2002     2.9   3.6

你也可以使用類(lèi)似NumPy數(shù)組的方法,對(duì)DataFrame進(jìn)行轉(zhuǎn)置(交換行和列):

In [68]: frame3.T
Out[68]: 
        2000  2001  2002
Nevada   NaN   2.4   2.9
Ohio     1.5   1.7   3.6

內(nèi)層字典的鍵會(huì)被合并、排序以形成最終的索引文兑。如果明確指定了索引橘原,則不會(huì)這樣:

In [69]: pd.DataFrame(pop, index=[2001, 2002, 2003])
Out[69]: 
      Nevada  Ohio
2001     2.4   1.7
2002     2.9   3.6
2003     NaN   NaN

由Series組成的字典差不多也是一樣的用法:

In [70]: pdata = {'Ohio': frame3['Ohio'][:-1],
....:          'Nevada': frame3['Nevada'][:2]}

In [71]: pd.DataFrame(pdata)
Out[71]: 
      Nevada  Ohio
2000     NaN   1.5
2001     2.4   1.7

表5-1列出了DataFrame構(gòu)造函數(shù)所能接受的各種數(shù)據(jù)吩愧。

如果設(shè)置了DataFrame的index和columns的name屬性,則這些信息也會(huì)被顯示出來(lái):

In [72]: frame3.index.name = 'year'; frame3.columns.name = 'state'

In [73]: frame3
Out[73]: 
state  Nevada  Ohio
year
2000      NaN   1.5
2001      2.4   1.7
2002      2.9   3.6

跟Series一樣同云,values屬性也會(huì)以二維ndarray的形式返回DataFrame中的數(shù)據(jù):

In [74]: frame3.values
Out[74]: 
array([[ nan,  1.5],
       [ 2.4,  1.7],
       [ 2.9,  3.6]])

如果DataFrame各列的數(shù)據(jù)類(lèi)型不同糖权,則值數(shù)組的dtype就會(huì)選用能兼容所有列的數(shù)據(jù)類(lèi)型:

In [75]: frame2.values
Out[75]:
array([[2000, 'Ohio', 1.5, nan],
       [2001, 'Ohio', 1.7, -1.2],
       [2002, 'Ohio', 3.6, nan],
       [2001, 'Nevada', 2.4, -1.5],
       [2002, 'Nevada', 2.9, -1.7],
       [2003, 'Nevada', 3.2, nan]], dtype=object)

索引對(duì)象

pandas的索引對(duì)象負(fù)責(zé)管理軸標(biāo)簽和其他元數(shù)據(jù)(比如軸名稱等)。構(gòu)建Series或DataFrame時(shí)炸站,所用到的任何數(shù)組或其他序列的標(biāo)簽都會(huì)被轉(zhuǎn)換成一個(gè)Index:

In [76]: obj = pd.Series(range(3), index=['a', 'b', 'c'])

In [77]: index = obj.index

In [78]: index
Out[78]: Index(['a', 'b', 'c'], dtype='object')

In [79]: index[1:]
Out[79]: Index(['b', 'c'], dtype='object')

Index對(duì)象是不可變的,因此用戶不能對(duì)其進(jìn)行修改:

index[1] = 'd'  # TypeError

不可變可以使Index對(duì)象在多個(gè)數(shù)據(jù)結(jié)構(gòu)之間安全共享:

In [80]: labels = pd.Index(np.arange(3))

In [81]: labels
Out[81]: Int64Index([0, 1, 2], dtype='int64')

In [82]: obj2 = pd.Series([1.5, -2.5, 0], index=labels)

In [83]: obj2
Out[83]: 
0    1.5
1   -2.5
2    0.0
dtype: float64

In [84]: obj2.index is labels
Out[84]: True

注意:雖然用戶不需要經(jīng)常使用Index的功能武契,但是因?yàn)橐恍┎僮鲿?huì)生成包含被索引化的數(shù)據(jù)募判,理解它們的工作原理是很重要的。

除了類(lèi)似于數(shù)組咒唆,Index的功能也類(lèi)似一個(gè)固定大小的集合:

In [85]: frame3
Out[85]: 
state  Nevada  Ohio
year               
2000      NaN   1.5
2001      2.4   1.7
2002      2.9   3.6
In [86]: frame3.columns
Out[86]: Index(['Nevada', 'Ohio'], dtype='object', name='state')

In [87]: 'Ohio' in frame3.columns
Out[87]: True

In [88]: 2003 in frame3.index
Out[88]: False

與python的集合不同届垫,pandas的Index可以包含重復(fù)的標(biāo)簽:

In [89]: dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar'])

In [90]: dup_labels
Out[90]: Index(['foo', 'foo', 'bar', 'bar'], dtype='object')

選擇重復(fù)的標(biāo)簽,會(huì)顯示所有的結(jié)果全释。

每個(gè)索引都有一些方法和屬性装处,它們可用于設(shè)置邏輯并回答有關(guān)該索引所包含的數(shù)據(jù)的常見(jiàn)問(wèn)題。表5-2列出了這些函數(shù)浸船。

5.2 基本功能

本節(jié)中妄迁,我將介紹操作Series和DataFrame中的數(shù)據(jù)的基本手段。后續(xù)章節(jié)將更加深入地挖掘pandas在數(shù)據(jù)分析和處理方面的功能李命。本書(shū)不是pandas庫(kù)的詳盡文檔登淘,主要關(guān)注的是最重要的功能,那些不大常用的內(nèi)容(也就是那些更深?yuàn)W的內(nèi)容)就交給你自己去摸索吧封字。

重新索引

pandas對(duì)象的一個(gè)重要方法是reindex黔州,其作用是創(chuàng)建一個(gè)新對(duì)象,它的數(shù)據(jù)符合新的索引阔籽×髌蓿看下面的例子:

In [91]: obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])

In [92]: obj
Out[92]: 
d    4.5
b    7.2
a   -5.3
c    3.6
dtype: float64

用該Series的reindex將會(huì)根據(jù)新索引進(jìn)行重排。如果某個(gè)索引值當(dāng)前不存在笆制,就引入缺失值:

In [93]: obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])

In [94]: obj2
Out[94]: 
a   -5.3
b    7.2
c    3.6
d    4.5
e    NaN
dtype: float64

對(duì)于時(shí)間序列這樣的有序數(shù)據(jù)绅这,重新索引時(shí)可能需要做一些插值處理。method選項(xiàng)即可達(dá)到此目的在辆,例如证薇,使用ffill可以實(shí)現(xiàn)前向值填充:

In [95]: obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])

In [96]: obj3
Out[96]: 
0      blue
2    purple
4    yellow
dtype: object

In [97]: obj3.reindex(range(6), method='ffill')
Out[97]: 
0      blue
1      blue
2    purple
3    purple
4    yellow
5    yellow
dtype: object

借助DataFrame度苔,reindex可以修改(行)索引和列。只傳遞一個(gè)序列時(shí)棕叫,會(huì)重新索引結(jié)果的行:

In [98]: frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
   ....:                      index=['a', 'c', 'd'],
   ....:                      columns=['Ohio', 'Texas', 'California'])

In [99]: frame
Out[99]: 
   Ohio  Texas  California
a     0      1           2
c     3      4           5
d     6      7           8

In [100]: frame2 = frame.reindex(['a', 'b', 'c', 'd'])

In [101]: frame2
Out[101]: 
   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 [102]: states = ['Texas', 'Utah', 'California']

In [103]: frame.reindex(columns=states)
Out[103]: 
   Texas  Utah  California
a      1   NaN           2
c      4   NaN           5
d      7   NaN           8

表5-3列出了reindex函數(shù)的各參數(shù)及說(shuō)明林螃。

丟棄指定軸上的項(xiàng)

丟棄某條軸上的一個(gè)或多個(gè)項(xiàng)很簡(jiǎn)單奕删,只要有一個(gè)索引數(shù)組或列表即可俺泣。由于需要執(zhí)行一些數(shù)據(jù)整理和集合邏輯,所以drop方法返回的是一個(gè)在指定軸上刪除了指定值的新對(duì)象:

In [105]: obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])

In [106]: obj
Out[106]: 
a    0.0
b    1.0
c    2.0
d    3.0
e    4.0
dtype: float64

In [107]: new_obj = obj.drop('c')

In [108]: new_obj
Out[108]: 
a    0.0
b    1.0
d    3.0
e    4.0
dtype: float64

In [109]: obj.drop(['d', 'c'])
Out[109]: 
a    0.0
b    1.0
e    4.0
dtype: float64

對(duì)于DataFrame完残,可以刪除任意軸上的索引值伏钠。為了演示,先新建一個(gè)DataFrame例子:

In [110]: data = pd.DataFrame(np.arange(16).reshape((4, 4)),
   .....:                     index=['Ohio', 'Colorado', 'Utah', 'New York'],
   .....:                     columns=['one', 'two', 'three', 'four'])

In [111]: data
Out[111]: 
          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

用標(biāo)簽序列調(diào)用drop會(huì)從行標(biāo)簽(axis 0)刪除值:

In [112]: data.drop(['Colorado', 'Ohio'])
Out[112]: 
          one  two  three  four
Utah        8    9     10    11
New York   12   13     14    15

通過(guò)傳遞axis=1或axis='columns'可以刪除列的值:

In [113]: data.drop('two', axis=1)
Out[113]: 
          one  three  four
Ohio        0      2     3
Colorado    4      6     7
Utah        8     10    11
New York   12     14    15

In [114]: data.drop(['two', 'four'], axis='columns')
Out[114]: 
          one  three
Ohio        0      2
Colorado    4      6
Utah        8     10
New York   12     14

許多函數(shù)谨设,如drop熟掂,會(huì)修改Series或DataFrame的大小或形狀,可以就地修改對(duì)象扎拣,不會(huì)返回新的對(duì)象:

In [115]: obj.drop('c', inplace=True)

In [116]: obj
Out[116]: 
a    0.0
b    1.0
d    3.0
e    4.0
dtype: float64

小心使用inplace赴肚,它會(huì)銷(xiāo)毀所有被刪除的數(shù)據(jù)。

索引二蓝、選取和過(guò)濾

Series索引(obj[...])的工作方式類(lèi)似于NumPy數(shù)組的索引誉券,只不過(guò)Series的索引值不只是整數(shù)。下面是幾個(gè)例子:

In [117]: obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])

In [118]: obj
Out[118]: 
a    0.0
b    1.0
c    2.0
d    3.0
dtype: float64

In [119]: obj['b']
Out[119]: 1.0

In [120]: obj[1]
Out[120]: 1.0

In [121]: obj[2:4]
Out[121]: 
c    2.0
d    3.0
dtype: float64

In [122]: obj[['b', 'a', 'd']]
Out[122]:
b    1.0
a    0.0
d    3.0
dtype: float64

In [123]: obj[[1, 3]]
Out[123]: 
b    1.0
d    3.0
dtype: float64

In [124]: obj[obj < 2]
Out[124]: 
a    0.0
b    1.0
dtype: float64

利用標(biāo)簽的切片運(yùn)算與普通的Python切片運(yùn)算不同刊愚,其末端是包含的:

In [125]: obj['b':'c']
Out[125]:
b    1.0
c    2.0
dtype: float64

用切片可以對(duì)Series的相應(yīng)部分進(jìn)行設(shè)置:

In [126]: obj['b':'c'] = 5

In [127]: obj
Out[127]: 
a    0.0
b    5.0
c    5.0
d    3.0
dtype: float64

用一個(gè)值或序列對(duì)DataFrame進(jìn)行索引其實(shí)就是獲取一個(gè)或多個(gè)列:

In [128]: data = pd.DataFrame(np.arange(16).reshape((4, 4)),
   .....:                     index=['Ohio', 'Colorado', 'Utah', 'New York'],
   .....:                     columns=['one', 'two', 'three', 'four'])

In [129]: data
Out[129]: 
          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 [130]: data['two']
Out[130]: 
Ohio         1
Colorado     5
Utah         9
New York    13
Name: two, dtype: int64

In [131]: data[['three', 'one']]
Out[131]: 
          three  one
Ohio          2    0
Colorado      6    4
Utah         10    8
New York     14   12

這種索引方式有幾個(gè)特殊的情況踊跟。首先通過(guò)切片或布爾型數(shù)組選取數(shù)據(jù):

In [132]: data[:2]
Out[132]: 
          one  two  three  four
Ohio        0    1      2     3
Colorado    4    5      6     7

In [133]: data[data['three'] > 5]
Out[133]: 
          one  two  three  four
Colorado    4    5      6     7
Utah        8    9     10    11
New York   12   13     14    15

選取行的語(yǔ)法data[:2]十分方便。向[ ]傳遞單一的元素或列表鸥诽,就可選擇列商玫。

另一種用法是通過(guò)布爾型DataFrame(比如下面這個(gè)由標(biāo)量比較運(yùn)算得出的)進(jìn)行索引:

In [134]: data < 5
Out[134]: 
            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 [135]: data[data < 5] = 0

In [136]: data
Out[136]: 
          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的語(yǔ)法與NumPy二維數(shù)組的語(yǔ)法很像。

用loc和iloc進(jìn)行選取

對(duì)于DataFrame的行的標(biāo)簽索引牡借,我引入了特殊的標(biāo)簽運(yùn)算符loc和iloc拳昌。它們可以讓你用類(lèi)似NumPy的標(biāo)記,使用軸標(biāo)簽(loc)或整數(shù)索引(iloc)钠龙,從DataFrame選擇行和列的子集炬藤。

作為一個(gè)初步示例,讓我們通過(guò)標(biāo)簽選擇一行和多列:

In [137]: data.loc['Colorado', ['two', 'three']]
Out[137]: 
two      5
three    6
Name: Colorado, dtype: int64

然后用iloc和整數(shù)進(jìn)行選瓤∮恪:

In [138]: data.iloc[2, [3, 0, 1]]
Out[138]: 
four    11
one      8
two      9
Name: Utah, dtype: int64

In [139]: data.iloc[2]
Out[139]: 
one       8
two       9
three    10
four     11
Name: Utah, dtype: int64

In [140]: data.iloc[[1, 2], [3, 0, 1]]
Out[140]: 
          four  one  two
Colorado     7    0    5
Utah        11    8    9

這兩個(gè)索引函數(shù)也適用于一個(gè)標(biāo)簽或多個(gè)標(biāo)簽的切片:

In [141]: data.loc[:'Utah', 'two']
Out[141]: 
Ohio        0
Colorado    5
Utah        9
Name: two, dtype: int64

In [142]: data.iloc[:, :3][data.three > 5]
Out[142]: 
          one  two  three
Colorado    0    5      6
Utah        8    9     10
New York   12   13     14

所以刻像,在pandas中,有多個(gè)方法可以選取和重新組合數(shù)據(jù)并闲。對(duì)于DataFrame细睡,表5-4進(jìn)行了總結(jié)。后面會(huì)看到帝火,還有更多的方法進(jìn)行層級(jí)化索引溜徙。

筆記:在一開(kāi)始設(shè)計(jì)pandas時(shí)湃缎,我覺(jué)得用frame[:, col]選取列過(guò)于繁瑣(也容易出錯(cuò)),因?yàn)榱械倪x擇是非常常見(jiàn)的操作蠢壹。我做了些取舍嗓违,將花式索引的功能(標(biāo)簽和整數(shù))放到了ix運(yùn)算符中。在實(shí)踐中图贸,這會(huì)導(dǎo)致許多邊緣情況蹂季,數(shù)據(jù)的軸標(biāo)簽是整數(shù),所以pandas團(tuán)隊(duì)決定創(chuàng)造loc和iloc運(yùn)算符分別處理嚴(yán)格基于標(biāo)簽和整數(shù)的索引疏日。
ix運(yùn)算符仍然可用偿洁,但并不推薦。

表5-4 DataFrame的索引選項(xiàng)

整數(shù)索引

處理整數(shù)索引的pandas對(duì)象常常難住新手沟优,因?yàn)樗cPython內(nèi)置的列表和元組的索引語(yǔ)法不同涕滋。例如,你可能不認(rèn)為下面的代碼會(huì)出錯(cuò):

ser = pd.Series(np.arange(3.))
ser
ser[-1]

這里挠阁,pandas可以勉強(qiáng)進(jìn)行整數(shù)索引宾肺,但是會(huì)導(dǎo)致小bug。我們有包含0,1,2的索引侵俗,但是引入用戶想要的東西(基于標(biāo)簽或位置的索引)很難:

In [144]: ser
Out[144]: 
0    0.0
1    1.0
2    2.0
dtype: float64

另外锨用,對(duì)于非整數(shù)索引,不會(huì)產(chǎn)生歧義:

In [145]: ser2 = pd.Series(np.arange(3.), index=['a', 'b', 'c'])

In [146]: ser2[-1]
Out[146]: 2.0

為了進(jìn)行統(tǒng)一坡慌,如果軸索引含有整數(shù)黔酥,數(shù)據(jù)選取總會(huì)使用標(biāo)簽。為了更準(zhǔn)確洪橘,請(qǐng)使用loc(標(biāo)簽)或iloc(整數(shù)):

In [147]: ser[:1]
Out[147]: 
0    0.0
dtype: float64

In [148]: ser.loc[:1]
Out[148]: 
0    0.0
1    1.0
dtype: float64

In [149]: ser.iloc[:1]
Out[149]: 
0    0.0
dtype: float64

算術(shù)運(yùn)算和數(shù)據(jù)對(duì)齊

pandas最重要的一個(gè)功能是跪者,它可以對(duì)不同索引的對(duì)象進(jìn)行算術(shù)運(yùn)算。在將對(duì)象相加時(shí)熄求,如果存在不同的索引對(duì)渣玲,則結(jié)果的索引就是該索引對(duì)的并集。對(duì)于有數(shù)據(jù)庫(kù)經(jīng)驗(yàn)的用戶弟晚,這就像在索引標(biāo)簽上進(jìn)行自動(dòng)外連接忘衍。看一個(gè)簡(jiǎn)單的例子:

In [150]: s1 = pd.Series([7.3, -2.5, 3.4, 1.5], index=['a', 'c', 'd', 'e'])

In [151]: s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1],
   .....:                index=['a', 'c', 'e', 'f', 'g'])

In [152]: s1
Out[152]: 
a    7.3
c   -2.5
d    3.4
e    1.5
dtype: float64

In [153]: s2
Out[153]: 
a   -2.1
c    3.6
e   -1.5
f    4.0
g    3.1
dtype: float64

將它們相加就會(huì)產(chǎn)生:

In [154]: s1 + s2
Out[154]: 
a    5.2
c    1.1
d    NaN
e    0.0
f    NaN
g    NaN
dtype: float64

自動(dòng)的數(shù)據(jù)對(duì)齊操作在不重疊的索引處引入了NA值卿城。缺失值會(huì)在算術(shù)運(yùn)算過(guò)程中傳播枚钓。

對(duì)于DataFrame,對(duì)齊操作會(huì)同時(shí)發(fā)生在行和列上:

In [155]: df1 = pd.DataFrame(np.arange(9.).reshape((3, 3)), columns=list('bcd'),
   .....:                    index=['Ohio', 'Texas', 'Colorado'])

In [156]: df2 = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'),
   .....:                    index=['Utah', 'Ohio', 'Texas', 'Oregon'])

In [157]: df1
Out[157]: 
            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 [158]: df2
Out[158]: 
          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

把它們相加后將會(huì)返回一個(gè)新的DataFrame瑟押,其索引和列為原來(lái)那兩個(gè)DataFrame的并集:

In [159]: df1 + df2
Out[159]: 
            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

因?yàn)?c'和'e'列均不在兩個(gè)DataFrame對(duì)象中搀捷,在結(jié)果中以缺省值呈現(xiàn)。行也是同樣。

如果DataFrame對(duì)象相加嫩舟,沒(méi)有共用的列或行標(biāo)簽氢烘,結(jié)果都會(huì)是空:

In [160]: df1 = pd.DataFrame({'A': [1, 2]})

In [161]: df2 = pd.DataFrame({'B': [3, 4]})

In [162]: df1
Out[162]: 
   A
0  1
1  2

In [163]: df2
Out[163]: 
   B
0  3
1  4

In [164]: df1 - df2
Out[164]: 
    A   B
0 NaN NaN
1 NaN NaN

在算術(shù)方法中填充值

在對(duì)不同索引的對(duì)象進(jìn)行算術(shù)運(yùn)算時(shí),你可能希望當(dāng)一個(gè)對(duì)象中某個(gè)軸標(biāo)簽在另一個(gè)對(duì)象中找不到時(shí)填充一個(gè)特殊值(比如0):

In [165]: df1 = pd.DataFrame(np.arange(12.).reshape((3, 4)),
   .....:                    columns=list('abcd'))

In [166]: df2 = pd.DataFrame(np.arange(20.).reshape((4, 5)),
   .....:                    columns=list('abcde'))

In [167]: df2.loc[1, 'b'] = np.nan

In [168]: df1
Out[168]: 
     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 [169]: df2
Out[169]: 
      a     b     c     d     e
0   0.0   1.0   2.0   3.0   4.0
1   5.0   NaN   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í)家厌,沒(méi)有重疊的位置就會(huì)產(chǎn)生NA值:

In [170]: df1 + df2
Out[170]: 
      a     b     c     d   e
0   0.0   2.0   4.0   6.0 NaN
1   9.0   NaN  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 [171]: df1.add(df2, fill_value=0)
Out[171]: 
      a     b     c     d     e
0   0.0   2.0   4.0   6.0   4.0
1   9.0   5.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

表5-5列出了Series和DataFrame的算術(shù)方法。它們每個(gè)都有一個(gè)副本饭于,以字母r開(kāi)頭蜀踏,它會(huì)翻轉(zhuǎn)參數(shù)。因此這兩個(gè)語(yǔ)句是等價(jià)的:

In [172]: 1 / df1
Out[172]: 
          a         b         c         d
0       inf  1.000000  0.500000  0.333333
1  0.250000  0.200000  0.166667  0.142857
2  0.125000  0.111111  0.100000  0.090909

In [173]: df1.rdiv(1)
Out[173]: 
          a         b         c         d
0       inf  1.000000  0.500000  0.333333
1  0.250000  0.200000  0.166667  0.142857
2  0.125000  0.111111  0.100000  0.090909
表5-5 靈活的算術(shù)方法

與此類(lèi)似镰绎,在對(duì)Series或DataFrame重新索引時(shí)脓斩,也可以指定一個(gè)填充值:

In [174]: df1.reindex(columns=df2.columns, fill_value=0)
Out[174]: 
     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

DataFrame和Series之間的運(yùn)算

跟不同維度的NumPy數(shù)組一樣,DataFrame和Series之間算術(shù)運(yùn)算也是有明確規(guī)定的畴栖。先來(lái)看一個(gè)具有啟發(fā)性的例子,計(jì)算一個(gè)二維數(shù)組與其某行之間的差:

In [175]: arr = np.arange(12.).reshape((3, 4))

In [176]: arr
Out[176]: 
array([[  0.,   1.,   2.,   3.],
       [  4.,   5.,   6.,   7.],
       [  8.,   9.,  10.,  11.]])

In [177]: arr[0]
Out[177]: array([ 0.,  1.,  2.,  3.])

In [178]: arr - arr[0]
Out[178]: 
array([[ 0.,  0.,  0.,  0.],
       [ 4.,  4.,  4.,  4.],
       [ 8.,  8.,  8.,  8.]])

當(dāng)我們從arr減去arr[0]八千,每一行都會(huì)執(zhí)行這個(gè)操作吗讶。這就叫做廣播(broadcasting),附錄A將對(duì)此進(jìn)行詳細(xì)講解恋捆。DataFrame和Series之間的運(yùn)算差不多也是如此:

In [179]: frame = pd.DataFrame(np.arange(12.).reshape((4, 3)),
   .....:                      columns=list('bde'),
   .....:                      index=['Utah', 'Ohio', 'Texas', 'Oregon'])

In [180]: series = frame.iloc[0]

In [181]: frame
Out[181]: 
          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 [182]: series
Out[182]: 
b    0.0
d    1.0
e    2.0
Name: Utah, dtype: float64

默認(rèn)情況下照皆,DataFrame和Series之間的算術(shù)運(yùn)算會(huì)將Series的索引匹配到DataFrame的列,然后沿著行一直向下廣播:

In [183]: frame - series
Out[183]: 
          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è)對(duì)象就會(huì)被重新索引以形成并集:

In [184]: series2 = pd.Series(range(3), index=['b', 'e', 'f'])

In [185]: frame + series2
Out[185]: 
          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 [186]: series3 = frame['d']

In [187]: frame
Out[187]: 
          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 [188]: series3
Out[188]: 
Utah       1.0
Ohio       4.0
Texas      7.0
Oregon    10.0
Name: d, dtype: float64

In [189]: frame.sub(series3, axis='index')
Out[189]: 
          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

傳入的軸號(hào)就是希望匹配的軸愤钾。在本例中瘟滨,我們的目的是匹配DataFrame的行索引(axis='index' or axis=0)并進(jìn)行廣播。

函數(shù)應(yīng)用和映射

NumPy的ufuncs(元素級(jí)數(shù)組方法)也可用于操作pandas對(duì)象:

In [190]: frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'),
   .....:                      index=['Utah', 'Ohio', 'Texas', 'Oregon'])

In [191]: frame
Out[191]: 
               b         d         e
Utah   -0.204708  0.478943 -0.519439
Ohio   -0.555730  1.965781  1.393406
Texas   0.092908  0.281746  0.769023
Oregon  1.246435  1.007189 -1.296221

In [192]: np.abs(frame)
Out[192]: 
               b         d         e
Utah    0.204708  0.478943  0.519439
Ohio    0.555730  1.965781  1.393406
Texas   0.092908  0.281746  0.769023
Oregon  1.246435  1.007189  1.296221

另一個(gè)常見(jiàn)的操作是能颁,將函數(shù)應(yīng)用到由各列或行所形成的一維數(shù)組上杂瘸。DataFrame的apply方法即可實(shí)現(xiàn)此功能:

In [193]: f = lambda x: x.max() - x.min()

In [194]: frame.apply(f)
Out[194]: 
b    1.802165
d    1.684034
e    2.689627
dtype: float64

這里的函數(shù)f,計(jì)算了一個(gè)Series的最大值和最小值的差伙菊,在frame的每列都執(zhí)行了一次败玉。結(jié)果是一個(gè)Series,使用frame的列作為索引镜硕。

如果傳遞axis='columns'到apply运翼,這個(gè)函數(shù)會(huì)在每行執(zhí)行:

In [195]: frame.apply(f, axis='columns')
Out[195]:
Utah      0.998382
Ohio      2.521511
Texas     0.676115
Oregon    2.542656
dtype: float64

許多最為常見(jiàn)的數(shù)組統(tǒng)計(jì)功能都被實(shí)現(xiàn)成DataFrame的方法(如sum和mean),因此無(wú)需使用apply方法兴枯。

傳遞到apply的函數(shù)不是必須返回一個(gè)標(biāo)量血淌,還可以返回由多個(gè)值組成的Series:

In [196]: def f(x):
   .....:     return pd.Series([x.min(), x.max()], index=['min', 'max'])

In [197]: frame.apply(f)
Out[197]: 
            b         d         e
min -0.555730  0.281746 -1.296221
max  1.246435  1.965781  1.393406

元素級(jí)的Python函數(shù)也是可以用的。假如你想得到frame中各個(gè)浮點(diǎn)值的格式化字符串念恍,使用applymap即可:

In [198]: format = lambda x: '%.2f' % x

In [199]: frame.applymap(format)
Out[199]: 
            b     d      e
Utah    -0.20  0.48  -0.52
Ohio    -0.56  1.97   1.39
Texas    0.09  0.28   0.77
Oregon   1.25  1.01  -1.30

之所以叫做applymap六剥,是因?yàn)镾eries有一個(gè)用于應(yīng)用元素級(jí)函數(shù)的map方法:

In [200]: frame['e'].map(format)
Out[200]: 
Utah      -0.52
Ohio       1.39
Texas      0.77
Oregon    -1.30
Name: e, dtype: object

排序和排名

根據(jù)條件對(duì)數(shù)據(jù)集排序(sorting)也是一種重要的內(nèi)置運(yùn)算晚顷。要對(duì)行或列索引進(jìn)行排序(按字典順序),可使用sort_index方法疗疟,它將返回一個(gè)已排序的新對(duì)象:

In [201]: obj = pd.Series(range(4), index=['d', 'a', 'b', 'c'])

In [202]: obj.sort_index()
Out[202]:
a    1
b    2
c    3
d    0
dtype: int64

對(duì)于DataFrame该默,則可以根據(jù)任意一個(gè)軸上的索引進(jìn)行排序:

In [203]: frame = pd.DataFrame(np.arange(8).reshape((2, 4)),
   .....:                      index=['three', 'one'],
   .....:                      columns=['d', 'a', 'b', 'c'])

In [204]: frame.sort_index()
Out[204]: 
       d  a  b  c
one    4  5  6  7
three  0  1  2  3

In [205]: frame.sort_index(axis=1)
Out[205]:
       a  b  c  d
three  1  2  3  0
one    5  6  7  4

數(shù)據(jù)默認(rèn)是按升序排序的,但也可以降序排序:

In [206]: frame.sort_index(axis=1, ascending=False)
Out[206]: 
       d  c  b  a
three  0  3  2  1
one    4  7  6  5

若要按值對(duì)Series進(jìn)行排序策彤,可使用其sort_values方法:

In [207]: obj = pd.Series([4, 7, -3, 2])

In [208]: obj.sort_values()
Out[208]: 
2   -3
3    2
0    4
1    7
dtype: int64

在排序時(shí)栓袖,任何缺失值默認(rèn)都會(huì)被放到Series的末尾:

In [209]: obj = pd.Series([4, np.nan, 7, np.nan, -3, 2])

In [210]: obj.sort_values()
Out[210]: 
4   -3.0
5    2.0
0    4.0
2    7.0
1    NaN
3    NaN
dtype: float64

當(dāng)排序一個(gè)DataFrame時(shí),你可能希望根據(jù)一個(gè)或多個(gè)列中的值進(jìn)行排序店诗。將一個(gè)或多個(gè)列的名字傳遞給sort_values的by選項(xiàng)即可達(dá)到該目的:

In [211]: frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})

In [212]: frame
Out[212]: 
   a  b
0  0  4
1  1  7
2  0 -3
3  1  2

In [213]: frame.sort_values(by='b')
Out[213]: 
   a  b
2  0 -3
3  1  2
0  0  4
1  1  7

要根據(jù)多個(gè)列進(jìn)行排序裹刮,傳入名稱的列表即可:

In [214]: frame.sort_values(by=['a', 'b'])
Out[214]: 
   a  b
2  0 -3
0  0  4
3  1  2
1  1  7

排名會(huì)從1開(kāi)始一直到數(shù)組中有效數(shù)據(jù)的數(shù)量。接下來(lái)介紹Series和DataFrame的rank方法庞瘸。默認(rèn)情況下捧弃,rank是通過(guò)“為各組分配一個(gè)平均排名”的方式破壞平級(jí)關(guān)系的:

In [215]: obj = pd.Series([7, -5, 7, 4, 2, 0, 4])
In [216]: obj.rank()
Out[216]: 
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 [217]: obj.rank(method='first')
Out[217]: 
0    6.0
1    1.0
2    7.0
3    4.0
4    3.0
5    2.0
6    5.0
dtype: float64

這里,條目0和2沒(méi)有使用平均排名6.5擦囊,它們被設(shè)成了6和7违霞,因?yàn)閿?shù)據(jù)中標(biāo)簽0位于標(biāo)簽2的前面。

你也可以按降序進(jìn)行排名:

# Assign tie values the maximum rank in the group
In [218]: obj.rank(ascending=False, method='max')
Out[218]: 
0    2.0
1    7.0
2    2.0
3    4.0
4    5.0
5    6.0
6    4.0
dtype: float64

表5-6列出了所有用于破壞平級(jí)關(guān)系的method選項(xiàng)瞬场。DataFrame可以在行或列上計(jì)算排名:

In [219]: frame = pd.DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1],
   .....:                       'c': [-2, 5, 8, -2.5]})

In [220]: frame
Out[220]: 
   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 [221]: frame.rank(axis='columns')
Out[221]: 
     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-6 排名時(shí)用于破壞平級(jí)關(guān)系的方法

帶有重復(fù)標(biāo)簽的軸索引

直到目前為止买鸽,我所介紹的所有范例都有著唯一的軸標(biāo)簽(索引值)。雖然許多pandas函數(shù)(如reindex)都要求標(biāo)簽唯一贯被,但這并不是強(qiáng)制性的眼五。我們來(lái)看看下面這個(gè)簡(jiǎn)單的帶有重復(fù)索引值的Series:

In [222]: obj = pd.Series(range(5), index=['a', 'a', 'b', 'b', 'c'])

In [223]: obj
Out[223]: 
a    0
a    1
b    2
b    3
c    4
dtype: int64

索引的is_unique屬性可以告訴你它的值是否是唯一的:

In [224]: obj.index.is_unique
Out[224]: False

對(duì)于帶有重復(fù)值的索引,數(shù)據(jù)選取的行為將會(huì)有些不同彤灶。如果某個(gè)索引對(duì)應(yīng)多個(gè)值看幼,則返回一個(gè)Series;而對(duì)應(yīng)單個(gè)值的枢希,則返回一個(gè)標(biāo)量值:

In [225]: obj['a']
Out[225]: 
a    0
a    1
dtype: int64

In [226]: obj['c']
Out[226]: 4

這樣會(huì)使代碼變復(fù)雜桌吃,因?yàn)樗饕妮敵鲱?lèi)型會(huì)根據(jù)標(biāo)簽是否有重復(fù)發(fā)生變化。

對(duì)DataFrame的行進(jìn)行索引時(shí)也是如此:

In [227]: df = pd.DataFrame(np.random.randn(4, 3), index=['a', 'a', 'b', 'b'])

In [228]: df
Out[228]: 
          0         1         2
a  0.274992  0.228913  1.352917
a  0.886429 -2.001637 -0.371843
b  1.669025 -0.438570 -0.539741
b  0.476985  3.248944 -1.021228

In [229]: df.loc['b']
Out[229]: 
          0         1         2
b  1.669025 -0.438570 -0.539741
b  0.476985  3.248944 -1.021228

5.3 匯總和計(jì)算描述統(tǒng)計(jì)

pandas對(duì)象擁有一組常用的數(shù)學(xué)和統(tǒng)計(jì)方法苞轿。它們大部分都屬于約簡(jiǎn)和匯總統(tǒng)計(jì)茅诱,用于從Series中提取單個(gè)值(如sum或mean)或從DataFrame的行或列中提取一個(gè)Series。跟對(duì)應(yīng)的NumPy數(shù)組方法相比搬卒,它們都是基于沒(méi)有缺失數(shù)據(jù)的假設(shè)而構(gòu)建的瑟俭。看一個(gè)簡(jiǎn)單的DataFrame:

In [230]: df = pd.DataFrame([[1.4, np.nan], [7.1, -4.5],
   .....:                    [np.nan, np.nan], [0.75, -1.3]],
   .....:                   index=['a', 'b', 'c', 'd'],
   .....:                   columns=['one', 'two'])

In [231]: df
Out[231]: 
    one  two
a  1.40  NaN
b  7.10 -4.5
c   NaN  NaN
d  0.75 -1.3

調(diào)用DataFrame的sum方法將會(huì)返回一個(gè)含有列的和的Series:

In [232]: df.sum()
Out[232]: 
one    9.25
two   -5.80
dtype: float64

傳入axis='columns'或axis=1將會(huì)按行進(jìn)行求和運(yùn)算:

In [233]: df.sum(axis=1)
Out[233]:
a    1.40
b    2.60
c     NaN
d   -0.55

NA值會(huì)自動(dòng)被排除契邀,除非整個(gè)切片(這里指的是行或列)都是NA摆寄。通過(guò)skipna選項(xiàng)可以禁用該功能:

In [234]: df.mean(axis='columns', skipna=False)
Out[234]: 
a      NaN
b    1.300
c      NaN
d   -0.275
dtype: float64

表5-7列出了這些約簡(jiǎn)方法的常用選項(xiàng)。

有些方法(如idxmin和idxmax)返回的是間接統(tǒng)計(jì)(比如達(dá)到最小值或最大值的索引):

In [235]: df.idxmax()
Out[235]: 
one    b
two    d
dtype: object

另一些方法則是累計(jì)型的:

In [236]: df.cumsum()
Out[236]: 
    one  two
a  1.40  NaN
b  8.50 -4.5
c   NaN  NaN
d  9.25 -5.8

還有一種方法,它既不是約簡(jiǎn)型也不是累計(jì)型微饥。describe就是一個(gè)例子逗扒,它用于一次性產(chǎn)生多個(gè)匯總統(tǒng)計(jì):

In [237]: df.describe()
Out[237]: 
            one       two
count  3.000000  2.000000
mean   3.083333 -2.900000
std    3.493685  2.262742
min    0.750000 -4.500000
25%    1.075000 -3.700000
50%    1.400000 -2.900000
75%    4.250000 -2.100000
max    7.100000 -1.300000

對(duì)于非數(shù)值型數(shù)據(jù),describe會(huì)產(chǎn)生另外一種匯總統(tǒng)計(jì):

In [238]: obj = pd.Series(['a', 'a', 'b', 'c'] * 4)

In [239]: obj.describe()
Out[239]: 
count     16
unique     3
top        a
freq       8
dtype: object

表5-8列出了所有與描述統(tǒng)計(jì)相關(guān)的方法欠橘。

相關(guān)系數(shù)與協(xié)方差

有些匯總統(tǒng)計(jì)(如相關(guān)系數(shù)和協(xié)方差)是通過(guò)參數(shù)對(duì)計(jì)算出來(lái)的矩肩。我們來(lái)看幾個(gè)DataFrame,它們的數(shù)據(jù)來(lái)自Yahoo!Finance的股票價(jià)格和成交量肃续,使用的是pandas-datareader包(可以用conda或pip安裝):

conda install pandas-datareader

我使用pandas_datareader模塊下載了一些股票數(shù)據(jù):

import pandas_datareader.data as web
all_data = {ticker: web.get_data_yahoo(ticker)
            for ticker in ['AAPL', 'IBM', 'MSFT', 'GOOG']}

price = pd.DataFrame({ticker: data['Adj Close']
                     for ticker, data in all_data.items()})
volume = pd.DataFrame({ticker: data['Volume']
                      for ticker, data in all_data.items()})

注意:此時(shí)Yahoo! Finance已經(jīng)不存在了黍檩,因?yàn)?017年Yahoo!被Verizon收購(gòu)了。參閱pandas-datareader文檔始锚,可以學(xué)習(xí)最新的功能刽酱。

現(xiàn)在計(jì)算價(jià)格的百分?jǐn)?shù)變化,時(shí)間序列的操作會(huì)在第11章介紹:

In [242]: returns = price.pct_change()

In [243]: returns.tail()
Out[243]: 
                AAPL      GOOG       IBM      MSFT
Date                                              
2016-10-17 -0.000680  0.001837  0.002072 -0.003483
2016-10-18 -0.000681  0.019616 -0.026168  0.007690
2016-10-19 -0.002979  0.007846  0.003583 -0.002255
2016-10-20 -0.000512 -0.005652  0.001719 -0.004867
2016-10-21 -0.003930  0.003011 -0.012474  0.042096

Series的corr方法用于計(jì)算兩個(gè)Series中重疊的瞧捌、非NA的棵里、按索引對(duì)齊的值的相關(guān)系數(shù)。與此類(lèi)似察郁,cov用于計(jì)算協(xié)方差:

In [244]: returns['MSFT'].corr(returns['IBM'])
Out[244]: 0.49976361144151144

In [245]: returns['MSFT'].cov(returns['IBM'])
Out[245]: 8.8706554797035462e-05

因?yàn)镸STF是一個(gè)合理的Python屬性衍慎,我們還可以用更簡(jiǎn)潔的語(yǔ)法選擇列:

In [246]: returns.MSFT.corr(returns.IBM)
Out[246]: 0.49976361144151144

另一方面,DataFrame的corr和cov方法將以DataFrame的形式分別返回完整的相關(guān)系數(shù)或協(xié)方差矩陣:

In [247]: returns.corr()
Out[247]: 
          AAPL      GOOG       IBM      MSFT
AAPL  1.000000  0.407919  0.386817  0.389695
GOOG  0.407919  1.000000  0.405099  0.465919
IBM   0.386817  0.405099  1.000000  0.499764
MSFT  0.389695  0.465919  0.499764  1.000000

In [248]: returns.cov()
Out[248]: 
          AAPL      GOOG       IBM      MSFT
AAPL  0.000277  0.000107  0.000078  0.000095
GOOG  0.000107  0.000251  0.000078  0.000108
IBM   0.000078  0.000078  0.000146  0.000089
MSFT  0.000095  0.000108  0.000089  0.000215

利用DataFrame的corrwith方法皮钠,你可以計(jì)算其列或行跟另一個(gè)Series或DataFrame之間的相關(guān)系數(shù)。傳入一個(gè)Series將會(huì)返回一個(gè)相關(guān)系數(shù)值Series(針對(duì)各列進(jìn)行計(jì)算):

In [249]: returns.corrwith(returns.IBM)
Out[249]: 
AAPL    0.386817
GOOG    0.405099
IBM     1.000000
MSFT    0.499764
dtype: float64

傳入一個(gè)DataFrame則會(huì)計(jì)算按列名配對(duì)的相關(guān)系數(shù)赠法。這里麦轰,我計(jì)算百分比變化與成交量的相關(guān)系數(shù):

In [250]: returns.corrwith(volume)
Out[250]: 
AAPL   -0.075565
GOOG   -0.007067
IBM    -0.204849
MSFT   -0.092950
dtype: float64

傳入axis='columns'即可按行進(jìn)行計(jì)算。無(wú)論如何砖织,在計(jì)算相關(guān)系數(shù)之前款侵,所有的數(shù)據(jù)項(xiàng)都會(huì)按標(biāo)簽對(duì)齊。

唯一值侧纯、值計(jì)數(shù)以及成員資格

還有一類(lèi)方法可以從一維Series的值中抽取信息新锈。看下面的例子:

In [251]: obj = pd.Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c'])

第一個(gè)函數(shù)是unique眶熬,它可以得到Series中的唯一值數(shù)組:

In [252]: uniques = obj.unique()

In [253]: uniques
Out[253]: array(['c', 'a', 'd', 'b'], dtype=object)

返回的唯一值是未排序的妹笆,如果需要的話,可以對(duì)結(jié)果再次進(jìn)行排序(uniques.sort())娜氏。相似的拳缠,value_counts用于計(jì)算一個(gè)Series中各值出現(xiàn)的頻率:

In [254]: obj.value_counts()
Out[254]: 
c    3
a    3
b    2
d    1
dtype: int64

為了便于查看,結(jié)果Series是按值頻率降序排列的贸弥。value_counts還是一個(gè)頂級(jí)pandas方法窟坐,可用于任何數(shù)組或序列:

In [255]: pd.value_counts(obj.values, sort=False)
Out[255]: 
a    3
b    2
c    3
d    1
dtype: int64

isin用于判斷矢量化集合的成員資格,可用于過(guò)濾Series中或DataFrame列中數(shù)據(jù)的子集:

In [256]: obj
Out[256]: 
0    c
1    a
2    d
3    a
4    a
5    b
6    b
7    c
8    c
dtype: object

In [257]: mask = obj.isin(['b', 'c'])

In [258]: mask
Out[258]: 
0     True
1    False
2    False
3    False
4    False
5     True
6     True
7     True
8     True
dtype: bool

In [259]: obj[mask]
Out[259]: 
0    c
5    b
6    b
7    c
8    c
dtype: object

與isin類(lèi)似的是Index.get_indexer方法,它可以給你一個(gè)索引數(shù)組哲鸳,從可能包含重復(fù)值的數(shù)組到另一個(gè)不同值的數(shù)組:

In [260]: to_match = pd.Series(['c', 'a', 'b', 'b', 'c', 'a'])

In [261]: unique_vals = pd.Series(['c', 'b', 'a'])

In [262]: pd.Index(unique_vals).get_indexer(to_match)
Out[262]: array([0, 2, 1, 1, 0, 2])

表5-9給出了這幾個(gè)方法的一些參考信息臣疑。

表5-9 唯一值、值計(jì)數(shù)徙菠、成員資格方法

有時(shí)讯沈,你可能希望得到DataFrame中多個(gè)相關(guān)列的一張柱狀圖。例如:

In [263]: data = pd.DataFrame({'Qu1': [1, 3, 4, 3, 4],
   .....:                      'Qu2': [2, 3, 1, 2, 3],
   .....:                      'Qu3': [1, 5, 2, 4, 4]})

In [264]: data
Out[264]: 
   Qu1  Qu2  Qu3
0    1    2    1
1    3    3    5
2    4    1    2
3    3    2    4
4    4    3    4

將pandas.value_counts傳給該DataFrame的apply函數(shù)懒豹,就會(huì)出現(xiàn):

In [265]: result = data.apply(pd.value_counts).fillna(0)

In [266]: result
Out[266]: 
   Qu1  Qu2  Qu3
1  1.0  1.0  1.0
2  0.0  2.0  1.0
3  2.0  2.0  0.0
4  2.0  0.0  2.0
5  0.0  0.0  1.0

這里芙盘,結(jié)果中的行標(biāo)簽是所有列的唯一值。后面的頻率值是每個(gè)列中這些值的相應(yīng)計(jì)數(shù)脸秽。

5.4 總結(jié)

在下一章儒老,我們將討論用pandas讀取(或加載)和寫(xiě)入數(shù)據(jù)集的工具记餐。

之后驮樊,我們將更深入地研究使用pandas進(jìn)行數(shù)據(jù)清洗、規(guī)整片酝、分析和可視化工具囚衔。


第1章 準(zhǔn)備工作
第2章 Python語(yǔ)法基礎(chǔ),IPython和Jupyter
第3章 Python的數(shù)據(jù)結(jié)構(gòu)雕沿、函數(shù)和文件
第4章 NumPy基礎(chǔ):數(shù)組和矢量計(jì)算
第5章 pandas入門(mén)
第6章 數(shù)據(jù)加載练湿、存儲(chǔ)與文件格式
第7章 數(shù)據(jù)清洗和準(zhǔn)備
第8章 數(shù)據(jù)規(guī)整:聚合、合并和重塑
第9章 繪圖和可視化
第10章 數(shù)據(jù)聚合與分組運(yùn)算
第11章 時(shí)間序列
第12章 pandas高級(jí)應(yīng)用
第13章 Python建模庫(kù)介紹
第14章 數(shù)據(jù)分析案例
附錄A NumPy高級(jí)應(yīng)用
附錄B 更多關(guān)于IPython的內(nèi)容(完)


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末审轮,一起剝皮案震驚了整個(gè)濱河市肥哎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌疾渣,老刑警劉巖篡诽,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異榴捡,居然都是意外死亡杈女,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)吊圾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)达椰,“玉大人,你說(shuō)我怎么就攤上這事街夭∨椴辏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵板丽,是天一觀的道長(zhǎng)呈枉。 經(jīng)常有香客問(wèn)我趁尼,道長(zhǎng),這世上最難降的妖魔是什么猖辫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任酥泞,我火速辦了婚禮,結(jié)果婚禮上啃憎,老公的妹妹穿的比我還像新娘芝囤。我一直安慰自己,他們只是感情好辛萍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布悯姊。 她就那樣靜靜地躺著,像睡著了一般贩毕。 火紅的嫁衣襯著肌膚如雪悯许。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天辉阶,我揣著相機(jī)與錄音先壕,去河邊找鬼。 笑死谆甜,一個(gè)胖子當(dāng)著我的面吹牛垃僚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播规辱,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼谆棺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了罕袋?” 一聲冷哼從身側(cè)響起包券,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎炫贤,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體付秕,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡兰珍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了询吴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掠河。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖猛计,靈堂內(nèi)的尸體忽然破棺而出唠摹,到底是詐尸還是另有隱情,我是刑警寧澤奉瘤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布勾拉,位于F島的核電站煮甥,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏藕赞。R本人自食惡果不足惜成肘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斧蜕。 院中可真熱鬧双霍,春花似錦、人聲如沸批销。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)均芽。三九已至丘逸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間骡技,已是汗流浹背鸣个。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留布朦,地道東北人囤萤。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像是趴,于是被迫代替她去往敵國(guó)和親涛舍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容