pandas层次化索引
多级索引包括: 多级行索引 和 多级列索引
1. 创建多层行索引
1) 隐式构造
最常见的方法是给DataFrame构造函数的index参数传递两个或更多的数组
- Series也可以创建多层索引
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
index = [np.array(["期中","期中","期末","期末"]),np.array(["语文","英语","语文","英语"])]
Series(np.random.randn(4),index=index)
结果为:
期中 语文 1.040276
英语 0.456647
期末 语文 0.583853
英语 0.348378
dtype: float64
2) 显示构造pd.MultiIndex
- 使用数组
index = pd.MultiIndex.from_arrays([["期中","期中","期中","期末","期末","期末"],["语文","英语","数学","语文","英语","数学"]])
columns = ["张三","李四","王五","赵柳"]
data = np.random.randint(0,150,size=(6,4))
DataFrame(data,index,columns)
张三 | 李四 | 王五 | 赵柳 | ||
---|---|---|---|---|---|
期中 | 语文 | 12 | 146 | 61 | 121 |
英语 | 120 | 119 | 100 | 68 | |
数学 | 73 | 80 | 40 | 102 | |
期末 | 语文 | 90 | 143 | 51 | 85 |
英语 | 6 | 35 | 62 | 90 | |
数学 | 32 | 60 | 114 | 149 |
- 使用tuple
index = pd.MultiIndex.from_tuples([("期中","语文"),("期中","数学"),("期中","英语"),("期末","语文"),("期末","数学"),("期末","英语")])
columns = ["张三","李四","王五","赵柳"]
data = np.random.randint(0,150,size=(6,4))
DataFrame(data,index,columns)
张三 | 李四 | 王五 | 赵柳 | ||
---|---|---|---|---|---|
期中 | 语文 | 0 | 40 | 95 | 1 |
数学 | 112 | 137 | 32 | 65 | |
英语 | 84 | 81 | 74 | 104 | |
期末 | 语文 | 146 | 125 | 44 | 51 |
数学 | 146 | 55 | 62 | 137 | |
英语 | 80 | 24 | 129 | 77 |
-
使用product
最简单,推荐使用
index = pd.MultiIndex.from_product([["期中","期末"],["语文","数学","英语"]])
columns = ["张三","李四","王五","赵柳"]
data = np.random.randint(0,150,size=(6,4))
df2 = DataFrame(data,index,columns)
df2
张三 | 李四 | 王五 | 赵柳 | ||
---|---|---|---|---|---|
期中 | 语文 | 117 | 85 | 77 | 38 |
数学 | 119 | 108 | 121 | 130 | |
英语 | 6 | 96 | 126 | 133 | |
期末 | 语文 | 125 | 87 | 133 | 113 |
数学 | 84 | 112 | 28 | 26 | |
英语 | 132 | 43 | 126 | 104 |
============================================
练习8:
- 创建一个DataFrame,表示出张三李四期中期末各科成绩
============================================
data = np.random.randint(0,150,size=(4,2))
index= pd.MultiIndex.from_product([["期中","期末"],["语文","英语"]])
columns = ["张三","李四"]
DataFrame(data,index,columns)
张三 | 李四 | ||
---|---|---|---|
期中 | 语文 | 14 | 149 |
英语 | 97 | 84 | |
期末 | 语文 | 4 | 124 |
英语 | 7 | 27 |
2. 多层列索引
除了行索引index,列索引columns也能用同样的方法创建多层索引
data = np.random.randint(0,150,size=(2,4))
index= pd.MultiIndex.from_product([["期中","期末"],["语文","英语"]]) # 多层索引
columns = ["张三","李四"] #单层索引
df1 = DataFrame(data=data,index=columns,columns=index)
期中 | 期末 | |||
---|---|---|---|---|
语文 | 英语 | 语文 | 英语 | |
张三 | 50 | 12 | 89 | 99 |
李四 | 119 | 9 | 133 | 102 |
3. 多层索引对象的索引与切片操作
1)Series的操作
【重要】对于Series来说,直接中括号[]与使用.loc()完全一样,推荐使用.loc中括号索引和切片。
(1) 索引
df2
张三 | 李四 | 王五 | 赵柳 | ||
---|---|---|---|---|---|
期中 | 语文 | 117 | 85 | 77 | 38 |
数学 | 119 | 108 | 121 | 130 | |
英语 | 6 | 96 | 126 | 133 | |
期末 | 语文 | 125 | 87 | 133 | 113 |
数学 | 84 | 112 | 28 | 26 | |
英语 | 132 | 43 | 126 | 104 |
从列入手
df2["张三"] # 找出来的是个Series 这个Series有多重行索引
结果为:
期中 语文 117
数学 119
英语 6
期末 语文 125
数学 84
英语 132
Name: 张三, dtype: int32
type(df2["张三"])
结果为:pandas.core.series.Series
df2["张三"].loc["期中"].loc["语文"]
结果为:117
从行入手
df2.loc["期中"]["张三"]
结果为:
语文 117
数学 119
英语 6
Name: 张三, dtype: int32
df2.loc["期中"].loc["语文"]
结果为:
张三 117
李四 85
王五 77
赵柳 38
Name: 语文, dtype: int32
(2) 切片
df2[0:4]
张三 | 李四 | 王五 | 赵柳 | ||
---|---|---|---|---|---|
期中 | 语文 | 117 | 85 | 77 | 38 |
数学 | 119 | 108 | 121 | 130 | |
英语 | 6 | 96 | 126 | 133 | |
期末 | 语文 | 125 | 87 | 133 | 113 |
2)DataFrame的操作
data = np.random.randint(0,150,size=(6,6))
index = pd.MultiIndex.from_product([["期中","期末"],["语文","数学","英语"]])
columns = pd.MultiIndex.from_product([["一班","二班"],["01","02","03"]])
df1 = DataFrame(data=data,index=index,columns=columns)
df1
一班 | 二班 | ||||||
---|---|---|---|---|---|---|---|
01 | 02 | 03 | 01 | 02 | 03 | ||
期中 | 语文 | 21 | 19 | 135 | 105 | 53 | 126 |
数学 | 75 | 67 | 8 | 103 | 93 | 125 | |
英语 | 63 | 76 | 65 | 78 | 78 | 39 | |
期末 | 语文 | 65 | 47 | 26 | 34 | 95 | 33 |
数学 | 135 | 55 | 78 | 125 | 92 | 56 | |
英语 | 21 | 136 | 84 | 72 | 13 | 27 |
(1) 可以直接使用列名称来进行列索引
df1["一班"] # 开始的时候只能传 最外层的
01 | 02 | 03 | ||
---|---|---|---|---|
期中 | 语文 | 21 | 19 | 135 |
数学 | 75 | 67 | 8 | |
英语 | 63 | 76 | 65 | |
期末 | 语文 | 65 | 47 | 26 |
数学 | 135 | 55 | 78 | |
英语 | 21 | 136 | 84 |
df1["01"]
结果为:
期中 语文 92
数学 124
英语 4
期末 语文 104
数学 8
英语 135
Name: 01, dtype: int32
df1["一班"]["01"]
与上面结果保持一致
行多级索引的索引和切片操作
df1.loc["期中"] # 一开始的时候只能找最外层的
一班 | 二班 | |||||
---|---|---|---|---|---|---|
01 | 02 | 03 | 01 | 02 | 03 | |
语文 | 21 | 19 | 135 | 105 | 53 | 126 |
数学 | 75 | 67 | 8 | 103 | 93 | 125 |
英语 | 63 | 76 | 65 | 78 | 78 | 39 |
df1.loc["语文"]
df1.loc["期中"].loc["语文"]
df1.loc["期中"][0:2]
一班 | 二班 | |||||
---|---|---|---|---|---|---|
01 | 02 | 03 | 01 | 02 | 03 | |
语文 | 21 | 19 | 135 | 105 | 53 | 126 |
数学 | 75 | 67 | 8 | 103 | 93 | 125 |
df1.loc["期中"].iloc[:,0:2]
一班 | ||
---|---|---|
01 | 02 | |
语文 | 21 | 19 |
数学 | 75 | 67 |
英语 | 63 | 76 |
(2) 使用行索引需要用loc()等函数
【重要】推荐使用loc()函数
============================================
练习9:
- 分析比较Series和DataFrame各种索引的方式,熟练掌握.loc()方法
- 假设张三再一次在期中考试的时候因为特殊原因放弃英语考试,如何实现?
============================================