pandas簡介
pandas 是基於NumPy 的一種工具,該工具是為瞭解決資料分析任務而建立的。Pandas 納入了大量庫和一些標準的資料模型,提供了高效地操作大型資料集所需的工具。pandas提供了大量能使我們快速便捷地處理資料的函數和方法。
Series:一維數組,與Numpy中的一維array類似。二者與Python基本的資料結構List也很相近,其區別是:List中的元素可以是不同的資料類型,而Array和Series中則只允許儲存相同的資料類型,這樣可以更有效使用記憶體,提高運算效率。 Time- Series:以時間為索引的Series。 DataFrame:二維的表格型資料結構。很多功能與R中的data.frame類似。可以將DataFrame理解為Series的容器。以下的內容主要以DataFrame為主。 Panel :三維的數組,可以理解為DataFrame的容器。 Series
Series資料結構是一種類似於一維數組的對象,是由一組資料(各種Numpy資料類型)以及一組與之相關的標籤(即索引)組成。 建立Series
多數情況下,Series資料結構是我們直接從DataFrame資料結構中截取出來的,但也可以自己建立Series。文法如下:
s = pd.Series(data, index=index)
其中data可以是不同的內容: 字典 ndarray 標量
index 是軸標籤列表,根據不同的情況傳入的內容有所不同。 由ndarray構建
如果data是ndarray,則索引的長度必須與資料相同。如果沒有入索引,將建立一個值為[0,…,len(data)-1]的索引。
>>> ser = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])>>> sera -0.063364b 0.907505c -0.862125d -0.696292e 0.000751dtype: float64>>> ser.indexIndex(['a', 'b', 'c', 'd', 'e'], dtype='object')>>> ser.index[[True,False,True,True,True]]Index(['a', 'c', 'd', 'e'], dtype='object')>>> pd.Series(np.random.randn(5))0 -0.8540751 -0.1526202 -0.7195423 -0.2191854 1.206630dtype: float64>>> np.random.seed(100)>>> ser=pd.Series(np.random.rand(7))>>> ser0 0.5434051 0.2783692 0.4245183 0.8447764 0.0047195 0.1215696 0.670749dtype: float64>>> import calendar as cal>>> monthNames=[cal.month_name[i] for i in np.arange(1,6)]>>> monthNames['January', 'February', 'March', 'April', 'May']>>> months=pd.Series(np.arange(1,6),index=monthNames);>>> monthsJanuary 1February 2March 3April 4May 5dtype: int32
由字典構建
若data是一個dict,如果傳遞了索引,則索引中與標籤對應的資料中的值將被列出。否則,將從dict的排序鍵構造索引(如果可能)。
>>> d = {'a' : 0., 'b' : 1., 'c' : 2.}>>> pd.Series(d)a 0.0b 1.0c 2.0dtype: float64>>> pd.Series(d, index=['b', 'c', 'd', 'a'])b 1.0c 2.0d NaNa 0.0dtype: float64>>> stockPrices = {'GOOG':1180.97,'FB':62.57,'TWTR': 64.50, 'AMZN':358.69,'AAPL':500.6}>>> stockPriceSeries=pd.Series(stockPrices,index=['GOOG','FB','YHOO','TWTR','AMZN','AAPL'],name='stockPrices')>>> stockPriceSeriesGOOG 1180.97FB 62.57YHOO NaNTWTR 64.50AMZN 358.69AAPL 500.60Name: stockPrices, dtype: float64
註:NaN(not a number)是Pandas的標準缺失資料標記。
>>> stockPriceSeries.name'stockPrices'>>> stockPriceSeries.indexIndex(['GOOG', 'FB', 'YHOO', 'TWTR', 'AMZN', 'AAPL'], dtype='object')>>> dogSeries=pd.Series('chihuahua',index=['breed','countryOfOrigin','name', 'gender'])>>> dogSeriesbreed chihuahuacountryOfOrigin chihuahuaname chihuahuagender chihuahuadtype: object由標量建立
如果資料是標量值,則必須提供索引。將該值重複以匹配索引的長度。
>>> pd.Series(5., index=['a', 'b', 'c', 'd', 'e'])a 5.0b 5.0c 5.0d 5.0e 5.0dtype: float64
除了上述之外,類ndarray的對象傳入後也會轉換為ndarray來建立Series
>>> ser = pd.Series([5,4,2,-3,True])>>> ser0 51 42 23 -34 Truedtype: object>>> ser.valuesarray([5, 4, 2, -3, True], dtype=object)>>> ser.indexRangeIndex(start=0, stop=5, step=1)>>> ser2 = pd.Series([5, 4, 2, -3, True], index=['b', 'e', 'c', 'a', 'd'])>>> ser2b 5e 4c 2a -3d Truedtype: object>>> ser2.indexIndex(['b', 'e', 'c', 'a', 'd'], dtype='object')>>> ser2.valuesarray([5, 4, 2, -3, True], dtype=object)
索引 Series is ndarray-like
Series與ndarray非常相似,是大多數NumPy函數的有效參數。包括像切片這樣的索引操作。
>>> ser = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])>>> sera -0.231872b 0.207976c 0.935808d 0.179578e -0.577162dtype: float64>>> ser[0]-0.2318721969038312>>> ser[:3]a -0.231872b 0.207976c 0.935808dtype: float64>>> ser[ser >0]b 0.207976c 0.935808d 0.179578dtype: float64>>> ser[ser > ser.median()]b 0.207976c 0.935808dtype: float64>>> ser[ser > ser.median()]=1>>> sera -0.231872b 1.000000c 1.000000d 0.179578e -0.577162dtype: float64>>> ser[[4, 3, 1]]e -0.577162d 0.179578b 1.000000dtype: float64>>> np.exp(ser)a 0.793047b 2.718282c 2.718282d 1.196713e 0.561490dtype: float64
Series is dict-like
Series同時也像一個固定大小的dict,可以通過索引標籤擷取和設定值:
>>> ser['a']-0.2318721969038312>>> ser['e'] = 12.>>> sera -0.231872b 1.000000c 1.000000d 0.179578e 12.000000dtype: float64>>> 'e' in serTrue>>> 'f' in serFalse
註:如果引用了未包含的標籤,則會引發異常:
使用get方法,未包含的索引則會返回None,或者特定值。和dict的操作類似。
>>> print(ser.get('f'))None>>> ser.get('f', np.nan)nan向量化操作&標籤對齊
在進行資料分析時,通常沒必要去使用迴圈,而是使用向量化的操作方式。
>>> ser + sera -0.463744b 2.000000c 2.000000d 0.359157e 24.000000dtype: float64>>> ser * 2a -0.463744b 2.000000c 2.000000d 0.359157e 24.000000dtype: float64>>> np.exp(ser)a 0.793047b 2.718282c 2.718282d 1.196713e 162754.791419dtype: float64
Series和ndarray之間的一個主要區別是,Series之間的操作會自動對齊基於標籤的資料。
>>> sera -0.231872b 1.000000c 1.000000d 0.179578e 12.000000dtype: float64>>> ser[1:] + ser[:-1]a NaNb 2.000000c 2.000000d 0.359157e NaNdtype: float64
未對齊Series之間的操作結果將包含所涉及的索引的並集。如果在其中一個Seires中找不到標籤,結果將被標記為NaN。
注意:通常不同索引對象之間的操作的預設結果產生索引的並集,以避免資訊丟失。
因為儘管資料丟失,但擁有索引標籤也可以作為計算的重要訊息。當然也可以選擇通過dropna功能刪除遺失資料的標籤。 屬性
名稱屬性:
>>> s = pd.Series(np.random.randn(5), name='something')>>> s0 -0.5333731 -0.2254022 -0.3149193 0.4229974 -0.438827Name: something, dtype: float64>>> s.name'something'
在多數情況下,series名稱會被自動分配,例如在擷取1D切片的DataFrame時。(後續DataFrame操作將會講解到)
>>> s2 = s.rename("different")>>> s20 -0.5333731 -0.2254022 -0.3149193 0.4229974 -0.438827Name: different, dtype: float64
這裡需要注意的是,s和s2是指向不同的對象的。
通過索引屬性擷取索引
>>> s2.indexRangeIndex(start=0, stop=5, step=1)
索引對象也有一個name屬性
>>> s.index.name = "index_name">>> sindex_name0 -0.5333731 -0.2254022 -0.3149193 0.4229974 -0.438827Name: something, dtype: float64
通過值索引擷取值
>>> s.valuesarray([-0.53337271, -0.22540212, -0.31491934, 0.42299678, -0.43882681])
DataFrame
DataFrame 是可以包含不同類型的列且帶索引的二維資料結構,類似於SQL表,或者Series的字典集合。 建立DataFrame
DataFrame 是被使用最多的Pandas的對象,和Series類似,建立DataFrame時,也接受許多不同類的參數。 From dict of Series or dicts
>>>d = {'one' : pd.Series([1., 2., 3.], index=['a', 'b', 'c']), 'two' : pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}>>>df = pd.DataFrame(d)>>>df
| one |
two |
| a |
1.0 |
| b |
2.0 |
| c |
3.0 |
| d |
NaN |
>>>pd.DataFrame(d, index=['d', 'b', 'a'])
| one |
two |
| d |
NaN |
| b |
2.0 |
| a |
1.0 |
pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three'])
| two |
three |
| d |
4.0 |
| b |
2.0 |
| a |
1.0 |
可以通過訪問索引和列屬性分別訪問行和欄標籤。
>>> df.indexIndex(['a', 'b', 'c', 'd'], dtype='object')>>> df.columnsIndex(['one', 'two'], dtype='object')
From dict of ndarrays / lists
ndarrays必須都是相同的長度。如果傳遞了索引,它的長度也必須與數組一樣長。如果沒有傳遞索引,結果將是range(n),其中n是數組長度。
>>> d = {'one' : [1., 2., 3., 4.],... 'two' : [4., 3., 2., 1.]}>>> pd.DataFrame(d)
| one |
two |
| 0 |
1.0 |
| 1 |
2.0 |
| 2 |
3.0 |
| 3 |
4.0 |
>>> pd.DataFrame(d, index=['a', 'b', 'c', 'd'])
| one |
two |
| a |
1.0 |
| b |
2.0 |
| c |
3.0 |
| d |
4.0 |
From structured or record array
這種情況和從數組的字典集合建立是一樣的。
類型簡略字元參數:
'b' boolean'i' (signed) integer'u' unsigned integer'f' floating-point'c' complex-floating point'm' timedelta'M' datetime'O' (Python) objects'S', 'a' (byte-)string'U' Unicode'V' raw data (void)# 例子:>>> dt = np.dtype('f8') # 64位浮點,注意8為位元組>>> dt = np.dtype('c16') # 128位複數>>> dt = np.dtype("a3, 3u8, (3,4)a10") //3位元組字串、3個64位整型子數組、3*4的10位元組字串數組,注意8為位元組>>> dt = np.dtype((void, 10)) #10位>>> dt = np.dtype((str, 35)) # 35字元字串>>> dt = np.dtype(('U', 10)) # 10字元unicode string>>> dt = np.dtype((np.int32, (2,2))) # 2*2int子數組>>> dt = np.dtype(('S10', 1)) # 10字元字串>>> dt = np.dtype(('i4, (2,3)f8, f4', (2,3))) # 2x3結構子數組# 使用astype,不可直接更改對象的dtype值>>> b = np.array([1., 2., 3., 4.])>>> b.dtypedtype(‘float64‘)>>> c = b.astype(int)>>> carray([1, 2, 3, 4])>>> c.shape(8,)>>> c.dtypedtype(‘int32‘)
>>> data = np.zeros((2,), dtype=[('A', 'i4'),('B', 'f4'),('C', 'a10')])# i4:定義一個big-endian int 4*8=32位的資料類型>>> dataarray([(0, 0., b''), (0, 0., b'')], dtype=[('A', '<i4'), ('B', '<f4'), ('C', 'S10')])>>> data.shape(2,)>>> data[:] = [(1,2.,'Hello'), (2,3.,"World")]>>> dataarray([(1, 2., b'Hello'), (2, 3., b'World')], dtype=[('A', '<i4'), ('B', '<f4'), ('C', 'S10')])>>> pd.DataFrame(data, index=['first', 'second'])
| A |
B |
C |
| first |
1 |
2.0 |
| second |
2 |
3.0 |
>>> pd.DataFrame(data, columns=['C', 'A', 'B'])
| C |
A |
B |
| 0 |
b’Hello’ |
1 |
| 1 |
b’World’ |
2 |
注意:DataFrame和 2-dimensional NumPy ndarray 並不是完全一樣的。
除了以上的構造方法之外還有很多其他的構造方法,但擷取DataFrame的主要方法是讀取表結構的檔案,其他構造方法就不一一列出。
>>> d = {'one' : pd.Series([1., 2