pandas层次化索引
1. 创建多层行索引
1) 隐式构造
最常见的方法是给DataFrame构造函数的index参数传递两个或更多的数组
- Series也可以创建多层索引
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
s = Series([1,2,3,4],
index =[['a','a','b','b'],['期中','期末','期中','期末']] )
s
a 期中 1 期末 2 b 期中 3 期末 4 dtype: int64
df = DataFrame(data = np.random.randint(0,150,size = (6,3)),
columns = ['语文','数学','python'],
index = [['Michael','Michael','Lisa','Lisa','Po','Po'],['期中','期末','期中','期末','期中','期末']])
#隐式创建
df
Michael | 期中 | 126 | 111 | 14 |
---|---|---|---|---|
期末 | 101 | 37 | 145 | |
Lisa | 期中 | 95 | 138 | 111 |
期末 | 117 | 60 | 5 | |
Po | 期中 | 134 | 131 | 88 |
期末 | 56 | 85 | 113 |
2) 显示构造pd.MultiIndex
- 使用数组
df1 = DataFrame(data = np.random.randint(0,150,size = (6,3)),
columns = ["Java",'Html5','Python'],
index = pd.MultiIndex.from_arrays([['张三','张三','李四','李四','Michael','Michael'],['期中','期末','期中','期末','期中','期末']]))
df1
张三 | 期中 | 120 | 119 | 137 |
---|---|---|---|---|
期末 | 101 | 1 | 115 | |
李四 | 期中 | 66 | 117 | 121 |
期末 | 127 | 69 | 70 | |
Michael | 期中 | 41 | 25 | 128 |
期末 | 101 | 7 | 10 |
- 使用tuple
df2 = DataFrame(data = np.random.randint(0,150,size = (6,4)),
columns = ["Spring",'Summer','Autumn','Winter'],
index = pd.MultiIndex.from_tuples([('张三','期中'),('张三','期末'),('李四','期中'),('李四','期末'),('Sara','期中'),('Sara','期末')]))
df2
张三 | 期中 | 143 | 84 | 10 | 74 |
---|---|---|---|---|---|
期末 | 66 | 72 | 71 | 115 | |
李四 | 期中 | 98 | 126 | 37 | 42 |
期末 | 90 | 10 | 5 | 90 | |
Sara | 期中 | 104 | 95 | 93 | 28 |
期末 | 139 | 7 | 143 | 122 |
使用product
最简单,推荐使用
df3 = DataFrame(data = np.random.randint(0,150,size = (12,4)),
columns = ["Spring",'Summer','Autumn','Winter'],
index = pd.MultiIndex.from_product([['张三','Sara','Lisa'],['middle','end'],list('AB')]))
df3
张三 | middle | A | 134 | 23 | 5 | 30 |
---|---|---|---|---|---|---|
B | 6 | 12 | 105 | 47 | ||
end | A | 149 | 121 | 50 | 56 | |
B | 17 | 28 | 90 | 89 | ||
Sara | middle | A | 110 | 64 | 86 | 20 |
B | 20 | 28 | 76 | 136 | ||
end | A | 39 | 66 | 62 | 78 | |
B | 128 | 147 | 6 | 79 | ||
Lisa | middle | A | 12 | 51 | 10 | 58 |
B | 126 | 51 | 133 | 146 | ||
end | A | 25 | 57 | 107 | 30 | |
B | 19 | 31 | 55 | 120 |
============================================
练习8:
- 创建一个DataFrame,表示出张三李四期中期末各科成绩
============================================
2. 多层列索引
除了行索引index,列索引columns也能用同样的方法创建多层索引
df4 = DataFrame(data = np.random.randint(0,150,size = (4,12)),
columns = pd.MultiIndex.from_product([['张三','Sara','Lisa'],['middle','end'],list('AB')]),
index = ["Spring",'Summer','Autumn','Winter'])
df4
Spring | 109 | 22 | 35 | 58 | 38 | 134 | 22 | 134 | 50 | 52 | 64 | 87 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Summer | 140 | 117 | 13 | 3 | 29 | 140 | 125 | 43 | 76 | 78 | 113 | 147 |
Autumn | 128 | 31 | 146 | 76 | 60 | 40 | 34 | 51 | 111 | 129 | 64 | 142 |
Winter | 111 | 91 | 54 | 12 | 89 | 45 | 127 | 28 | 42 | 58 | 7 | 6 |
3. 多层索引对象的索引与切片操作
1)Series的操作
【重要】对于Series来说,直接中括号[]与使用.loc[]完全一样,因此,推荐使用中括号索引和切片。
多层索引进行切片时,有些汉字,或者英文,不识别,运行异常,并不是代码的问题,自身的bug
(1) 索引
s
a 期中 1 期末 2 b 期中 3 期末 4 dtype: int64
# 第一个参数,多层索引的第一维,第二个参数,多层索引第二维
s['a','期中']
1
#['a','期中']作为一个参数
s[['a','期中']]
a 期中 1 期末 2 dtype: int64
s[['a','b','c']]
a 期中 1 期末 2 b 期中 3 期末 4 dtype: int64
s.loc['李四','期末']
109
(2) 切片
s['a':'b']
a 期中 1 期末 2 b 期中 3 期末 4 dtype: int64
s.iloc[0:3]
a 期中 1 期末 2 b 期中 3 dtype: int64
s2 = Series(data = np.random.randint(0,150,size = 6),index = pd.MultiIndex.from_product([list('ABC'),['e','f']]))
s2
A e 136 f 120 B e 84 f 56 C e 142 f 101 dtype: int32
s2['A':'C']
A e 136 f 120 B e 84 f 56 C e 142 f 101 dtype: int32
s2.loc['A':'B']
A e 136 f 120 B e 84 f 56 dtype: int32
2)DataFrame的操作
(1) 可以直接使用列名称来进行列索引
对于二维索引,如果包含中文,进行切片时,存在报错bug,不是代码问题
df1.index = pd.MultiIndex.from_product([list('ABC'),['期中','期末']])
df1
A | 期中 | 120 | 119 | 137 |
---|---|---|---|---|
期末 | 101 | 1 | 115 | |
B | 期中 | 66 | 117 | 121 |
期末 | 127 | 69 | 70 | |
C | 期中 | 41 | 25 | 128 |
期末 | 101 | 7 | 10 |
df1['A':'B']
A | 期中 | 120 | 119 | 137 |
---|---|---|---|---|
期末 | 101 | 1 | 115 | |
B | 期中 | 66 | 117 | 121 |
期末 | 127 | 69 | 70 |
df1.iloc[0:4]
A | 期中 | 120 | 119 | 137 |
---|---|---|---|---|
期末 | 101 | 1 | 115 | |
B | 期中 | 66 | 117 | 121 |
期末 | 127 | 69 | 70 |
(2) 使用行索引需要用loc()等函数
【极其重要】推荐使用loc()函数
注意在对行索引的时候,若一级行索引还有多个,对二级行索引会遇到问题!也就是说,无法直接对二级索引进行索引,必须让二级索引变成一级索引后才能对其进行索引!
df2
张三 | 期中 | 143 | 84 | 10 | 74 |
---|---|---|---|---|---|
期末 | 66 | 72 | 71 | 115 | |
李四 | 期中 | 98 | 126 | 37 | 42 |
期末 | 90 | 10 | 5 | 90 | |
Sara | 期中 | 104 | 95 | 93 | 28 |
期末 | 139 | 7 | 143 | 122 |
df2.loc['张三','期中']
Spring 143 Summer 84 Autumn 10 Winter 74 Name: (张三, 期中), dtype: int32
df2.loc['张三'].loc['期中']
Spring 143 Summer 84 Autumn 10 Winter 74 Name: 期中, dtype: int32
df2.loc[['张三','李四']]
张三 | 期中 | 143 | 84 | 10 | 74 |
---|---|---|---|---|---|
期末 | 66 | 72 | 71 | 115 | |
李四 | 期中 | 98 | 126 | 37 | 42 |
期末 | 90 | 10 | 5 | 90 |
============================================
练习9:
分析比较Series和DataFrame各种索引的方式,熟练掌握.loc()方法
假设张三再一次在期中考试的时候因为特殊原因放弃英语考试,如何实现?
============================================
4. 索引的堆(stack)
stack()
unstack()
【小技巧】使用stack()的时候,level等于哪一个,哪一个就消失,出现在行里。
df4
Spring | 109 | 22 | 35 | 58 | 38 | 134 | 22 | 134 | 50 | 52 | 64 | 87 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Summer | 140 | 117 | 13 | 3 | 29 | 140 | 125 | 43 | 76 | 78 | 113 | 147 |
Autumn | 128 | 31 | 146 | 76 | 60 | 40 | 34 | 51 | 111 | 129 | 64 | 142 |
Winter | 111 | 91 | 54 | 12 | 89 | 45 | 127 | 28 | 42 | 58 | 7 | 6 |
#stack = 堆--->行
#多层索引的列而言0,1,1:从上往下计数
df4.stack()
Spring | A | 64 | 50 | 22 | 38 | 35 | 109 |
---|---|---|---|---|---|---|---|
B | 87 | 52 | 134 | 134 | 58 | 22 | |
Summer | A | 113 | 76 | 125 | 29 | 13 | 140 |
B | 147 | 78 | 43 | 140 | 3 | 117 | |
Autumn | A | 64 | 111 | 34 | 60 | 146 | 128 |
B | 142 | 129 | 51 | 40 | 76 | 31 | |
Winter | A | 7 | 42 | 127 | 89 | 54 | 111 |
B | 6 | 58 | 28 | 45 | 12 | 91 |
df4.stack(level=0)
Spring | Lisa | 64 | 87 | 50 | 52 |
---|---|---|---|---|---|
Sara | 22 | 134 | 38 | 134 | |
张三 | 35 | 58 | 109 | 22 | |
Summer | Lisa | 113 | 147 | 76 | 78 |
Sara | 125 | 43 | 29 | 140 | |
张三 | 13 | 3 | 140 | 117 | |
Autumn | Lisa | 64 | 142 | 111 | 129 |
Sara | 34 | 51 | 60 | 40 | |
张三 | 146 | 76 | 128 | 31 | |
Winter | Lisa | 7 | 6 | 42 | 58 |
Sara | 127 | 28 | 89 | 45 | |
张三 | 54 | 12 | 111 | 91 |
【小技巧】使用unstack()的时候,level等于哪一个,哪一个就消失,出现在列里。
df2
张三 | 期中 | 143 | 84 | 10 | 74 |
---|---|---|---|---|---|
期末 | 66 | 72 | 71 | 115 | |
李四 | 期中 | 98 | 126 | 37 | 42 |
期末 | 90 | 10 | 5 | 90 | |
Sara | 期中 | 104 | 95 | 93 | 28 |
期末 | 139 | 7 | 143 | 122 |
df2.unstack(level=1)
Sara | 104 | 139 | 95 | 7 | 93 | 143 | 28 | 122 |
---|---|---|---|---|---|---|---|---|
张三 | 143 | 66 | 84 | 72 | 10 | 71 | 74 | 115 |
李四 | 98 | 90 | 126 | 10 | 37 | 5 | 42 | 90 |
============================================
练习10:
使用unstack()将ddd变为两行,分别为期中期末
使用unstack()将ddd变为四行,分别为四个科目
============================================
5. 聚合操作
【注意】
需要指定axis
【小技巧】和unstack()相反,聚合的时候,axis等于哪一个,哪一个就会进行计算。
所谓的聚合操作:平均数,方差,最大值,最小值……
df1
A | 期中 | 120 | 119 | 137 |
---|---|---|---|---|
期末 | 101 | 1 | 115 | |
B | 期中 | 66 | 117 | 121 |
期末 | 127 | 69 | 70 | |
C | 期中 | 41 | 25 | 128 |
期末 | 101 | 7 | 10 |
#axis=0 进行行间计算
#axis=1 进行列间计算
df1.sum()
Java 556 Html5 338 Python 581 dtype: int64
df1.sum(axis =1)
A 期中 376 期末 217 B 期中 304 期末 266 C 期中 194 期末 118 dtype: int64
df1.mean(axis = 1)
A 期中 125.333333 期末 72.333333 B 期中 101.333333 期末 88.666667 C 期中 64.666667 期末 39.333333 dtype: float64
#数据离散的程度,方差越大数值间差距大
df1.std(axis=1)
A 期中 10.115994 期末 62.171805 B 期中 30.664855 期末 33.201406 C 期中 55.428633 期末 53.425961 dtype: float64
============================================
练习11:
计算各个科目期中期末平均成绩
计算各科目张三李四的最高分
============================================