pandas的數據結構介紹
pandas有兩個主要數據結構:Series和DataFrame。
Series
Series是一種類似一維數組的對象,由一組數據和與之相關的索引組成。
創建Series
第一種方式,直接傳入一個列表或元組等序列數據,如果沒有指定索引,會自動創建一個從0到N-1 的整數型索引。
In [3]: s1=pd.Series([1,2,3])
In [4]: s1
Out[4]:
0 1
1 2
2 3
dtype: int64
In [5]: s2=pd.Series(np.arange(4),index=['a','b','c','d'])
In [6]: s2
Out[6]:
a 0
b 1
c 2
d 3
dtype: int64
第二種方式,傳入一個字典,字典的鍵會變成Series的索引,字典的值變成Series的值。但是Series的索引和字典的鍵不同的是,Series的索引之間可以重複。以字典爲參數創建Series對象時,可以傳入索引序列,指定索引順序。如果傳入的索引在字典裏找不到對應的值,Series會自動補充缺失值(NaN)。
In [14]: s_dic={"k1":"v1","k2":"v2","k3":"v3"}
In [15]: s3=pd.Series(s_dic,index=["k3","k2","k1"])
In [16]: s3
Out[16]:
k3 v3
k2 v2
k1 v1
dtype: object
In [22]: s4=pd.Series(s_dic,index=["k3","k2","k4"])
In [23]: s4
Out[23]:
k3 v3
k2 v2
k4 NaN
dtype: object
Series操作
通過values和index屬性獲取數組和索引對象。
In [5]: s1.index
Out[5]: RangeIndex(start=0, stop=3, step=1)
In [7]: s1.values
Out[7]: array([1, 2, 3])
可以使用索引的方式選取Series中的單個或一組值。
In [11]: s2
Out[11]:
a 0
b 1
c 2
d 3
dtype: int64
In [12]: s2['a']
Out[12]: 0
In [13]: s2[['c','d']]
Out[13]:
c 2
d 3
dtype: int64
使用NumPy的函數或者類似NumPy運算會保留索引和值的鏈接。可以把Series對象看作是有序字典。
使用Series的isnull和notnull檢測缺失數據。
In [24]: s4.isnull()
Out[24]:
k3 False
k2 False
k4 True
dtype: bool
In [25]: s4.notnull()
Out[25]:
k3 True
k2 True
k4 False
dtype: bool
Series對象之間的運算會自動將索引對齊,對於不同時存在與兩個Series對象的索引會取並集。
In [26]: s3+s4
Out[26]:
k1 NaN
k2 v2v2
k3 v3v3
k4 NaN
dtype: object
DataFrame
DataFrame(簡記爲DF)是一個表格型的數據,既有行索引又有列索引,也可以看作由Series組成的字典。
創建DF數組
- 傳入一個由等長的列表或NumPy數組組成的字典。DF會自動加上索引,如果傳入列索引,DF會根據傳入的索引序列將列排列。
- 傳入一個嵌套字典,這個字典會被DF解釋爲:外層的鍵作爲列名,內層的鍵會被合併作爲索引,對於內層鍵對不上的值會補上缺失值(NaN)。
- 傳入由Series組成的字典,和上面的方式類似,Series的索引會被DF合併,無法合併的值會被補上缺失值(NaN)。
In [27]: p1=pd.DataFrame({"A":[0,1,2],"B":[3,4,5],"C":[6,7,8]})
In [28]: p1
Out[28]:
A B C
0 0 3 6
1 1 4 7
2 2 5 8
In [29]: p2=pd.DataFrame({"A1":{"a1":1,"a2":2,"a3":3},"B1":{"a1":4,"a2":5,"a3":6},"C1":{"a1":7,"a2"
...: :8,"a3":9}})
In [30]: p2
Out[30]:
A1 B1 C1
a1 1 4 7
a2 2 5 8
a3 3 6 9
In [31]: p3=pd.DataFrame({"s3":s3,"s4":s4})
In [32]: p3
Out[32]:
s3 s4
k1 v1 NaN
k2 v2 v2
k3 v3 v3
k4 NaN NaN
列索引
通過類似字典的形式或屬性可以獲取一個DF的一個列(Series類型)。
In [33]: p1['A']
Out[33]:
0 0
1 1
2 2
Name: A, dtype: int64
In [34]: p1.A
Out[34]:
0 0
1 1
2 2
Name: A, dtype: int64
以索引的方式獲取多個列。
In [38]: p1[['C','B']]
Out[38]:
C B
0 6 3
1 7 4
2 8 5
行索引
使用loc方法以字典的方式獲取單行。
In [52]: p3.loc['k1']
Out[52]:
s3 v1
s4 NaN
Name: k1, dtype: object
使用切片的方式獲取多行。
In [56]: p3[:1]
Out[56]:
s3 s4
k1 v1 NaN
In [57]: p3['k1':]
Out[57]:
s3 s4
k1 v1 NaN
k2 v2 v2
k3 v3 v3
k4 NaN NaN
DF操作
del可以刪除DF的列,只能刪除單列。
In [61]: del p1['A']
In [62]: p1
Out[62]:
B C
0 3 6
1 4 7
2 5 8
通過索引返回的數據是DF的視圖,對視圖的任何修改都會反映到原數據。
In [64]: p1[['B','C']]=1
In [65]: p1
Out[65]:
B C
0 1 1
1 1 1
2 1 1
使用DF的index屬性可以得到DF的行索引對象, columns屬性可以得到DF的列索引對象,values屬性得到一個像ndarray的數組對象。
In [66]: p1.index
Out[66]: RangeIndex(start=0, stop=3, step=1)
In [67]: p1.columns
Out[67]: Index(['B', 'C'], dtype='object')
In [68]: p1.values
Out[68]:
array([[1, 1],
[1, 1],
[1, 1]])
索引對象
Series和DF的Index對象是不可變的。
In [72]: p1.index[0]=1
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-72-1a8caf92d83a> in <module>
----> 1 p1.index[0]=1
~/anaconda3/lib/python3.7/site-packages/pandas/core/indexes/base.py in __setitem__(self, key, value)
3936
3937 def __setitem__(self, key, value):
-> 3938 raise TypeError("Index does not support mutable operations")
3939
3940 def __getitem__(self, key):
TypeError: Index does not support mutable operations
Index對象可以包含重複的標籤
In [74]: p1.index=[1,1,1]
In [75]: p1
Out[75]:
B C
1 1 1
1 1 1
1 1 1
pandas的主要Index對象
類 | 說明 |
---|---|
Index | 最泛化的Index對象,將軸標籤表示爲一個由Python對象組成的NumPy數組 |
Int64Index | 針對整數的特殊Index |
MultiIndex | “層次化”索引對象,表示單個軸上的多層索引。可以看作由元組組成的數組 |
DatetimeIndex | 存儲納秒級時間戳(NumPy的datetime64類型) |
PeriodIndex | 針對Period數據(時間間隔)的特殊Index |
Index的方法和屬性
方法 | 說明 |
---|---|
append | 連接另一個Index對象,產生一個新Index對象 |
diff | 計算差集,並得到一個Index |
intersection | 計算交集 |
union | 計算並集 |
isin | 計算一個指示各值是否都包含在參數集合中的布爾型數組 |
delete | 刪除索引i處的元素,並得到新的Index |
drop | 刪除傳入的值,並得到新的Index |
insert | 將元素插入到索引i處,並得到新的Index |
is_monotonic | 當個元素均大於等於前一個元素時,返回True |
is_unique | 當Index沒有重複值時,返回True |
unique | 計算Index中唯一值的數組 |
基本功能
重新索引
DF和Series對象的index方法可以爲數據重新創建索引,索引值不存在會引入缺失值(NaN)。reindex並不會原地修改原對象的索引,而是返回一個新的對象。
In [102]: s5=pd.Series(data=['v1','v2','v3','v4'],index=list("abcd"))
In [103]: s5.reindex(index=list("abce"))
Out[103]:
a v1
b v2
c v3
e NaN
dtype: object
對於一些有序數據,重新索引可能需要做一些向前或向後插值處理,reindex的method參數即可達到這個目的。
reindex的method選項
參數 | 說明 |
---|---|
ffill或pad | 前向填充(或搬運)值 |
bfill或backfill | 後向填充(或搬運)值 |
DF傳入關鍵字參數axis="columns"修改列索引。
In [106]: p4
Out[106]:
A B C D
a 0 1 2 3
b 4 5 6 7
c 8 9 10 11
In [107]: p4.reindex(['A','B','C','E'],axis="columns")
Out[107]:
A B C E
a 0 1 2 NaN
b 4 5 6 NaN
c 8 9 10 NaN
reindex函數的參數
參數 | 說明 |
---|---|
index | 用作索引的新序列。既可以是Index實例,也可以是其他序列性的Python數據結構。 |
method | 插值(填充)方式 |
fill_value | 在重新索引的過程中,需要引入缺失值時使用的替代值 |
limit | 前向或後向填充式的最大填充量 |
level | 在MultiIndex的指定級別上匹配簡單索引,否則選取其子集 |
copy | 默認爲True,無論如何都複製;如果爲False,則新舊相等就不復制 |
丟棄指定軸上的項
使用Series、DF的drop方法可以刪除任意軸上的索引值。通過關鍵字參數axis指定軸,不傳axis默認爲0軸,axis=1或axis=“columns”指定列。
In [111]: s1
Out[111]:
0 0
1 1
2 2
3 3
dtype: int64
In [113]: s1.drop(1)
Out[113]:
0 0
2 2
3 3
dtype: int64
In [114]: p1
Out[114]:
B C
a 1 1
b 1 1
c 1 1
In [115]: p1.drop(['C'],axis="columns")
Out[115]:
B
a 1
b 1
c 1
drop方法不會在原數組上修改, 會返回一個修改以後的數組。如果現在原數組上修改,需要傳入關鍵字參數inplace=True,傳入inplace=True後不會有返回值。
索引、選取和過濾
Series的索引方式和NumPy數組類似,Series還支持非整數索引,並且Series用切片選取時,其末端是包含的。
In [118]: s2
Out[118]:
a 0
b 1
c 2
d 3
dtype: int64
In [119]: s2['b':'d']
Out[119]:
b 1
c 2
d 3
dtype: int64
用一個值或序列對DF進行索引會得到一個或多個列。使用切片的方式選取行。
In [121]: p4
Out[121]:
A B C D
a 0 1 2 3
b 4 5 6 7
c 8 9 10 11
In [122]: p4['C']
Out[122]:
a 2
b 6
c 10
Name: C, dtype: int64
In [123]: p4[['C','D']]
Out[123]:
C D
a 2 3
b 6 7
c 10 11
In [124]: p4[:2]
Out[124]:
A B C D
a 0 1 2 3
b 4 5 6 7
還可以使用布爾型數組對DF索引。
In [126]: p4[p4>=6]
Out[126]:
A B C D
a NaN NaN NaN NaN
b NaN NaN 6.0 7.0
c 8.0 9.0 10.0 11.0
還可以用loc和iloc(整數索引)行索引選取。
In [127]: p4.loc[['a','b']]
Out[127]:
A B C D
a 0 1 2 3
b 4 5 6 7
In [133]: p4.iloc[[0,1]]
Out[133]:
A B C D
a 0 1 2 3
b 4 5 6 7
DF的索引選項
類型 | 說明 |
---|---|
df[val] | 從DF選取單列或一組列;在特殊情況下比較便利:布爾型數組(過濾行)、切片(行切片)、或布爾型DF |
df.loc[val] | 通過標籤,選取DF的單個行或一組行 |
df.loc[:,val] | 通過標籤選取單列或一組列 |
df.loc[val1,val2] | 通過標籤,同時選取行和列 |
df.iloc[where] | 通過整數位置,從DF選取單個行或一組行 |
df.iloc[:,where] | 通過整數位置,從DF選取單個列或一組列 |
df.iloc[where_i,where_j] | 通過整數行和列,同時選取行和列 |
df.at[label_i,label_j] | 通過行和列標籤,選取單一的變量 |
df.iat[i,j] | 通過行和列的位置(整數),選取單一的標量 |
reindex | 通過標籤選取行或列 |
get_value,set_value | 通過行和列標籤選取單一值 |
算術運算和數據對齊
DF對象間進行算術運算時,會將數據先根據索引對齊後再運算。如果存在不同的索引,結果將是兩個DF索引的並集。
In [138]: p2
Out[138]:
A1 B1 C1
a1 1 4 7
a2 2 5 8
a3 3 6 9
In [139]: p4
Out[139]:
A B C D
a 0 1 2 3
b 4 5 6 7
c 8 9 10 11
In [140]: p2.add(p4,fill_value=0)
Out[140]:
A A1 B B1 C C1 D
a 0.0 NaN 1.0 NaN 2.0 NaN 3.0
a1 NaN 1.0 NaN 4.0 NaN 7.0 NaN
a2 NaN 2.0 NaN 5.0 NaN 8.0 NaN
a3 NaN 3.0 NaN 6.0 NaN 9.0 NaN
b 4.0 NaN 5.0 NaN 6.0 NaN 7.0
c 8.0 NaN 9.0 NaN 10.0 NaN 11.0
自動對齊索引的操作會在索引不重疊的地方補入NaN值,缺失值會在算術運算過程中廣播。有時候運算過程中有NaN值無法計算,這時候需要對NaN值去一個可以計算的值替代NaN,就可以使用關鍵字參數fill_value把NaN值替換成替代值。
用於Series和DF的算術方法
方法 | 說明 |
---|---|
add,radd | 用於加法(+)的方法 |
sub,rsub | 用於減法(-)的方法 |
div,rdiv | 用於除法(/)的方法 |
floordiv,rfloordiv | 用於整除(//)的方法 |
mul,rmul | 用於乘法(*)的方法 |
pow,rpow | 用於指數(**)的方法 |
DF和Series之間的運算
一般情況下DF的列名回合Series的索引對齊後,在行上進行廣播。如果某個索引只存在DF中或Series中找不到,則結果索引會變成DF和Series索引的並集。
In [163]: s2
Out[163]:
a 0
b 1
c 2
d 3
dtype: int64
In [164]: p5
Out[164]:
a b c d
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
In [165]: p5+s2
Out[165]:
a b c d
0 0 2 4 6
1 4 6 8 10
2 8 10 12 14
如果希望DF和Series的運算在列上,需要傳入關鍵字參數axis=1或axis="columns"。
In [172]: s0=p5.loc[0]
In [173]: p5.sub(s0,axis=1)
Out[173]:
a b c d
0 0 0 0 0
1 4 4 4 4
2 8 8 8 8
函數應用的和映射
NumPy的元素級方法也可用於操作pandas對象。
In [11]: p1=pd.DataFrame(np.arange(24).reshape(4,6),index=list('abcd'),columns=list('qwerty'))
In [12]: np.sqrt(p1)
Out[12]:
q w e r t y
a 0.000000 1.000000 1.414214 1.732051 2.000000 2.236068
b 2.449490 2.645751 2.828427 3.000000 3.162278 3.316625
c 3.464102 3.605551 3.741657 3.872983 4.000000 4.123106
d 4.242641 4.358899 4.472136 4.582576 4.690416 4.795832
對於需要將操作作用到DF的行或列上的情況 ,可以使用apply函數。apply默認對DF的列操作。
In [13]: def f(series):
...: return max(series)
...:
In [14]: p1.apply(f)
Out[14]:
q 18
w 19
e 20
r 21
t 22
y 23
dtype: int64
如果傳遞axis=1或axis='columns'參數到apply函數裏,這個函數將在每行執行。
In [16]: p1.apply(f,axis=1)
Out[16]:
a 5
b 11
c 17
d 23
dtype: int64
apply不但可以返回一個標量,還可以返回一個Series。
In [17]: def f1(series):
...: return series[::-1]
...:
In [18]: p1.apply(f1)
Out[18]:
q w e r t y
d 18 19 20 21 22 23
c 12 13 14 15 16 17
b 6 7 8 9 10 11
a 0 1 2 3 4 5
元素級的python函數也可以被使用到DF對象中,需要使用applymap函數。
In [20]: def f3(x):
...: return x%2
...:
In [21]: p1.applymap(f3)
Out[21]:
q w e r t y
a 0 1 0 1 0 1
b 0 1 0 1 0 1
c 0 1 0 1 0 1
d 0 1 0 1 0 1
如果需要用元素級的python函數對Series操作,可以Series的map函數和apply函數。
In [34]: s1
Out[34]:
a 5
b 6
c 7
d 8
e 9
dtype: int64
In [35]: def f4(x):
...: return x+5
...:
In [36]: s1.map(f4)
Out[36]:
a 10
b 11
c 12
d 13
e 14
dtype: int64
In [37]: s1.apply(f4)
Out[37]:
a 10
b 11
c 12
d 13
e 14
dtype: int64
排序和排名
sort_index可以對索引排序,默認按照升序排列索引。
In [8]: p1
Out[8]:
Q W E R T
a 0 1 2 3 4
b 5 6 7 8 9
c 10 11 12 13 14
d 15 16 17 18 19
e 20 21 22 23 24
In [9]: p1.sort_index(axis=1)
Out[9]:
E Q R T W
a 2 0 3 4 1
b 7 5 8 9 6
c 12 10 13 14 11
d 17 15 18 19 16
e 22 20 23 24 21
傳入axis=1或axis="columns"在列上排序,傳入ascending=False按照索引降序排列。
In [12]: p1.sort_index(axis=1,ascending=False)
Out[12]:
W T R Q E
a 1 4 3 0 2
b 6 9 8 5 7
c 11 14 13 10 12
d 16 19 18 15 17
e 21 24 23 20 22
若要按值對Series排序,可以使用sort_values方法。傳入ascending=False倒序排列。
Out[13]:
a 0
b 1
c 2
d 3
e 4
dtype: int64
In [16]: s1.sort_values(ascending=False)
Out[16]:
e 4
d 3
c 2
b 1
a 0
dtype: int64
按值給DF排序,使用sort_values方法,與Series不同的是DF必須傳列名或列名的序列給關鍵字參數by。傳入ascending=False倒序排列。
In [21]: p1
Out[21]:
Q W E R T
a 0 1 2 3 4
b 5 6 7 8 9
c 10 11 12 13 14
d 15 16 17 18 19
e 20 21 22 23 24
In [22]: p1.sort_values(by=['Q','E'],ascending=False)
Out[22]:
Q W E R T
e 20 21 22 23 24
d 15 16 17 18 19
c 10 11 12 13 14
b 5 6 7 8 9
a 0 1 2 3 4
In [23]: p1.sort_values(by='Q')
Out[23]:
Q W E R T
a 0 1 2 3 4
b 5 6 7 8 9
c 10 11 12 13 14
d 15 16 17 18 19
e 20 21 22 23 24
排名會從1開始一直到數組中有效數據的數量。Series和DF的rank方法會給每組數據分配一個平均排名的方式來破壞平級關係。倒序排名需要傳入關鍵字參數ascending=False。
In [28]: s2
Out[28]:
a 1
b 1
c 2
d 2
e 3
f 4
g 5
dtype: int64
In [29]: s2.rank()
Out[29]:
a 1.5
b 1.5
c 3.5
d 3.5
e 5.0
f 6.0
g 7.0
dtype: float64
排名時用於破壞平級關係的方法
方法 | 說明 |
---|---|
'average' | 默認:在相等分組中,爲各個值分配平均排名 |
'min' |
使用整個分組的最小排名 |
'max' | 使用整個分組最大的排名 |
'first' |
按值在原始數據中的出現順序分配排名 |
'dense' |
類似於'min'方法,但是排名總是在組間增加1,而不是組中相同的元素數 |
彙總和計算描述統計
DF的各方法傳入axis參數會axis的軸運算。在一些運算中NA值會自動被過濾掉,除非整個行或列都是NaN,通過skipna選項可以禁用這個功能。
In [33]: p1
Out[33]:
Q W E R T
a 0 1 2 3 4
b 5 6 7 8 9
c 10 11 12 13 14
d 15 16 17 18 19
e 20 21 22 23 24
In [34]: p1.sum(axis=1)
Out[34]:
a 10
b 35
c 60
d 85
e 110
dtype: int64
約簡方法的選項
選項 | 說明 |
---|---|
axis | 約簡的軸。DF的行用0,列用1 |
skipna | 排除缺失值,默認爲True |
level | 如果軸是層次化索引的(MultiIndex),則根據level分組約簡 |
描述和彙總統計
方法 | 說明 |
---|---|
count | 非NA的數量 |
describe | 針對Series和DF各列的計算彙總統計 |
min、max |
計算最小值和最大值 |
argmin、argmax | 計算能夠獲取到最小值或最大值的索引位置(整數索引) |
idxmin、idxmax | 計算能夠獲取到最小值和最大值的索引值 |
quantile | 計算樣本的分位數(0到1) |
sum | 值的總和 |
mean | 值的平均數 |
median | 值的算術中位數(50%分位數) |
mad | 根據平均值計算平均絕對離差 |
var | 樣本值的方差 |
std | 樣本值的標準差 |
skew | 樣本值的偏度(三階矩) |
kurt | 樣本值的峯度(四階矩) |
cumsum | 樣本值的累計和 |
cummin、cummax | 樣本值的累計最小值和累計最大值 |
cumprod | 樣本值的累計積 |
diff | 計算一階差分(對時間序列很有用) |
pct_change | 計算百分數變化 |
相關係數與協方差
Series的corr用來計算兩個Series中重疊的、非NA的、按索引對齊的相關係數,cov計算兩個Series的協方差。
In [59]: s1
Out[59]:
a 0
b 1
c 2
d 3
e 4
dtype: int64
In [60]: s2
Out[60]:
a 1
b 1
c 2
d 2
e 3
f 4
g 5
dtype: int64
In [61]: s1.cov(s2)
Out[61]: 1.25
In [62]: s1.corr(s2)
Out[62]: 0.9449111825230679
DF的corr和cov方法將以DF的形式分別返回完整的相關係數或協方差矩陣。
In [66]: p1
Out[66]:
Q W E R T
a 0 1 2 3 4
b 5 6 7 8 9
c 10 11 12 13 14
d 15 16 17 18 19
e 20 21 22 23 24
In [67]: p1.cov()
Out[67]:
Q W E R T
Q 62.5 62.5 62.5 62.5 62.5
W 62.5 62.5 62.5 62.5 62.5
E 62.5 62.5 62.5 62.5 62.5
R 62.5 62.5 62.5 62.5 62.5
T 62.5 62.5 62.5 62.5 62.5
In [68]: p1.corr()
Out[68]:
Q W E R T
Q 1.0 1.0 1.0 1.0 1.0
W 1.0 1.0 1.0 1.0 1.0
E 1.0 1.0 1.0 1.0 1.0
R 1.0 1.0 1.0 1.0 1.0
T 1.0 1.0 1.0 1.0 1.0
DF的corrwith方法可以計算DF的行和列與另一個Series或DF之間的相關係數。傳入一個Series會返回一個相關係數值Series(針對各列進行計算)。傳入一個DF將會計算按列名配對的相關係數。傳入axis='columns'即可按行計算。無論如何,在計算相關係數之前,所有的數據項都會按標籤對齊。
唯一值、值計數以及成員資格
唯一值、值計數、成員資格方法
方法 | 說明 |
---|---|
isin | 計算一個表示“Series各值是否包含於傳入的值序列中”的布爾型數組 |
match | 計算一個數組中的各值到另一個不同數值的正樹索引;對於數據對其和連接類型的操作十分有用 |
unique | 計算Series中的唯一值數組,按發現的順序返回 |
value_counts | 返回一個Series,其索引爲唯一值,其值爲頻率,按計數值降序排列 |