一、Series
Pandas的核心是三大數據結構:Series、DataFrame和Index。絕大多數操作都是圍繞這三種結構進行的。
Series是一個一維的數組對象,它包含一個值序列和一個對應的索引序列。 Numpy的一維數組通過隱式定義的整數索引獲取元素值,而Series用一種顯式定義的索引與元素關聯。顯式索引讓Series對象擁有更強的能力,索引也不再僅僅是整數,還可以是別的類型,比如字符串,索引也不需要連續,也可以重復,自由度非常高。
最基本的生成方式是使用Series構造器:
import pandas as pd s = pd.Series([7,-3,4,-2]) s Out[5]: 0 7
1 -3
2 4
3 -2 dtype: int64
打印的時候,自動對齊了,看起來比較美觀。左邊是索引,右邊是實際對應的值。默認的索引是0到N-1(N是數據的長度)。可以通過values和index屬性分別獲取Series對象的值和索引:
In [5]: s.dtype Out[5]: dtype('int64') In [6]: s.values Out[6]: array([ 7, -3, 4, -2], dtype=int64) In [7]: s.index Out[7]: RangeIndex(start=0, stop=4, step=1)
可以在創建Series對象的時候指定索引:
In [8]: s2 = pd.Series([7,-3,4,-2], index=['d','b','a','c']) In [9]: s2 Out[9]: d 7 b -3 a 4 c -2 dtype: int64 In [10]: s2.index Out[10]: Index(['d', 'b', 'a', 'c'], dtype='object') In [4]: pd.Series(5, index=list('abcde')) Out[4]: a 5 b 5 c 5 d 5 e 5 dtype: int64 In [5]: pd.Series({2:'a',1:'b',3:'c'}, index=[3,2]) # 通過index篩選結果
Out[5]: 3 c 2 a dtype: object
也可以在后期,直接修改index:
In [33]: s Out[33]: 0 7
1 -3
2 4
3 -2 dtype: int64 In [34]: s.index = ['a','b','c','d'] In [35]: s Out[35]: a 7 b -3 c 4 d -2 dtype: int64
類似Python的列表和Numpy的數組,Series也可以通過索引獲取對應的值:
In [11]: s2['a'] Out[11]: 4 In [12]: s2[['c','a','d']] Out[12]: c -2 a 4 d 7 dtype: int64
也可以對Seires執行一些類似Numpy的通用函數操作:
In [13]: s2[s2>0] Out[13]: d 7 a 4 dtype: int64 In [14]: s2*2 Out[14]: d 14 b -6 a 8 c -4 dtype: int64 In [15]: import numpy as np In [16]: np.exp(s2) Out[16]: d 1096.633158 b 0.049787 a 54.598150 c 0.135335 dtype: float64
因為索引可以是字符串,所以從某個角度看,Series又比較類似Python的有序字典,所以可以使用in操作:
In [17]: 'b' in s2 Out[17]: True In [18]: 'e'in s2 Out[18]: False
自然,我們也會想到使用Python的字典來創建Series:
In [19]: dic = {'beijing':35000,'shanghai':71000,'guangzhou':16000,'shenzhen':5000} In [20]: s3=pd.Series(dic) In [21]: s3 Out[21]: beijing 35000 shanghai 71000 guangzhou 16000 shenzhen 5000 dtype: int64 In [14]: s3.keys() # 自然,具有類似字典的方法
Out[14]: Index(['beijing', 'shanghai', 'guangzhou', 'shenzhen'], dtype='object') In [15]: s3.items() Out[15]: <zip at 0x1a5c2d88c88> In [16]: list(s3.items()) Out[16]: [('beijing', 35000), ('shanghai', 71000), ('guangzhou', 16000), ('shenzhen', 5000)] In [18]: s3['changsha'] = 20300
看下面的例子:
In [22]: city = ['nanjing', 'shanghai','guangzhou','beijing'] In [23]: s4=pd.Series(dic, index=city) In [24]: s4 Out[24]: nanjing NaN shanghai 71000.0 guangzhou 16000.0 beijing 35000.0 dtype: float64
city列表中,多了‘nanjing’,但少了‘shenzhen’。Pandas會依據city中的關鍵字去dic中查找對應的值,因為dic中沒有‘nanjing’,這個值缺失,所以以專門的標記值NaN表示。因為city中沒有‘shenzhen’,所以在s4中也不會存在‘shenzhen’這個條目。可以看出,索引很關鍵,在這里起到了決定性的作用。
在Pandas中,可以使用isnull和notnull函數來檢查缺失的數據:
In [25]: pd.isnull(s4) Out[25]: nanjing True shanghai False guangzhou False beijing False dtype: bool In [26]: pd.notnull(s4) Out[26]: nanjing False shanghai True guangzhou True beijing True dtype: bool In [27]: s4.isnull() Out[27]: nanjing True shanghai False guangzhou False beijing False dtype: bool
可以為Series對象和其索引設置name屬性,這有助於標記識別:
In [29]: s4.name = 'people' In [30]: s4.index.name= 'city' In [31]: s4 Out[31]: city nanjing NaN shanghai 71000.0 guangzhou 16000.0 beijing 35000.0 Name: people, dtype: float64 In [32]: s4.index Out[32]: Index(['nanjing', 'shanghai', 'guangzhou', 'beijing'], dtype='object', name='city')
二、DataFrame
DataFrame是Pandas的核心數據結構,表示的是二維的矩陣數據表,類似關系型數據庫的結構,每一列可以是不同的值類型,比如數值、字符串、布爾值等等。DataFrame既有行索引,也有列索引,它可以被看做為一個共享相同索引的Series的字典。
創建DataFrame對象的方法有很多,最常用的是利用包含等長度列表或Numpy數組的字典來生成。可以查看DataFrame對象的columns和index屬性。
In [37]: data = {'state':['beijing','beijing','beijing','shanghai','shanghai','shanghai'], ...: 'year':[2000,2001,2002,2001,2002,2003], ...: 'pop':[1.5, 1.7,3.6,2.4,2.9,3.2 ...: ]} In [38]: f = pd.DataFrame(data) In [39]: f Out[39]: state year pop 0 beijing 2000 1.5
1 beijing 2001 1.7
2 beijing 2002 3.6
3 shanghai 2001 2.4
4 shanghai 2002 2.9
5 shanghai 2003 3.2 In [61]: f.columns Out[61]: Index(['state', 'year', 'pop'], dtype='object') In [62]: f.index Out[62]: RangeIndex(start=0, stop=6, step=1) In [10]: f.dtypes Out[10]: state object year int64 pop float64 dtype: object In [11]: f.values # 按行查看
Out[11]: array([['beijing', 2000, 1.5], ['beijing', 2001, 1.7], ['beijing', 2002, 3.6], ['shanghai', 2001, 2.4], ['shanghai', 2002, 2.9], ['shanghai', 2003, 3.2]], dtype=object)
上面自動生成了0-5的索引。
可以使用head方法查看DataFrame對象的前5行,用tail方法查看后5行。或者head(3),tail(3)指定查看行數:
In [40]: f.head() Out[40]: state year pop 0 beijing 2000 1.5
1 beijing 2001 1.7
2 beijing 2002 3.6
3 shanghai 2001 2.4
4 shanghai 2002 2.9 In [41]: f.tail() Out[41]: state year pop 1 beijing 2001 1.7
2 beijing 2002 3.6
3 shanghai 2001 2.4
4 shanghai 2002 2.9
5 shanghai 2003 3.2
DataFrame對象中的state/year/pop,其實就是列索引,可以在創建的時候使用參數名columns指定它們的先后順序:
In [44]: pd.DataFrame(data, columns=['year','state','pop']) Out[44]: year state pop 0 2000 beijing 1.5
1 2001 beijing 1.7
2 2002 beijing 3.6
3 2001 shanghai 2.4
4 2002 shanghai 2.9
5 2003 shanghai 3.2
當然,也可以使用參數名index指定行索引:
In [45]: f2 = pd.DataFrame(data, columns=['year','state','pop'],index=['a','b','c','d','e','f']) In [47]: f2 Out[47]: year state pop a 2000 beijing 1.5 b 2001 beijing 1.7 c 2002 beijing 3.6 d 2001 shanghai 2.4 e 2002 shanghai 2.9 f 2003 shanghai 3.2
可以使用columns列索引來檢索一列:
In [49]: f2['year'] Out[49]: a 2000 b 2001 c 2002 d 2001 e 2002 f 2003 Name: year, dtype: int64 In [52]: f2.state # 屬性的形式來檢索。這種方法bug多,比如屬性名不是純字符串,或者與其它方法同名
Out[52]: a beijing b beijing c beijing d shanghai e shanghai f shanghai Name: state, dtype: object
但是檢索一行卻不能通過f2['a']這種方式,而是需要通過loc方法進行選取:
In [53]: f2.loc['a'] Out[53]: year 2000 state beijing pop 1.5 Name: a, dtype: object
當然,可以給DataFrame對象追加列:
In [54]: f2['debt'] = 12 In [55]: f2 Out[55]: year state pop debt a 2000 beijing 1.5 12 b 2001 beijing 1.7 12 c 2002 beijing 3.6 12 d 2001 shanghai 2.4 12 e 2002 shanghai 2.9 12 f 2003 shanghai 3.2 12 In [56]: f2['debt'] = np.arange(1,7) In [57]: f2 Out[57]: year state pop debt a 2000 beijing 1.5 1 b 2001 beijing 1.7 2 c 2002 beijing 3.6 3 d 2001 shanghai 2.4 4 e 2002 shanghai 2.9 5 f 2003 shanghai 3.2 6 In [58]: val = pd.Series([1,2,3],index = ['c','d','f']) In [59]: f2['debt'] = val In [60]: f2 # 缺失值以NaN填補
Out[60]: year state pop debt a 2000 beijing 1.5 NaN b 2001 beijing 1.7 NaN c 2002 beijing 3.6 1.0 d 2001 shanghai 2.4 2.0 e 2002 shanghai 2.9 NaN f 2003 shanghai 3.2 3.0
那么如何給DataFrame追加行呢?
>>> data = {'state':['beijing','beijing','beijing','shanghai','shanghai','shanghai'], ...: 'year':[2000,2001,2002,2001,2002,2003], ...: 'pop':[1.5, 1.7,3.6,2.4,2.9,3.2 ...: ]} >>> df = pd.DataFrame(data,index=list('abcdef')) >>> df state year pop a beijing 2000 1.5 b beijing 2001 1.7 c beijing 2002 3.6 d shanghai 2001 2.4 e shanghai 2002 2.9 f shanghai 2003 3.2
>>> df1 = df.loc['a'] >>> df1 state beijing year 2000 pop 1.5 Name: a, dtype: object >>> df.append(df1) state year pop a beijing 2000 1.5 b beijing 2001 1.7 c beijing 2002 3.6 d shanghai 2001 2.4 e shanghai 2002 2.9 f shanghai 2003 3.2 a beijing 2000 1.5
可以使用del方法刪除指定的列:
In [63]: f2['new'] = f2.state=='beijing' In [64]: f2 Out[64]: year state pop debt new a 2000 beijing 1.5 NaN True b 2001 beijing 1.7 NaN True c 2002 beijing 3.6 1.0 True d 2001 shanghai 2.4 2.0 False e 2002 shanghai 2.9 NaN False f 2003 shanghai 3.2 3.0 False In [65]: del f2.new # 要注意的是我們有時候不能這么調用f2的某個列,並執行某個操作。這是個坑。
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-65-03e4ec812cdb> in <module>() ----> 1 del f2.new AttributeError: new In [66]: del f2['new'] In [67]: f2.columns Out[67]: Index(['year', 'state', 'pop', 'debt'], dtype='object')
需要注意的是:從DataFrame中選取的列是數據的視圖,而不是拷貝。因此,對選取列的修改會反映到DataFrame上。如果需要復制,應當使用copy方法。
可以使用類似Numpy的T屬性,將DataFrame進行轉置:
In [68]: f2.T Out[68]: a b c d e f year 2000 2001 2002 2001 2002 2003 state beijing beijing beijing shanghai shanghai shanghai pop 1.5 1.7 3.6 2.4 2.9 3.2 debt NaN NaN 1 2 NaN 3
DataFrame對象同樣具有列名、索引名,也可以查看values:
In [70]: f2.index.name = 'order';f2.columns.name='key' In [71]: f2 Out[71]: key year state pop debt order a 2000 beijing 1.5 NaN b 2001 beijing 1.7 NaN c 2002 beijing 3.6 1.0 d 2001 shanghai 2.4 2.0 e 2002 shanghai 2.9 NaN f 2003 shanghai 3.2 3.0 In [72]: f2.values Out[72]: array([[2000, 'beijing', 1.5, nan], [2001, 'beijing', 1.7, nan], [2002, 'beijing', 3.6, 1.0], [2001, 'shanghai', 2.4, 2.0], [2002, 'shanghai', 2.9, nan], [2003, 'shanghai', 3.2, 3.0]], dtype=object)
最后,DataFrame有一個Series所不具備的方法,那就是info!通過這個方法,可以看到DataFrame的一些整體信息情況:
In [73]: f.info() Out[73]: <class 'pandas.core.frame.DataFrame'> RangeIndex: 6 entries, 0 to 5 Data columns (total 3 columns): state 6 non-null object year 6 non-null int64 pop 6 non-null float64 dtypes: float64(1), int64(1), object(1) memory usage: 224.0+ bytes
