1、Series
(1)簡介
Series是一種類似于一維數組的對象,它由一組資料(各種NumPy資料類型)以及一組與之相關的資料标簽(即索引)組成。僅由一組資料即可産生最簡單的Series:
obj = pd.Series([4,7,-5,3])
obj
Out[16]:
0 4
1 7
2 -5
3 3
dtype: int64
(2)Series的字元串表現形式為:索引在左,值在右邊。
由于我們沒有為資料指定索引,于是會自動建立一個0到N-1(N為資料的長度)的整數型索引。你可以通過Series的values和index屬性擷取其數組表示形式和索引對象:
obj.values
Out[17]: array([ 4, 7, -5, 3], dtype=int64)
obj.index
Out[19]: RangeIndex(start=0, stop=4, step=1)
(3)通常,我們希望所建立的Series帶有一個可以對各個資料點進行标記的索引:
obj2 = pd.Series([4,7,-5,3],index=['d','F','W','f'])
obj2
Out[4]:
d 4
F 7
W -5
f 3
dtype: int64
obj2.index
Out[5]: Index(['d', 'F', 'W', 'f'], dtype='object')
與普通NumPy數組相比,你可以通過索引的方式選取Series中的單個或一組值:
obj2['d']
Out[7]: 4
obj2['d'] = 6
obj2[['d','F','W']]
Out[9]:
d 6
F 7
W -5
dtype: int64
(4)NumPy數組運算(如根據布爾型數組進行過濾、标量乘法、應用數學函數等)都會保留索引和值之間的連結:
obj2
Out[10]:
d 6
F 7
W -5
f 3
dtype: int64
obj2[obj2 > 0]
Out[11]:
d 6
F 7
f 3
dtype: int64
obj2 * 2
Out[12]:
d 12
F 14
W -10
f 6
dtype: int64
np.exp(obj2)
Out[15]:
d 403.428793
F 1096.633158
W 0.006738
f 20.085537
dtype: float64
(5)可以将Series看成是一個定長的有序字典,因為它是索引值到資料值的一個映射。它可以用在許多原本需要字典參數的函數中:
'b' in obj2
Out[16]: False
'd' in obj2
Out[17]: True
如果資料被存放在一個Python字典中,也可以直接通過這個字典來建立Series:
data = {'a':23,'T':45,'S':34}
obj3 = pd.Series(data)
obj3
Out[22]:
a 23
T 45
S 34
dtype: int64
如果隻傳入一個字典,則結果Series中的索引就是原字典的鍵(有序排列)。
import pandas as pd
sdata = {'sa':23,'sfq':45,'dsa':75}
obj3 = pd.Series(sdata)
print(obj3)
sa 23
sfq 45
dsa 75
dtype: int64
states = ['sa','hh','dsa','sfq']
obj4 = pd.Series(sdata,index = states)
obj4
Out[4]:
sa 23.0
hh NaN
dsa 75.0
sfq 45.0
dtype: float64
在這個例子中,sdata中跟states索引相比對的那3個值會被找出來并放到相應的位置上,但由于“hh”所對應的sdata值找不到,是以其結果就為NaN(即‘not a number’,在pandas中,它用于表示缺失或NA值。在這裡會使用missing或NA表示缺失資料)。pandas的isnull和notnull函數可用于檢測缺失資料:
pd.isnull(obj4)
Out[5]:
sa False
hh True
dsa False
sfq False
dtype: bool
pd.notnull(obj4)
Out[6]:
sa True
hh False
dsa True
sfq True
dtype: bool
Series也有類似的執行個體方法:
obj4.isnull()
Out[7]:
sa False
hh True
dsa False
sfq False
dtype: bool
(6)對于應用而言,Series最重要的一個功能是:它在算術運算中會自動對齊不同索引的資料。
obj3
Out[8]:
sa 23
sfq 45
dsa 75
dtype: int64
obj4
Out[9]:
sa 23.0
hh NaN
dsa 75.0
sfq 45.0
dtype: float64
obj3+obj4
Out[10]:
dsa 150.0
hh NaN
sa 46.0
sfq 90.0
dtype: float64
(7)Series對象本身及其索引都有一個name屬性,該屬性跟pandas其他的關鍵功能關系非常密切:
obj4.name='population'
obj4.index.name = 'state'
obj4
Out[13]:
state
sa 23.0
hh NaN
dsa 75.0
sfq 45.0
Name: population, dtype: float64
Series的索引可以通過指派的方式就地修改:
obj4.index = ['Bob','Ss','sw','ww'] #對的
obj4.index = ['Bob','Ss','sw','ww','fwq'] #錯的,個數與原Series不符
2、DataFrame
(1)DataFrame簡介
DataFrame是一個表格型的資料結構,它含有一組有序的列,每列可以是不同的值類型(數值、字元串、布爾值等)。DataFrame既有行索引也有列索引,它可以被看作由Series組成的字典(共用同一個索引)。跟其他類似的資料結構相比(如R的data.frame),DataFrame中面向行和面向列的操作基本上是平衡的。其實,DataFrame中的資料是以一個或多個二維塊存放的(而不是清單、字典或别的一維資料結構)。
(2)建構DataFrame
建構DataFrame的方法有很多,最常用的一種是直接傳入一個由等長清單或NumPy數組組成的字典:
from pandas import Series,DataFrame
data = {'state':['a','b','c','d','e'],
'year':[200,341,3432,23,43],
'pop':[1.5,2.4,2.3,4.4,5.5]}
frame = DataFrame(data)
結果DataFrame會自動加上索引(跟Series一樣),且全部列會被有序排列:
frame
Out[4]:
state year pop
0 a 200 1.5
1 b 341 2.4
2 c 3432 2.3
3 d 23 4.4
4 e 43 5.5
如果指定了列序列,則DataFrame的列就會按照指定順序進行排列:
DataFrame(data,columns=['year','state','pop'])
Out[5]:
year state pop
0 200 a 1.5
1 341 b 2.4
2 3432 c 2.3
3 23 d 4.4
4 43 e 5.5
(3)跟Series一樣,如果傳入的列在資料中找不到,就會産生NA值:
frame2 = DataFrame(data,columns=['year','state','pop','debt'],index=['one','two','three','four','five'])
frame2
Out[7]:
year state pop debt
one 200 a 1.5 NaN
two 341 b 2.4 NaN
three 3432 c 2.3 NaN
four 23 d 4.4 NaN
five 43 e 5.5 NaN
frame2.columns
Out[8]: Index(['year', 'state', 'pop', 'debt'], dtype='object')
(4)通過類似字典标記的方式或屬性的方式,可以将DataFrame的列擷取為一個Series:
frame2.year
Out[9]:
one 200
two 341
three 3432
four 23
five 43
Name: year, dtype: int64
frame2['state']
Out[10]:
one a
two b
three c
four d
five e
Name: state, dtype: object
注意,傳回的Series擁有原DataFrame相同的索引,且其name屬性也已經被相應地設定好了。
行也可以通過位置或名稱的方式進行擷取,比如用索引字段ix,沒有iy這個東東!
frame2.ix['three']
Out[11]:
year 3432
state c
pop 2.3
debt NaN
Name: three, dtype: object
(5)列可以通過指派的方式進行修改,例如,我們可以給那個空的“debt”列賦上一個标量值或一組值:
frame2['debt']=2
frame2
Out[13]:
year state pop debt
one 200 a 1.5 2
two 341 b 2.4 2
three 3432 c 2.3 2
four 23 d 4.4 2
five 43 e 5.5 2
import numpy as np
frame2['debt'] = np.arange(5.)
frame2
Out[16]:
year state pop debt
one 200 a 1.5 0.0
two 341 b 2.4 1.0
three 3432 c 2.3 2.0
four 23 d 4.4 3.0
five 43 e 5.5 4.0
将清單或數組指派給某個列時,其長度必須跟DataFrame的長度相比對。如果指派的是一個Series,就會精确比對DataFrame的長度相比對。如果指派的是一個Series,就會精确比對DataFrame的索引,所有的空位都将被填上缺失值:
val = Series([-1.2,-1.5,2.3],index=['two','t','five']) #如果設定的index中,存在和原DataFrame不相同的索引,會忽略
frame2['debt'] = val
frame2
Out[17]:
year state pop debt
one 200 a 1.5 NaN
two 341 b 2.4 -1.2
three 3432 c 2.3 NaN
four 23 d 4.4 NaN
five 43 e 5.5 2.3
為不存在的列指派會建立出一個新列。關鍵字del用于删除列:
frame2['eastern'] = frame2.state=='Oh'
frame2
Out[19]:
year state pop debt eastern
one 200 a 1.5 NaN False
two 341 b 2.4 -1.2 False
three 3432 c 2.3 NaN False
four 23 d 4.4 NaN False
five 43 e 5.5 2.3 False
del frame2['eastern']
frame2.columns
Out[20]: Index(['year', 'state', 'pop', 'debt'], dtype='object')
通過索引方式傳回的列隻是相應資料的視圖而已,并不是副本。是以對傳回的Series所做的任何就地修改全都會反映到源DataFrame上。通過Series的copy方法即可顯式地複制列。
(6)嵌套字典(字典中的字典)
pop = {'aa':{100:3,324:21},'bb':{200:1.5,201:1.7,203:4.5}}
如果将它傳給DataFrame,則 外層字典的鍵作為列,内層鍵則作為行索引:
frame = DataFrame(pop)
frame
Out[21]:
aa bb
100 3.0 NaN
200 NaN 1.5
201 NaN 1.7
203 NaN 4.5
324 21.0 NaN
當然,可以對該結果進行轉置:
frame.T
Out[22]:
100 200 201 203 324
aa 3.0 NaN NaN NaN 21.0
bb NaN 1.5 1.7 4.5 NaN
DataFrame(pop,index=[100,200,201,203,204])
Out[23]:
aa bb
100 3.0 NaN
200 NaN 1.5
201 NaN 1.7
203 NaN 4.5
204 NaN NaN
DataFrame(pop,columns=['aa','bb'])
Out[25]:
aa bb
100 3.0 NaN
200 NaN 1.5
201 NaN 1.7
203 NaN 4.5
324 21.0 NaN
由Series組成的字典差不多也是一樣的用法:
pdata = {'aa':frame['aa'][:-1],
'cc':frame['bb'][:2]}
DataFrame(pdata)
Out[27]:
aa cc
100 3.0 NaN
200 NaN 1.5
201 NaN NaN
203 NaN NaN
二維ndarray | 資料矩陣,還可以傳入行标和列标 |
由數組、清單或元組組成的字典 | 每個序列會變成DataFrame的一列。所有序列的長度必須相同 |
NumPy的結構化/記錄數組 | 類似于“由數組組成的字典” |
由Series組成的字典 | 每個Series會成為一列。如果沒有顯示指定索引,則各Series的索引會被合并成結果的行索引 |
由字典組成的字典 | 各内層字典會成為一列。鍵會被合并成結果的行索引,跟“由Series組成的字典”的情況一樣 |
字典或Series的清單 | 各項将會成為DataFrame的一行。字典鍵或Series索引的并集将會成為DataFrame的列标 |
由清單或元組組成的清單 | 類似于“二維ndarray” |
另一個DataFrame | 該DataFrame的索引将會被沿用,除非顯式指定了其他索引 |
NumPy的MaskedArray | 類似于“二維ndarray”的情況,隻是掩碼值在結果DataFrame會變成NA/缺失值 |
如果設定了DataFrame的index和columns的names屬性,則這些資訊也會被顯示出來:
frame.index.name = 'year'
frame.columns.name = 'state'
frame
Out[4]:
state aa bb
year
100 3.0 NaN
200 NaN 1.5
201 NaN 1.7
203 NaN 4.5
324 21.0 NaN
跟Series一樣,values屬性也會以二維ndarray的形式傳回DataFrame中的資料:
frame.values
Out[5]:
array([[ 3. , nan],
[ nan, 1.5],
[ nan, 1.7],
[ nan, 4.5],
[21. , nan]])
如果DataFrame各列的資料類型不同,則值數組的資料類型就會選用能相容所有列的資料類型。
3、索引對象
pandas的索引對象負責管理軸标簽和其他中繼資料(比如軸名稱等)。建構Series或DataFrame時,所用到的任何數組或其他序列的标簽都會被轉換成一個Index:
obj = Series(range(3),index=['a','b','c'])
index = obj.index
index
Out[17]: Index(['a', 'b', 'c'], dtype='object')
index[1:]
Out[26]: Index(['b', 'c'], dtype='object')
Index對象是不可修改的(immutable),是以使用者不能對其進行修改。這樣才能使Index對象在多個資料結構之間安全共享:
index0 = pd.Index(np.arange(3))
obj2 = Series([2,3,4],index=index0)
obj2.index is index0
Out[25]: True
Index甚至可以被繼承進而實作特别的軸索引功能