Python3 pandas.MultiIndex 概述
- 層次化索引(hierarchical indexing)在一個軸上擁有多個(兩個以上)索引級別,使用戶能以低維度形式處理高維度數(shù)據(jù)椒功。
- levels:每個等級上軸標簽的唯一值
- labels:以整數(shù)來表示每個level上標簽的位置
- sortorder:按照指定level上的標簽名稱的字典順序進行排序(可選參數(shù))
- names:index level的名稱
- copy:布爾值,默認為False翩迈。是否拷貝元數(shù)據(jù)產(chǎn)生新的對象
- verify_integrity:布爾值,默認為Ture盔夜。檢查levels/labels是否持續(xù)有效
入門級demo學習
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2019-06-13 10:11
# @Author : LiYahui
# @Description : python multiindex demo
import pandas as pd
import numpy as np
data = pd.Series(np.random.randn(10),
index=[['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd', 'd'],
[1, 2, 3, 1, 2, 3, 1, 2, 2, 3]])
print("----------print data---------------")
print(data)
'''
a 1 -0.902378
2 -1.512923
3 -1.082350
b 1 -0.900975
2 -1.723988
3 -0.791613
c 1 -1.631530
2 2.290227
d 2 0.530892
3 1.199453
dtype: float64
'''
print("----------print data.index-------------")
print(data.index)
'''
MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]],
codes=[[0, 0, 0, 1, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 1, 2]])
'''
print("----------print data.index.levels[0]----------------")
print(data.index.levels[0])
'''
Index(['a', 'b', 'c', 'd'], dtype='object')
'''
print("----------print data.index.levels[1]----------------")
print(data.index.levels[1])
'''
Int64Index([1, 2, 3], dtype='int64')
'''
- 總結(jié)分析如下:
- level中的唯一標簽值集合分別為[‘a(chǎn)’, ‘b’, ‘c’, ‘d’]和[1, 2, 3]帽馋。
- data.index.levels[0]上的標簽abcd對應(yīng)的索引為0123。data.index.levels[1]上的標簽123對應(yīng)的索引為012比吭。
- 外層level的label值[0, 0, 0, 1, 1, 1, 2, 2, 3, 3]表示對應(yīng)的標簽值分別出現(xiàn)幾次:a和b為3次绽族,c和d為2次
- 內(nèi)層level的label值[0, 1, 2, 0, 1, 2, 0, 1, 1, 2]按個數(shù)與外層label相對應(yīng)。例如:外層a出現(xiàn)3次衩藤,則內(nèi)層label的前3個值與a相對應(yīng)吧慢,這三個索引值為0,1赏表,2检诗,分別對應(yīng)1匈仗,2,3逢慌。
MultiIndex創(chuàng)建的方式
第一種
- 我們在創(chuàng)建Series或DataFrame時悠轩,可以通過給index(columns)參數(shù)傳遞多維數(shù)組,進而構(gòu)建多維索引攻泼』鸺埽【數(shù)組中每個維度對應(yīng)位置的元素,組成每個索引值】
- 多維索引的也可以設(shè)置名稱(names屬性)忙菠,屬性的值為一維數(shù)組何鸡,元素的個數(shù)需要與索引的層數(shù)相同(每層索引都需要具有一個名稱)。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2019-06-13 10:52
# @Author : LiYahui
# @Description : MultiIndex demo
import pandas as pd
import numpy as np
# 創(chuàng)建多層索引的第一種方式
# 創(chuàng)建Series對象牛欢,具有單層索引骡男。
s1 = pd.Series([1, 2, 3], index=["a", "b", "c"])
print(s1)
'''
a 1
b 2
c 3
dtype: int64
'''
# 創(chuàng)建多層索引。多層索引需要一個二維的數(shù)組傍睹,每個元素(一維數(shù)組)來指定每個層級的索引隔盛。順序
# 由高層(左邊)到底層(右邊)。
s2 = pd.Series([1, 2, 3, 4], index=[["a", "a", "b", "b"], ["c", "d", "e", "f"], ["m", "m", "k", "t"]])
print(s2)
'''
a c m 1
d m 2
b e k 3
f t 4
dtype: int64
'''
print("-------df--------")
df = pd.DataFrame(np.random.random(size=(4, 4)), index=[["上半年", "上半年", "下半年", "下半年"],
["第一季度", "第二季度", "第三季度", "第四季度"]],
columns=[["水果", "水果", "蔬菜", "蔬菜"], ["蘋果", "葡萄", "白菜", "蘿卜"]])
print(df)
'''
水果 蔬菜
蘋果 葡萄 白菜 蘿卜
上半年 第一季度 0.356637 0.358602 0.402864 0.550727
第二季度 0.963110 0.010293 0.378511 0.051015
下半年 第三季度 0.098882 0.394281 0.554502 0.676566
第四季度 0.828770 0.506423 0.681128 0.542206
'''
print(df.index)
'''
MultiIndex(levels=[['上半年', '下半年'], ['第一季度', '第三季度', '第二季度', '第四季度']],
codes=[[0, 0, 1, 1], [0, 2, 1, 3]])
'''
print(df.columns)
'''
MultiIndex(levels=[['水果', '蔬菜'], ['白菜', '蘋果', '蘿卜', '葡萄']],
codes=[[0, 0, 1, 1], [1, 3, 0, 2]])
'''
# 如果是單層索引拾稳,我們可以通過索引對象的name屬性來設(shè)置索引的名稱吮炕。
s2 = pd.Series([1, 2, 3, 4], index=["a", "b", "c", "d"])
s2.index.name = "索引名稱"
print("--------s2----------")
print(s2)
'''
索引名稱
a 1
b 2
c 3
d 4
dtype: int64
'''
# 對于多層索引膊夹,也可以設(shè)置索引的名稱,此時掐隐,設(shè)置名稱的屬性為names(通過一維數(shù)組來設(shè)置)跨扮。
# 每層索引都具有名稱。
# 修改df的索引
df.index.names = ["年度", "季度"]
df.columns.names = ["大類別", "小類別"]
print(df)
'''
大類別 水果 蔬菜
小類別 蘋果 葡萄 白菜 蘿卜
年度 季度
上半年 第一季度 0.078253 0.961293 0.770540 0.267522
第二季度 0.845138 0.239290 0.208779 0.347256
下半年 第三季度 0.869534 0.148100 0.046563 0.753004
第四季度 0.926966 0.305344 0.379041 0.467218
'''
第二種
- 我們可以通過MultiIndex類的相關(guān)方法吩抓,預先創(chuàng)建一個MultiIndex對象,然后作為Series與DataFrame中的index(或columns)參數(shù)值。同時传趾,可以通過names參數(shù)指定多層索引的名稱。
- from_arrays:接收一個多維數(shù)組參數(shù)泥技,高維指定高層索引浆兰,低維指定底層索引。
- from_tuples:接收一個元組的列表珊豹,每個元組指定每個索引(高維索引簸呈,低維索引)。
- from_product:接收一個可迭代對象的列表店茶,根據(jù)多個可迭代對象元素的笛卡爾積進行創(chuàng)建索引蜕便。
from_product相對于前兩個方法而言,實現(xiàn)相對簡單贩幻,但是轿腺,也存在局限两嘴。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2019-06-13 11:13
# @Author : LiYahui
# @Description :multiindex demo
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.random(size=(4, 4)), index=[["上半年", "上半年", "下半年", "下半年"],
["第一季度", "第二季度", "第三季度", "第四季度"]],
columns=[["水果", "水果", "蔬菜", "蔬菜"], ["蘋果", "葡萄", "白菜", "蘿卜"]])
print(df)
'''
水果 蔬菜
蘋果 葡萄 白菜 蘿卜
上半年 第一季度 0.645330 0.408014 0.121088 0.106337
第二季度 0.671892 0.212711 0.792635 0.031329
下半年 第三季度 0.063841 0.513930 0.342464 0.885220
第四季度 0.091936 0.745129 0.905859 0.760001
'''
# 創(chuàng)建多層索引的第二種方式
# ------------from_arrays-------------------
# from_arrays 參數(shù)為一個二維數(shù)組,每個元素(一維數(shù)組)來分別制定每層索引的內(nèi)容族壳。
mindex_arrsys = pd.MultiIndex.from_arrays([["上半年", "上半年", "下半年", "下半年"], ["1季度", "2季度", "3季度", "4季度"]])
df2 = pd.DataFrame(np.random.random(size=(4, 4)), index=mindex_arrsys)
print(df2)
'''
0 1 2 3
上半年 1季度 0.578044 0.636138 0.497155 0.389131
2季度 0.195453 0.623200 0.769118 0.637451
下半年 3季度 0.562462 0.629691 0.684193 0.981682
4季度 0.873525 0.489149 0.883518 0.252548
'''
# ------------from_tuples-------------------
# from_tuples 參數(shù)為一個(嵌套的)可迭代對象,元素為元祖類型憔辫。元祖的格式為:(高層索引內(nèi)容仿荆,低層索引內(nèi)容)
mindex_tuples = pd.MultiIndex.from_tuples([("上半年", "1季度"), ("上半年", "2季度"), ("下半年", "3季度"), ("下半年", "4季度")])
df3 = pd.DataFrame(np.random.random(size=(4, 4)), index=mindex_tuples)
print(df3)
'''
0 1 2 3
上半年 1季度 0.843825 0.242793 0.132814 0.024581
2季度 0.404961 0.870869 0.134744 0.220976
下半年 3季度 0.196361 0.074073 0.588173 0.181438
4季度 0.936489 0.246351 0.941209 0.144210
'''
# ------------from_products-------------------
# 使用笛卡爾積的方式來創(chuàng)建多層索引贰您。參數(shù)為嵌套的可迭代對象。結(jié)果為使用每個一維數(shù)組中的元素與其他一維數(shù)組中的元素來生成
# 索引內(nèi)容赖歌。
mindex_products = pd.MultiIndex.from_product([["a", "b"], ["c", "d"]], names=["outer", "inner"])
print(mindex_products)
'''
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
codes=[[0, 0, 1, 1], [0, 1, 0, 1]],
names=['outer', 'inner'])
'''
print(pd.MultiIndex.from_arrays([["a", "a", "b", "b"], ["c", "d", "c", "d"]]))
'''
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
codes=[[0, 0, 1, 1], [0, 1, 0, 1]])
'''
print(pd.MultiIndex.from_arrays([["a", "a", "b"], ["c", "d", "d"]]))
'''
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
codes=[[0, 0, 1], [0, 1, 1]])
'''
# MultiIndex的三個類方法枉圃,可以創(chuàng)建MultiIndex類型的對象。三種方式相比庐冯,第三種方式(笛卡爾積的方式)更加簡便孽亲,但是,
# 其也具有一定的局限:兩兩組合必須都存在展父,否則返劲,就不能使用這種方式。
# 在創(chuàng)建多層索引對象時栖茉,可以通過names參數(shù)來指定每個索引層級的名稱篮绿。
df4 = pd.DataFrame(np.random.random(size=(4, 4)),index=mindex_products)
print(df4)
print(df4.index)
'''
0 1 2 3
outer inner
a c 0.213218 0.561547 0.224423 0.764169
d 0.296970 0.557486 0.809295 0.300886
b c 0.134809 0.111138 0.619714 0.223240
d 0.707181 0.872395 0.800698 0.676075
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
codes=[[0, 0, 1, 1], [0, 1, 0, 1]],
names=['outer', 'inner'])
'''
# 還有第三種方式(因為繁瑣,所以不用)吕漂,最直接的方式:
mindex = pd.MultiIndex(levels=[['a', 'b'], ['c', 'd']],
codes=[[0, 0, 1, 1], [0, 1, 0, 1]],
names=['outer', 'inner'])
print(mindex)
'''
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
codes=[[0, 0, 1, 1], [0, 1, 0, 1]],
names=['outer', 'inner'])
'''
多層索引操作
- 對于多層索引亲配,同樣也支持單層索引的相關(guān)操作,例如惶凝,索引元素吼虎,切片,索引數(shù)組選擇元素等苍鲜。我們也可以根據(jù)多級索引思灰,按層次逐級選擇元素。
- 多層索引的優(yōu)勢:通過創(chuàng)建多層索引混滔,我們就可以使用高層次的索引洒疚,來操作整個索引組的數(shù)據(jù)。
- 格式:
- s[操作]
- s.loc[操作]
- s.iloc[操作]
其中坯屿,操作可以是索引油湖,切片,數(shù)組索引领跛,布爾索引肺魁。
Series多層索引
- 通過loc(標簽索引)操作,可以通過多層索引隔节,獲取該索引所對應(yīng)的一組值鹅经。
- 通過iloc(位置索引)操作寂呛,會獲取對應(yīng)位置的元素值(與是否多層索引無關(guān))贷痪。
- 通過s[操作]的行為有些詭異劫拢,建議不用舱沧。
- 對于索引(單級)偶洋,首先按照標簽選擇玄窝,如果標簽不存在,則按照位置選擇帽氓。
- 對于多級索引黎休,則按照標簽進行選擇势腮。
- 對于切片嫉鲸,如果提供的是整數(shù)歹啼,則按照位置選擇狸眼,否則按照標簽選擇拓萌。
- 對于數(shù)組索引, 如果數(shù)組元素都是整數(shù)微王,則根據(jù)位置進行索引,否則钧大,根據(jù)標簽進行索引(此時如果標簽不存在啊央,也不會出現(xiàn)錯誤)瓜饥。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2019-06-13 11:28
# @Author : LiYahui
# @Description : 位置選擇
import pandas as pd
s = pd.Series([1, 2, 3, 4], index=[["a", "a", "b", "b"], ["c", "d", "e", "f"]])
print(s)
'''
a c 1
d 2
b e 3
f 4
dtype: int64
'''
# 多層索引的優(yōu)勢乓土,可以一次獲取一組元素(值)
print(s.loc["a"])
'''
c 1
d 2
dtype: int64
'''
# 也可以沿著索引層次進行訪問帐我。
print(s.loc["a", "d"]) # 訪問指定坐標的元素值
'''
2
'''
# 通過位置索引訪問元素拦键,與多層索引沒有任何關(guān)系芬为。
print(s.iloc[0])
'''
1
'''
# 切片
print(s.loc["a":"b"])
'''
a c 1
d 2
b e 3
f 4
dtype: int64
'''
# 行index上的序號類型的切片
print(s.iloc[0:2])
'''
a c 1
d 2
b e 3
f 4
dtype: int64
'''
DataFrame多層索引
- 通過loc(標簽索引)操作媚朦,可以通過多層索引询张,獲取該索引所對應(yīng)的一組值浙炼。
- 通過iloc(位置索引)操作,會獲取對應(yīng)位置的一行(與是否多層索引無關(guān))弯屈。
- 通過s[操作]的行為有些詭異,建議不用厅缺。
- 對于索引湘捎,根據(jù)標簽獲取相應(yīng)的列(如果是多層索引,則可以獲得多列)且叁。
- 對于數(shù)組索引, 根據(jù)標簽逞带,獲取相應(yīng)的列(如果是多層索引纱新,則可以獲得多列)脸爱。
- 對于切片簿废,首先按照標簽進行索引族檬,然后再按照位置進行索引(取行)。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2019-06-13 11:28
# @Author : LiYahui
# @Description : 位置選擇
import pandas as pd
data=[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
df=pd.DataFrame(data)
print(df)
'''
0 1 2 3
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12
3 13 14 15 16
'''
# 指定行索引
df.index=[["a", "a", "b", "b"], ["c", "d", "c", "d"]]
# 指定列索引
df.columns=[["x", "x", "y", "y"], ["z", "u", "z", "u"]]
print("-----------指定行和列索引之后的數(shù)據(jù)值---------------")
print(df)
'''
x y
z u z u
a c 1 2 3 4
d 5 6 7 8
b c 9 10 11 12
d 13 14 15 16
'''
print('-------df.loc["a"]------------')
print(df.loc["a"]) # 對應(yīng)的外層索引的切片
'''
x y
z u z u
c 1 2 3 4
d 5 6 7 8
'''
print('--------df.loc["a", "c"]-----------')
print(df.loc["a", "c"]) #取的是對應(yīng)的行數(shù)據(jù)
'''
x z 1
u 2
y z 3
u 4
'''
print('------df["x", "z"])--------')
print(df["x", "z"]) #取的是列數(shù)據(jù)
'''
a c 1
d 5
b c 9
d 13
Name: (x, z), dtype: int64
'''
# 通過位置訪問元素與是否多層索引無關(guān)。
print('----------df.iloc[0])-----------------')
print(df.iloc[0])
'''
x z 1
u 2
y z 3
u 4
Name: (a, c), dtype: int64
'''
交換索引
我們可以調(diào)用DataFrame對象的swaplevel方法來交換兩個層級索引白对。該方法默認對倒數(shù)第2層與倒數(shù)第1層進行交換甩恼。我們也可以指定交換的層条摸。層次從0開始屈溉,由外向內(nèi)遞增(或者由上到下遞增)抬探,也可以指定負值小压,負值表示倒數(shù)第n層怠益。除此之外,我們也可以使用層次索引的名稱來進行交換烤咧。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2019-06-13 13:07
# @Author : LiYahui
# @Description :
# 交換索引的層級煮嫌,可以以一種不同的方式來進行展示(統(tǒng)計)昌阿。
import pandas as pd
data=[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
df = pd.DataFrame(data, index=[["a", "a", "b", "b"],
["north", "north", "south", "south"], [2017, 2018, 2017, 2018]])
print(df)
'''
0 1 2 3
a north 2017 1 2 3 4
2018 5 6 7 8
b south 2017 9 10 11 12
2018 13 14 15 16
'''
# 層級:從外層到內(nèi)層懦冰,值為0刷钢, 1闯捎, 2……瓤鼻,同時茬祷,層級也可以為負值并蝗,表示倒數(shù)第n個層級(由內(nèi)層到外層)。
# 例如沃粗,-1表示最內(nèi)層最盅。
# 如果沒有顯式指定交換的層級涡贱,則默認交換最內(nèi)層的兩個層級问词。
df = df.swaplevel(0, 2)
print(df)
'''
0 1 2 3
2017 north a 1 2 3 4
2018 north a 5 6 7 8
2017 south b 9 10 11 12
2018 south b 13 14 15 16
'''
# 索引名字的作用激挪。
# 除了數(shù)值來指定索引的層級外垄分,我們也可以通過索引的名字來指定索引的層級锋喜。
df.index.names = ["x", "area", "year"]
df.swaplevel("area", "year")
print(df)
'''
0 1 2 3
x area year
2017 north a 1 2 3 4
2018 north a 5 6 7 8
2017 south b 9 10 11 12
2018 south b 13 14 15 16
'''
df.sort_index()
print(df)
'''
0 1 2 3
x area year
2017 north a 1 2 3 4
2018 north a 5 6 7 8
2017 south b 9 10 11 12
2018 south b 13 14 15 16
'''
索引排序
我們可以使用sort_index方法對索引進行排序處理段标。
- level:指定根據(jù)哪一層進行排序逼庞,默認為最外(上)層赛糟。該值可以是數(shù)值璧南,索引名司倚,或者是由二者構(gòu)成的列表动知。
- inplace:是否就地修改盒粮。默認為False丹皱。
# 層級索引的排序
df = pd.DataFrame(data, index=[["b", "a", "c", "c"],
["c", "y", "k", "k"], [3, -2, 5, 2]])
print(df)
'''
0 1 2 3
b c 3 1 2 3 4
a y -2 5 6 7 8
c k 5 9 10 11 12
2 13 14 15 16
'''
# 在對索引進行排序時,可以通過level參數(shù)指定索引的層級(排序的層級)种呐。
# 如果沒有顯式指定,則默認為最外層的層級(層級為0)弃甥。
# 當我們對某個層級進行排序時爽室,該層級的所有內(nèi)層層級也會進行排序。
print(df.sort_index())
'''
0 1 2 3
a y -2 5 6 7 8
b c 3 1 2 3 4
c k 2 13 14 15 16
5 9 10 11 12
'''
print(df.sort_index(level=1))
'''
0 1 2 3
b c 3 1 2 3 4
c k 2 13 14 15 16
5 9 10 11 12
a y -2 5 6 7 8
'''
索引堆疊
- 通過DataFrame對象的stack方法淆攻,可以進行索引堆疊阔墩,即將指定層級的列轉(zhuǎn)換成行。
- level:指定轉(zhuǎn)換的層級瓶珊,默認為-1啸箫。
*詳見 Python--pandas--unstack() 與stack()
取消堆疊
- 通過DataFrame對象的unstack方法,可以取消索引堆疊伞芹,即將指定層級的行轉(zhuǎn)換成列忘苛。
- level:指定轉(zhuǎn)換的層級胸遇,默認為-1。
- fill_value:指定填充值逗威。默認為NaN尽纽。
- 詳見: Python--pandas--unstack() 與stack()
設(shè)置索引
- 在DataFrame中矫膨,如果我們需要將現(xiàn)有的某一(幾)列作為索引列呐萌,可以調(diào)用set_index方法來實現(xiàn)济欢。
- drop:是否丟棄作為新索引的列半等,默認為True。
- append:是否以追加的方式設(shè)置索引,默認為False。
- inplace:是否就地修改,默認為False是钥。
- 詳見Python-pandas--set_index與reset_index
重置索引
- 調(diào)用在DataFrame對象的reset_index弹囚,可以重置索引蛮穿。該操作與set_index正好相反府适。
- level:重置索引的層級,默認重置所有層級的索引蹦狂。如果重置所有索引摆屯,將會創(chuàng)建默認整數(shù)序列索引廷没。
- drop:是否丟棄重置的索引列狭归,默認為False。
- inplace:是否就地修改,默認為False。
- 詳見 Python-pandas--set_index與reset_index