一. 索引對象
在之前介紹的Series和DataFrame結(jié)構(gòu)中阵苇,我們已經(jīng)接觸到了索引對象,它是pandas的重要組成部分物臂。pandas定義了Index類來表示基本索引對象蛙讥,想要獲取數(shù)據(jù)的索引對象候醒,只需調(diào)用數(shù)據(jù)的index屬性即可index=df.index
。
這里有幾點(diǎn)需要強(qiáng)調(diào):
1. 索引是可以重復(fù)的
雖然很多時(shí)候都要求索引唯一哼绑,但這并不是強(qiáng)制的岩馍。我們可以使用索引對象的is_unique屬性,來判斷索引是否唯一抖韩。
d=DF({'A':[1,2,3,4,5],'B':[6,7,8,9,10]},index=[1,1,2,2,3])
print(d)
print(d.index.is_unique)
Out[1]:
A B
1 1 6
1 2 7
2 3 8
2 4 9
3 5 10
False
2. 索引一旦確立就不可以再修改
索引是不可以修改的蛀恩,但是可以全部重置。怎么理解呢茂浮?就是不可以修改索引的任何一部分双谆,但是可以全部替換掉。索引的不可修改性十分重要席揽,因?yàn)橹挥羞@樣才能保證數(shù)據(jù)結(jié)構(gòu)間安全共享(eg.自動(dòng)對齊)顽馋。
那么如何替換掉所有的索引呢?有4種方法:
reset_index:替換舊索引幌羞,新的索引按0,1,2,3,4.....遞增
Series/DataFrame.reset_index(level=None, drop=False, inplace=False, col_level=0, col_fill=' ')
level:要?jiǎng)h除哪一級(jí)索引(多重索引)
drop:False則將舊索引變成列寸谜,True則刪除舊索引
inplace:是否在原數(shù)據(jù)中修改
col_level:如果列是多重標(biāo)簽,舊索引名插入到哪一層
col_fill:如果列是多重標(biāo)簽新翎,剩下的標(biāo)簽名是什么set_index :將dataframe其中某列作為索引
DataFrame.set_index(keys, drop=True, append=False, inplace=False, verify_integrity=False)
keys:要置為索引的列標(biāo)簽(列表)
drop:True設(shè)置為新索引的列被刪除程帕,F(xiàn)alse被保留
append:True保留原索引,keys中的列變?yōu)橄乱患?jí)索引
inplace:是否在原數(shù)據(jù)中修改
verify_integrity:True檢測新的索引是否重復(fù)地啰,重復(fù)則報(bào)錯(cuò)愁拭。reindex:設(shè)置新索引, 新索引中不存在對應(yīng)的數(shù)據(jù),則將數(shù)據(jù)設(shè)為nan
reindex更多的不是修改pandas對象的索引亏吝,而只是修改索引的順序岭埠,如果修改的索引不存在就會(huì)使用默認(rèn)的None代替此行。
Series/Panel/DataFrame.reindex(labels=None, index=None, columns=None, axis=None, method=None, copy=True, level=None, fill_value=nan, limit=None, tolerance=None)
前4個(gè)參數(shù):傳入新的索引數(shù)組,說明要修改行索引還是列標(biāo)簽惜论。
舉個(gè)例子:我們看到许赃,舊索引是[0,1,2,3,4],替換的新索引是[1,2,3,4,5,6]馆类,2個(gè)索引的交集被保留下來混聊,新索引中不存在的標(biāo)簽0被刪除,同時(shí)引入了新索引中的標(biāo)簽[5,6]乾巧,數(shù)據(jù)為NAN
d=DF({'A':[1,1,3,4,5],'B':[6,7,8,9,10]})
print(d)
d=d.reindex([1,2,3,4,5,6])
print(d)
Out[2]:
A B
0 1 6
1 1 7
2 3 8
3 4 9
4 5 10
A B
1 1.0 7.0
2 3.0 8.0
3 4.0 9.0
4 5.0 10.0
5 NaN NaN
6 NaN NaN
method:新引入的索引標(biāo)簽的數(shù)據(jù)填充方法句喜。pad / ffill向前保持一致;backfill / bfill向后保持一致沟于;nearest和最近保持一致咳胃。
d=DF({'A':[1,1,3,4,5],'B':[6,7,8,9,10]},index=[0,1,3,4,5])
print(d)
d=d.reindex([1,2,3,4,5,6],method='pad')
print(d)
Out[3]:
A B
0 1 6
1 1 7
3 3 8
4 4 9
5 5 10
A B
1 1 7
2 1 7
3 3 8
4 4 9
5 5 10
6 5 10
fill_value:新引入的索引標(biāo)簽的數(shù)據(jù)填充值。
- 直接賦值:直接將索引賦值給index變量旷太,長度要和數(shù)據(jù)一致
data=pd.DataFrame({'A':[1,2,],'B':[0,0,],'C':[7,8]})
data.index=['a','b']
Out:
A B C
a 1 0 7
b 2 0 8
二. 多重索引對象
多重索引(hierarchical indexing)是pandas的一個(gè)重要的功能展懈,它可以在一個(gè)軸上有多個(gè)(兩個(gè)以上)的索引,這就表示著供璧,它能夠以低維度形式來表示高維度的數(shù)據(jù)存崖。注意,這里我說的是軸嗜傅,這就意味著金句,多重索引可以是行索引,也可以是列索引吕嘀。
1. 創(chuàng)建多重行索引
-
顯式創(chuàng)建多重行索引:利用pandas.MultiIndex對象
MultiIndex是pandas中標(biāo)準(zhǔn)的多重索引類违寞,使用時(shí)只需將該對象賦值給基本結(jié)構(gòu)的index參數(shù)即可。那么偶房,我們?nèi)绾蝿?chuàng)建這個(gè)MultiIndex對象呢趁曼?主要有以下幾種方法:
- 從數(shù)組構(gòu)建:
MultiIndex.from_arrays(arrays, sortorder=None, names=None)
- 從元組構(gòu)建:
MultiIndex.from_tuples(tuples, sortorder=None, names=None)
- 從數(shù)組交差配對構(gòu)建:
MultiIndex.from_product(iterables, sortorder=None, names=None)
其中,第一個(gè)參數(shù)是索引結(jié)構(gòu)棕洋,names是索引名挡闰,舉個(gè)例子:
#注意觀察從數(shù)組構(gòu)建,與從交叉迭代構(gòu)建的區(qū)別j獭摄悯!
arr=[['a','b'],[1,2]]
ind=pd.MultiIndex.from_arrays(arr,names=['alpha','number'])
data=pd.DataFrame({'A':[1,2,],'B':[0,0,],'C':[7,8]},index=ind)
print(data)
Out:
A B C
alpha number
a 1 1 0 7
b 2 2 0 8
arr=[['a','b'],[1,2]]
ind=pd.MultiIndex.from_product(arr,names=['alpha','number'])#交叉迭代
data=pd.DataFrame({'A':[1,2,3,4],'B':[0,0,5,6],'C':[7,8,0,0]},index=ind)
print(data)
Out:
A B C
alpha number
a 1 1 0 7
2 2 0 8
b 1 3 5 0
2 4 6 0
- 隱式創(chuàng)建多重行索引
- 利用set_index()函數(shù)添加索引
更多的時(shí)候我們不是自己創(chuàng)建數(shù)據(jù)結(jié)構(gòu),而是從文件中讀取數(shù)據(jù)愧捕,然后自己設(shè)定索引列奢驯。還記得之前介紹set_index()函數(shù)的時(shí)候,提到過一個(gè)參數(shù)append次绘,它被設(shè)置為True的時(shí)候瘪阁,原索引不變撒遣,指定列被設(shè)置為原索引的下一級(jí)索引,我們可以利用這個(gè)特點(diǎn)管跺,構(gòu)造多重索引义黎。
舉個(gè)例子:可以看到,栗子中的B列變成了2級(jí)索引豁跑。
data=pd.DataFrame({'A':[1,2,3],'B':[0,0,4],'C':[7,8,5]})
data.index.name='index'
data.set_index(keys=['B'],append=True,inplace=True)
print(data)
Out:
A C
index B
0 0 1 7
1 0 2 8
2 4 3 5
- 構(gòu)造數(shù)據(jù)時(shí)廉涕,直接傳入多個(gè)索引數(shù)組
直接上栗子,這個(gè)很好理解
data=pd.DataFrame({'A':[1,2,3],'B':[0,0,4],'C':[7,8,5]},index=[['a','a','b'],[1,2,3]])
print(data)
Out:
A B C
a 1 1 0 7
2 2 0 8
b 3 3 4 5
2. 創(chuàng)建多重列索引
直接使用MultiIndex對象顯示創(chuàng)建多重列索引艇拍。
arr=[['A','A','C'],['a','b','a']]
ind=pd.MultiIndex.from_arrays(arr,names=['letter','number'])
data=pd.DataFrame([[1,2,3],[0,0,4],[7,8,5]],columns=ind)
print(data)
Out:
letter A C
number a b a
0 1 2 3
1 0 0 4
2 7 8 5
3.多重索引對象下的索引操作
之前講pandas基本數(shù)據(jù)結(jié)構(gòu)的時(shí)候火的,我們提到,常用的索引操作方式主要有以下幾種:
- 點(diǎn)字符 :訪問列
- 中括號(hào) [ ]
- loc[ ] :基于標(biāo)簽索引淑倾,可以批量選取
- iloc[ ] :基于位置索引,可以批量選取
- at[ ] : 基于標(biāo)簽索引征椒,只能選取一個(gè)元素
- iat[ ] : 基于位置索引娇哆,只能選取一個(gè)元素
在多重索引中也同樣適用,而且使用方法基本雷同勃救。這個(gè)時(shí)候可能會(huì)有人問碍讨,如何選擇子索引呢?這個(gè)很簡單蒙秒,下面我們一起來看:
示例數(shù)據(jù):
A C
a b a
1 i 1 2 3
ii 0 0 4
3 iii 7 8 5
- 索引元組:如果想要選取最外層索引勃黍,和普通單索引對象沒區(qū)別。若是想要選取多層索引晕讲,就要使用元組的括號(hào)把索引包裹起來覆获,我們看個(gè)栗子。
#只選最外層
print(data['A'])
Out:
a b
1 i 1 2
ii 0 0
3 iii 7 8
#選列多層
print(data[ ('A','a') ])
Out:
1 i 1
ii 0
3 iii 7
#行列都來個(gè)多層
print(data.loc[ (1,'ii') , ('A','a') ])
Out:
0
2.切片
多重索引也支持切片操作瓢省,只需用元組括號(hào)包裹多層的索引就可以了弄息。
print(data.loc[(1,'ii'):,('A','a')])
Out:
1 ii 0
3 iii 7
另外,slice(None), 是Python中的切片操作勤婚,這里用來選擇任意的id摹量,要注意!不能使用‘:’來指定任意index馒胆,‘:’用來指定dataframe任意的列
print(data.loc[(slice(None),'ii')])
Out:
A C
a b a
ii 0 0 4
3.點(diǎn)字符
多重索引也支持點(diǎn)字符訪問列缨称,可以每一級(jí)使用一個(gè)點(diǎn)字符。
print(data.A.a)
Out:
1 i 1
ii 0
3 iii 7
4.刪除多重索引
使用pandas.MultiIndex.droplevel()
函數(shù)祝迂,可以刪除指定level的行索引睦尽。
data.index=data.index.droplevel(0)
print(data)
Out:
A C
a b a
i 1 2 3
ii 0 0 4
iii 7 8 5