2. pandas入門?在本書(shū)的剩下部分,pandas將是我們最敢興趣的主要庫(kù)。它包含高級(jí)的數(shù)據(jù)結(jié)構(gòu)和精巧的工具,使得在Python中處理數(shù)據(jù)非??焖俸秃?jiǎn)單。pandas建造在NumPy之上,它使得以NumPy為中心的應(yīng)用很容易使用。 作為一點(diǎn)兒背景,早在2008年,我任職于AQR(一個(gè)量化投資管理公司)開(kāi)始構(gòu)建pandas。當(dāng)時(shí),我有一組不同的需求,但對(duì)于我不能有一個(gè)單一的工具來(lái)很好的解決: * 支持自動(dòng)或明確的數(shù)據(jù)對(duì)齊的帶有標(biāo)簽軸的數(shù)據(jù)結(jié)構(gòu)。這可以防止由數(shù)據(jù)不對(duì)齊引起的常見(jiàn)錯(cuò)誤,并可以處理不同來(lái)源的不同索引數(shù)據(jù)。 * 整合的時(shí)間序列功能。 * 以相同的數(shù)據(jù)結(jié)構(gòu)來(lái)處理時(shí)間序列和非時(shí)間序列。 * 支持傳遞元數(shù)據(jù)(坐標(biāo)軸標(biāo)簽)的算術(shù)運(yùn)算和縮減。 * 靈活處理丟失數(shù)據(jù)。 * 在常用的基于數(shù)據(jù)的數(shù)據(jù)庫(kù)(例如基于SQL)中的合并和其它關(guān)系操作。 我想要在一個(gè)地方能夠做上面的所有的事情,最好是在一個(gè)非常適合于通用軟件開(kāi)發(fā)的語(yǔ)言中。Python是一個(gè)很好的候選,但是在那個(gè)時(shí)候沒(méi)有一個(gè)完整的數(shù)據(jù)結(jié)構(gòu)和工具的集合來(lái)提供這些功能。 在過(guò)去的四年里,pandas出乎我的意料,已經(jīng)成熟到一個(gè)非常大的庫(kù),可以解決非常廣泛的數(shù)據(jù)處理問(wèn)題。雖然它的使用范圍擴(kuò)大了,但并沒(méi)有拋棄我最初所渴望的簡(jiǎn)單和易使用性。我希望,通過(guò)閱讀本書(shū)后,你會(huì)想我一樣的發(fā)現(xiàn)它是一個(gè)必不可少的工具。 在本書(shū)的剩余部分,我對(duì)pandas使用下面的導(dǎo)入慣例: In [1]: from pandas import Series, DataFrame In [2]: import pandas as pd 2.1. pandas數(shù)據(jù)結(jié)構(gòu)入門?為了開(kāi)始使用pandas,你需要熟悉它的兩個(gè)重要的數(shù)據(jù)結(jié)構(gòu): Series 和 DataFrame 。雖然它們不是沒(méi)一個(gè)問(wèn)題的通用解決方案,但提供了一個(gè)堅(jiān)實(shí)的,易于使用的大多數(shù)應(yīng)用程序的基礎(chǔ)。 2.1.1. Series?Series是一個(gè)一維的類似的數(shù)組對(duì)象,包含一個(gè)數(shù)組的數(shù)據(jù)(任何NumPy的數(shù)據(jù)類型)和一個(gè)與數(shù)組關(guān)聯(lián)的數(shù)據(jù)標(biāo)簽,被叫做 索引 。最簡(jiǎn)單的Series是由一個(gè)數(shù)組的數(shù)據(jù)構(gòu)成: In [4]: obj = Series([4, 7, -5, 3]) In [5]: obj Out[5]: 0 4 1 7 2 -5 3 3 Seriers的交互式顯示的字符竄表示形式是索引在左邊,值在右邊。因?yàn)槲覀儧](méi)有給數(shù)據(jù)指定索引,一個(gè)包含整數(shù)0到 N-1 (這里N是數(shù)據(jù)的長(zhǎng)度)的默認(rèn)索引被創(chuàng)建。 你可以分別的通過(guò)它的 values 和 index 屬性來(lái)獲取Series的數(shù)組表示和索引對(duì)象: In [6]: obj.values Out[6]: array([ 4, 7, -5, 3]) In [7]: obj.index Out[7]: Int64Index([0, 1, 2, 3]) 通常,需要?jiǎng)?chuàng)建一個(gè)帶有索引來(lái)確定沒(méi)一個(gè)數(shù)據(jù)點(diǎn)的Series: In [8]: obj2 = Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c']) In [9]: obj2 Out[9]: d 4 b 7 a -5 c 3 In [10]: obj2.index Out[10]: Index([d, b, a, c], dtype=object) 與正規(guī)的NumPy數(shù)組相比,你可以使用索引里的值來(lái)選擇一個(gè)單一值或一個(gè)值集: 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 NumPy數(shù)組操作,例如通過(guò)一個(gè)布爾數(shù)組過(guò)濾,純量乘法,或使用數(shù)學(xué)函數(shù),將會(huì)保持索引和值間的關(guān)聯(lián): In [14]: obj2 Out[14]: d 6 b 7 a -5 c 3 In [15]: obj2[obj2 > 0] In [16]: obj2 * 2 In [17]: np.exp(obj2) Out[15]: Out[16]: Out[17]: d 6 d 12 d 403.428793 b 7 b 14 b 1096.633158 c 3 a -10 a 0.006738 c 6 c 20.085537 另一種思考的方式是,Series是一個(gè)定長(zhǎng)的,有序的字典,因?yàn)樗阉饕椭涤成淦饋?lái)了。它可以適用于許多期望一個(gè)字典的函數(shù): In [18]: 'b' in obj2 Out[18]: True In [19]: 'e' in obj2 Out[19]: False 如果你有一些數(shù)據(jù)在一個(gè)Python字典中,你可以通過(guò)傳遞字典來(lái)從這些數(shù)據(jù)創(chuàng)建一個(gè)Series: In [20]: sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000} In [21]: obj3 = Series(sdata) In [22]: obj3 Out[22]: Ohio 35000 Oregon 16000 Texas 71000 Utah 5000113 只傳遞一個(gè)字典的時(shí)候,結(jié)果Series中的索引將是排序后的字典的建。
在這種情況下, sdata 中的3個(gè)值被放在了合適的位置,但因?yàn)闆](méi)有發(fā)現(xiàn)對(duì)應(yīng)于 ‘California’ 的值,就出現(xiàn)了 NaN (不是一個(gè)數(shù)),這在pandas中被用來(lái)標(biāo)記數(shù)據(jù)缺失或 NA 值。我使用“missing”或“NA”來(lái)表示數(shù)度丟失。在pandas中用函數(shù) isnull 和 notnull 來(lái)檢測(cè)數(shù)據(jù)丟失: In [26]: pd.isnull(obj4) In [27]: pd.notnull(obj4) Out[26]: Out[27]: California True California False Ohio False Ohio True Oregon False Oregon True Texas False Texas True Series也提供了這些函數(shù)的實(shí)例方法: In [28]: obj4.isnull() Out[28]: California True Ohio False Oregon False Texas False 有關(guān)數(shù)據(jù)丟失的更詳細(xì)的討論將在本章的后面進(jìn)行。 在許多應(yīng)用中Series的一個(gè)重要功能是在算術(shù)用算中它會(huì)自動(dòng)對(duì)齊不同索引的數(shù)據(jù): In [29]: obj3 In [30]: obj4 Out[29]: Out[30]: Ohio 35000 California NaN Oregon 16000 Ohio 35000 Texas 71000 Oregon 16000 Utah 5000 Texas 71000 In [31]: obj3 + obj4 Out[31]: California NaN Ohio 70000 Oregon 32000 Texas 142000 Utah NaN 數(shù)據(jù)對(duì)齊被安排為一個(gè)獨(dú)立的話題。 Series對(duì)象本身和它的索引都有一個(gè) name 屬性,它和pandas的其它一些關(guān)鍵功能整合在一起: In [32]: obj4.name = 'population' In [33]: obj4.index.name = 'state' In [34]: obj4 Out[34]: state California NaN Ohio 35000 Oregon 16000 Texas 71000 Name: population Series的索引可以通過(guò)賦值就地更改: In [35]: obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan'] In [36]: obj Out[36]: Bob 4 Steve 7 Jeff -5 Ryan 3 2.1.2. DataFrame?一個(gè)Datarame表示一個(gè)表格,類似電子表格的數(shù)據(jù)結(jié)構(gòu),包含一個(gè)經(jīng)過(guò)排序的列表集,它們沒(méi)一個(gè)都可以有不同的類型值(數(shù)字,字符串,布爾等等)。Datarame有行和列的索引;它可以被看作是一個(gè)Series的字典(每個(gè)Series共享一個(gè)索引)。與其它你以前使用過(guò)的(如 R 的 data.frame )類似Datarame的結(jié)構(gòu)相比,在DataFrame里的面向行和面向列的操作大致是對(duì)稱的。在底層,數(shù)據(jù)是作為一個(gè)或多個(gè)二維數(shù)組存儲(chǔ)的,而不是列表,字典,或其它一維的數(shù)組集合。DataDrame內(nèi)部的精確細(xì)節(jié)已超出了本書(shū)的范圍。 因?yàn)镈ataFrame在內(nèi)部把數(shù)據(jù)存儲(chǔ)為一個(gè)二維數(shù)組的格式,因此你可以采用分層索引以表格格式來(lái)表示高維的數(shù)據(jù)。分層索引是后面章節(jié)的一個(gè)主題,并且是pandas中許多更先進(jìn)的數(shù)據(jù)處理功能的關(guān)鍵因素。 有很多方法來(lái)構(gòu)建一個(gè)DataFrame,但最常用的一個(gè)是用一個(gè)相等長(zhǎng)度列表的字典或NumPy數(shù)組: data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 'year': [2000, 2001, 2002, 2001, 2002], 'pop': [1.5, 1.7, 3.6, 2.4, 2.9]} frame = DataFrame(data) 由此產(chǎn)生的DataFrame和Series一樣,它的索引會(huì)自動(dòng)分配,并且對(duì)列進(jìn)行了排序: In [38]: frame Out[38]: 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 如果你設(shè)定了一個(gè)列的順序,DataFrame的列將會(huì)精確的按照你所傳遞的順序排列: In [39]: DataFrame(data, columns=['year', 'state', 'pop']) Out[39]: 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一樣,如果你傳遞了一個(gè)行,但不包括在 data 中,在結(jié)果中它會(huì)表示為NA值: In [40]: frame2 = DataFrame(data, columns=['year', 'state', 'pop', 'debt'], ....: index=['one', 'two', 'three', 'four', 'five']) In [41]: frame2 Out[41]: 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 [42]: frame2.columns Out[42]: Index([year, state, pop, debt], dtype=object) 和Series一樣,在DataFrame中的一列可以通過(guò)字典記法或?qū)傩詠?lái)檢索: In [43]: frame2['state'] In [44]: frame2.year Out[43]: Out[44]: one Ohio one 2000 two Ohio two 2001 three Ohio three 2002 four Nevada four 2001 five Nevada five 2002 Name: state Name: year 注意,返回的Series包含和DataFrame相同的索引,并它們的 name 屬性也被正確的設(shè)置了。 行也可以使用一些方法通過(guò)位置或名字來(lái)檢索,例如 ix 索引成員(field)(更多的將在后面介紹): In [45]: frame2.ix['three'] Out[45]: year 2002 state Ohio pop 3.6 debt NaN Name: three 列可以通過(guò)賦值來(lái)修改。例如,空的 ‘debt’ 列可以通過(guò)一個(gè)純量或一個(gè)數(shù)組來(lái)賦值: In [46]: frame2['debt'] = 16.5 In [47]: frame2 Out[47]: 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 [48]: frame2['debt'] = np.arange(5.) In [49]: frame2 Out[49]: year state pop debt one 2000 Ohio 1.5 0 two 2001 Ohio 1.7 1 three 2002 Ohio 3.6 2 four 2001 Nevada 2.4 3 five 2002 Nevada 2.9 4 通過(guò)列表或數(shù)組給一列賦值時(shí),所賦的值的長(zhǎng)度必須和DataFrame的長(zhǎng)度相匹配。如果你使用Series來(lái)賦值,它會(huì)代替在DataFrame中精確匹配的索引的值,并在說(shuō)有的空洞插入丟失數(shù)據(jù): In [50]: val = Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five']) In [51]: frame2['debt'] = val In [52]: frame2 Out[52]: 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 給一個(gè)不存在的列賦值,將會(huì)創(chuàng)建一個(gè)新的列。 像字典一樣 del 關(guān)鍵字將會(huì)刪除列: In [53]: frame2['eastern'] = frame2.state == 'Ohio' In [54]: frame2 Out[54]: 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 [55]: del frame2['eastern'] In [56]: frame2.columns Out[56]: Index([year, state, pop, debt], dtype=object) 索引DataFrame時(shí)返回的列是底層數(shù)據(jù)的一個(gè)視窗,而不是一個(gè)拷貝。因此,任何在Series上的就地修改都會(huì)影響DataFrame。列可以使用Series的 copy 函數(shù)來(lái)顯式的拷貝。 另一種通用的數(shù)據(jù)形式是一個(gè)嵌套的字典的字典格式: In [57]: pop = {'Nevada': {2001: 2.4, 2002: 2.9}, ....: 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}} 如果被傳遞到DataFrame,它的外部鍵會(huì)被解釋為列索引,內(nèi)部鍵會(huì)被解釋為行索引: In [58]: frame3 = DataFrame(pop) In [59]: frame3 Out[59]: Nevada Ohio 2000 NaN 1.5 2001 2.4 1.7 2002 2.9 3.6 當(dāng)然,你總是可以對(duì)結(jié)果轉(zhuǎn)置: In [60]: frame3.T Out[60]: 2000 2001 2002 Nevada NaN 2.4 2.9 Ohio 1.5 1.7 3.6 內(nèi)部字典的鍵被結(jié)合并排序來(lái)形成結(jié)果的索引。如果指定了一個(gè)特定的索引,就不是這樣的了: In [61]: DataFrame(pop, index=[2001, 2002, 2003]) Out[61]: Nevada Ohio 2001 2.4 1.7 2002 2.9 3.6 2003 NaN NaN Series的字典也以相同的方式來(lái)處理: In [62]: pdata = {'Ohio': frame3['Ohio'][:-1], ....: 'Nevada': frame3['Nevada'][:2]} In [63]: DataFrame(pdata) Out[63]: Nevada Ohio 2000 NaN 1.5 2001 2.4 1.7 你可以傳遞到DataFrame構(gòu)造器的東西的完整清單,見(jiàn)表格5-1。 如果一個(gè)DataFrame的 index 和 columns 有它們的 name ,也會(huì)被顯示出來(lái): In [64]: frame3.index.name = 'year'; frame3.columns.name = 'state' In [65]: frame3 Out[65]: state Nevada Ohio year 2000 NaN 1.5 2001 2.4 1.7 2002 2.9 3.6 像Series一樣, values 屬性返回一個(gè)包含在DataFrame中的數(shù)據(jù)的二維ndarray: In [66]: frame3.values Out[66]: array([[ nan, 1.5], [ 2.4, 1.7], [ 2.9, 3.6]]) 如果DataFrame的列有不同的dtypes,返回值數(shù)組將會(huì)給所有的列選擇一個(gè)合適的dtyps: In [67]: frame2.values Out[67]: 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]], dtype=object)
2.1.3. 索引對(duì)象?pandas的索引對(duì)象用來(lái)保存坐標(biāo)軸標(biāo)簽和其它元數(shù)據(jù)(如坐標(biāo)軸名或名稱)。構(gòu)建一個(gè)Series或DataFrame時(shí)任何數(shù)組或其它序列標(biāo)簽在內(nèi)部轉(zhuǎn)化為索引: In [68]: obj = Series(range(3), index=['a', 'b', 'c']) In [69]: index = obj.index In [70]: index Out[70]: Index([a, b, c], dtype=object) In [71]: index[1:] Out[71]: Index([b, c], dtype=object) 索引對(duì)象是不可變的,因此不能由用戶改變: In [72]: index[1] = 'd' --------------------------------------------------------------------------- Exception Traceback (most recent call last) <ipython-input-72-676fdeb26a68> in <module>() ----> 1 index[1] = 'd' /Users/wesm/code/pandas/pandas/core/index.pyc in __setitem__(self, key, value) 302 def __setitem__(self, key, value): 303 """Disable the setting of values.""" --> 304 raise Exception(str(self.__class__) + ' object is immutable') 305 306 def __getitem__(self, key): Exception: <class 'pandas.core.index.Index'> object is immutable 索引對(duì)象的不可變性非常重要,這樣它可以在數(shù)據(jù)結(jié)構(gòu)中結(jié)構(gòu)中安全的共享: In [73]: index = pd.Index(np.arange(3)) In [74]: obj2 = Series([1.5, -2.5, 0], index=index) In [75]: obj2.index is index Out[75]: True 表格5-2 是庫(kù)中內(nèi)建的索引類清單。通過(guò)一些開(kāi)發(fā)努力,索引可以被子類化,來(lái)實(shí)現(xiàn)特定坐標(biāo)軸索引功能。 多數(shù)用戶不必要知道許多索引對(duì)象的知識(shí),但是它們?nèi)匀皇莗andas數(shù)據(jù)模型的重要部分。
除了類似于陣列,索引也有類似固定大小集合一樣的功能: In [76]: frame3 Out[76]: state Nevada Ohio year 2000 NaN 1.5 2001 2.4 1.7 2002 2.9 3.6 In [77]: 'Ohio' in frame3.columns Out[77]: True In [78]: 2003 in frame3.index Out[78]: False 每個(gè)索引都有許多關(guān)于集合邏輯的方法和屬性,且能夠解決它所包含的數(shù)據(jù)的常見(jiàn)問(wèn)題。這些都總結(jié)在表格5-3 中。
2.2. 重要的功能?在本節(jié)中,我將帶你穿過(guò)Series或DataFrame所包含的數(shù)據(jù)的基礎(chǔ)結(jié)構(gòu)的相互關(guān)系。在接下來(lái)的章節(jié)中,將要更深入的探究使用pandas進(jìn)行數(shù)據(jù)分析和處理的主題。本書(shū)并不想要作為一個(gè)關(guān)于pandas庫(kù)的詳盡的文檔;反而我將注意力集中在最重要的特性上,讓不常見(jiàn)(也就是,比較深?yuàn)W)的東西,你去自己探索。 2.2.1. 重新索引?pandas對(duì)象的一個(gè)關(guān)鍵的方法是 reindex ,意味著使數(shù)據(jù)符合一個(gè)新的索引來(lái)構(gòu)造一個(gè)新的對(duì)象。來(lái)看一下下面一個(gè)簡(jiǎn)單的例子: In [79]: obj = Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c']) In [80]: obj Out[80]: d 4.5 b 7.2 a -5.3 c 3.6 在Series上調(diào)用 reindex 重排數(shù)據(jù),使得它符合新的索引,如果那個(gè)索引的值不存在就引入缺失數(shù)據(jù)值: In [81]: obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e']) In [82]: obj2 Out[82]: a -5.3 b 7.2 c 3.6 d 4.5 e NaN In [83]: obj.reindex(['a', 'b', 'c', 'd', 'e'], fill_value=0) Out[83]: a -5.3 b 7.2 c 3.6 d 4.5 e 0.0 為了對(duì)時(shí)間序列這樣的數(shù)據(jù)排序,當(dāng)重建索引的時(shí)候可能想要對(duì)值進(jìn)行內(nèi)插或填充。 method 選項(xiàng)可以是你做到這一點(diǎn),使用一個(gè)如 ffill 的方法來(lái)向前填充值: In [84]: obj3 = Series(['blue', 'purple', 'yellow'], index=[0, 2, 4]) In [85]: obj3.reindex(range(6), method='ffill') Out[85]: 0 blue 1 blue 2 purple 3 purple 4 yellow 5 yellow 表格5-4 是可用的 method 選項(xiàng)的清單。在此,內(nèi)差比正向和反向填充更復(fù)雜。
對(duì)于DataFrame, reindex 可以改變(行)索引,列或兩者。當(dāng)只傳入一個(gè)序列時(shí),結(jié)果中的行被重新索引了: In [86]: frame = DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'], ....: columns=['Ohio', 'Texas', 'California']) In [87]: frame Out[87]: Ohio Texas California a 0 1 2 c 3 4 5 d 6 7 8 In [88]: frame2 = frame.reindex(['a', 'b', 'c', 'd']) In [89]: frame2 Out[89]: Ohio Texas California a 0 1 2 b NaN NaN NaN c 3 4 5 d 6 7 8 使用 columns 關(guān)鍵字可以是列重新索引: In [90]: states = ['Texas', 'Utah', 'California'] In [91]: frame.reindex(columns=states) Out[91]: Texas Utah California a 1 NaN 2 c 4 NaN 5 d 7 NaN 8 一次可以對(duì)兩個(gè)重新索引,可是插值只在行側(cè)(0坐標(biāo)軸)進(jìn)行: In [92]: frame.reindex(index=['a', 'b', 'c', 'd'], method='ffill', ....: columns=states) Out[92]: Texas Utah California a 1 NaN 2 b 1 NaN 2 c 4 NaN 5 d 7 NaN 8 正如你將看到的,使用帶標(biāo)簽索引的 ix 可以把重新索引做的更簡(jiǎn)單: In [93]: frame.ix[['a', 'b', 'c', 'd'], states] Out[93]: Texas Utah California a 1 NaN 2 b NaN NaN NaN c 4 NaN 5 d 7 NaN 8
2.3. 從一個(gè)坐標(biāo)軸刪除條目?從坐標(biāo)軸刪除一個(gè)多或多個(gè)條目是很容易的,如果你有一個(gè)索引數(shù)組或列表且沒(méi)有這些條目,但是這可能需要一點(diǎn)修改和集合邏輯。 drop 方法將會(huì)返回一個(gè)新的對(duì)象并從坐標(biāo)軸中刪除指定的一個(gè)或多個(gè)值: In [94]: obj = Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e']) In [95]: new_obj = obj.drop('c') In [96]: new_obj Out[96]: a 0 b 1 d 3 e 4 In [97]: obj.drop(['d', 'c']) Out[97]: a 0 b 1 e 4 對(duì)于DataFrame,可以從任何坐標(biāo)軸刪除索引值: In [98]: data = DataFrame(np.arange(16).reshape((4, 4)), ....: index=['Ohio', 'Colorado', 'Utah', 'New York'], ....: columns=['one', 'two', 'three', 'four']) In [99]: data.drop(['Colorado', 'Ohio']) Out[99]: one two three four Utah 8 9 10 11 New York 12 13 14 15 In [100]: data.drop('two', axis=1) In [101]: data.drop(['two', 'four'], axis=1) Out[100]: Out[101]: one three four one three Ohio 0 2 3 Ohio 0 2 Colorado 4 6 7 Colorado 4 6 Utah 8 10 11 Utah 8 10 New York 12 14 15 New York 12 14 2.3.1. 索引,挑選和過(guò)濾?Series索引( obj[...] )的工作原理類似與NumPy索引,除了可以使用Series的索引值,也可以僅使用整數(shù)來(lái)索引。下面是關(guān)于這一點(diǎn)的一些例子: In [102]: obj = Series(np.arange(4.), index=['a', 'b', 'c', 'd']) In [103]: obj['b'] In [104]: obj[1] Out[103]: 1.0 Out[104]: 1.0 In [105]: obj[2:4] In [106]: obj[['b', 'a', 'd']] Out[105]: Out[106]: c 2 b 1 d 3 a 0 d 3 In [107]: obj[[1, 3]] In [108]: obj[obj < 2] Out[107]: Out[108]: b 1 a 0 d 3 b 1 使用標(biāo)簽來(lái)切片和正常的Python切片并不一樣,它會(huì)把結(jié)束點(diǎn)也包括在內(nèi): In [109]: obj['b':'c'] Out[109]: b 1 c 2 使用這些函數(shù)來(lái)復(fù)制,其工作方法和你想象的一樣: In [110]: obj['b':'c'] = 5 In [111]: obj Out[111]: a 0 b 5 c 5 d 3 正如上面你所見(jiàn)到的,索引DataFrame來(lái)檢索一個(gè)或多個(gè)列,可以使用一個(gè)單一值或一個(gè)序列: In [112]: data = DataFrame(np.arange(16).reshape((4, 4)), .....: index=['Ohio', 'Colorado', 'Utah', 'New York'], .....: columns=['one', 'two', 'three', 'four']) In [113]: data Out[113]: 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 [114]: data['two'] In [115]: data[['three', 'one']] Out[114]: Out[115]: Ohio 1 three one Colorado 5 Ohio 2 0 Utah 9 Colorado 6 4 New York 13 Utah 10 8 Name: two New York 14 12 像這樣的索引有一些特殊的情況。首先,可以通過(guò)切片或一個(gè)布爾數(shù)組來(lái)選擇行: In [116]: data[:2] In [117]: data[data['three'] > 5] Out[116]: Out[117]: one two three four one two three four Ohio 0 1 2 3 Colorado 4 5 6 7 Colorado 4 5 6 7 Utah 8 9 10 11 New York 12 13 14 15 對(duì)一些讀者來(lái)說(shuō)這似乎不一致,但出現(xiàn)這種語(yǔ)法除了實(shí)用并沒(méi)有其它什么。另一種用法是在索引中使用一個(gè)布爾DataFrame,例如通過(guò)純量比較產(chǎn)生的: 這旨在在這種情況下使得DataFrame的語(yǔ)法更像一個(gè)ndarry。為了使DataFrame可以在行上進(jìn)行標(biāo)簽索引,我將介紹特殊的索引字段 ix 。這使你可以從DataFrame選擇一個(gè)行和列的子集,使用像NumPy的記法再加上軸標(biāo)簽。正如我早先提到的,這也是一種不是很冗長(zhǎng)的重新索引的方法: 因此,有很多方法來(lái)選擇和重排包含在pandas對(duì)象中的數(shù)據(jù)。對(duì)于DataFrame, 表格5-6 是這些方法的簡(jiǎn)短概要。稍后你將接觸到分層索引,那時(shí)你會(huì)有一些額外的選項(xiàng)。 在設(shè)計(jì)pandas時(shí),我覺(jué)得不得不敲下 frame[:, col] 來(lái)選擇一列,是非常冗余的(且易出錯(cuò)的),因此列選擇是最常見(jiàn)的操作之一。因此,我做了這個(gè)設(shè)計(jì)權(quán)衡,把所有的富標(biāo)簽索引引入到 ix 。
2.3.2. 算術(shù)和數(shù)據(jù)對(duì)其?pandas的最重要的特性之一是在具有不同索引的對(duì)象間進(jìn)行算術(shù)運(yùn)算的行為。當(dāng)把對(duì)象加起來(lái)時(shí),如果有任何的索引對(duì)不相同的話,在結(jié)果中將會(huì)把各自的索引聯(lián)合起來(lái)。讓我們看一個(gè)簡(jiǎn)單的例子: .. image:: _static/126.png 把它們加起來(lái)生成: ..image:: _static/130.png 內(nèi)部數(shù)據(jù)對(duì)其,在索引不重合的地方引入了NA值。數(shù)據(jù)缺失在算術(shù)運(yùn)算中會(huì)傳播。 對(duì)于DataFrame,對(duì)其在行和列上都表現(xiàn)的很好: 把這些加起來(lái)返回一個(gè)DataFrame,它的索引和列是每一個(gè)DataFrame對(duì)應(yīng)的索引和列的聯(lián)合: 2.3.2.1. 帶填充值的算術(shù)方法?在不同索引對(duì)象間的算術(shù)運(yùn)算,當(dāng)一個(gè)軸標(biāo)簽在另一個(gè)對(duì)象中找不到時(shí),你可能想要填充一個(gè)特定的值,如0: 把它們加起來(lái)導(dǎo)致在不重合的位置出現(xiàn)NA值: 在 df1 上使用 add 方法,我把 df2 傳遞給它并給 fill_value 賦了一個(gè)參數(shù): .. image:: _static/141.png 相關(guān)的,當(dāng)你重新索引Series或DataFrame時(shí),你可以設(shè)定一個(gè)不同的填充值:
2.3.2.2. DataFrame 和 Series 間的操作?與NumPy數(shù)組一樣,很好的定義了DataFrame和Series間的算術(shù)操作。首先,作為一個(gè)激發(fā)性的例子,考慮一個(gè)二維數(shù)組和它的一個(gè)行間的差分: 這被稱為 廣播 (broadcasting),在第12章將會(huì)對(duì)此進(jìn)行更詳細(xì)的解釋。在一個(gè)DataFrame和一個(gè)Series間的操作是類似的: 默認(rèn)的,DataFrame和Series間的算術(shù)運(yùn)算Series的索引將匹配DataFrame的列,并在行上擴(kuò)展: 如果一個(gè)索引值在DataFrame的列和Series的索引里都找不著,對(duì)象將會(huì)從它們的聯(lián)合重建索引: 如果想在行上而不是列上進(jìn)行擴(kuò)展,你要使用一個(gè)算術(shù)方法。例如: 你所傳遞的坐標(biāo)值是將要匹配的 坐標(biāo) 。在這種情況下,我們的意思是匹配DataFrame的行,并進(jìn)行擴(kuò)展。 2.3.3. 函數(shù)應(yīng)用和映射? |
|