1. 创建多层行索引
1) 隐式构造
最常见的方法是给DataFrame构造函数的index参数传递两个或更多的数组
- Series也可以创建多层索引
In [1]:
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
In [2]:
s = Series(data = np.random.randint(0,150,size = 6),
index =[['张三','张三','李四','李四','Michael','Michael'],['期中','期末','期中','期末','期中','期末']] )
s
Out[2]:
张三 期中 33
期末 65
李四 期中 139
期末 84
Michael 期中 88
期末 82
dtype: int64
In [3]:
df = DataFrame(data = np.random.randint(0,150,size = (6,3)),
columns = ['Python','Java','PHP'],
index = [['张三','张三','李四','李四','Michael','Michael'],['期中','期末','期中','期末','期中','期末']])
#隐式创建
df
Out[3]:
|
| Python | Java | PHP |
张三 | 期中 | 37 | 19 | 20 |
期末 | 119 | 110 | 44 | |
李四 | 期中 | 58 | 53 | 12 |
期末 | 131 | 127 | 74 | |
Michael | 期中 | 36 | 67 | 39 |
期末 | 49 | 79 | 43 |
2) 显示构造pd.MultiIndex
- 使用数组
In [4]:
df2 = DataFrame(data = np.random.randint(0,150,size = (6,4)),
columns = ["Spring",'Summer','Autumn','Winter'],
index = pd.MultiIndex.from_arrays([['张三','张三','李四','李四','Michael','Michael'],['期中','期末','期中','期末','期中','期末']]))
df2
Out[4]:
|
| Spring | Summer | Autumn | Winter |
张三 | 期中 | 98 | 71 | 41 | 65 |
期末 | 39 | 33 | 94 | 75 | |
李四 | 期中 | 106 | 65 | 66 | 107 |
期末 | 78 | 10 | 27 | 32 | |
Michael | 期中 | 132 | 113 | 127 | 117 |
期末 | 99 | 57 | 125 | 90 |
- 使用tuple
In [5]:
df3 = DataFrame(data = np.random.randint(0,150,size = (6,4)),
columns = ["Spring",'Summer','Autumn','Winter'],
index = pd.MultiIndex.from_tuples([('张三','期中'),('张三','期末'),('李四','期中'),('李四','期末'),('Sara','期中'),('Sara','期末')]))
df3
Out[5]:
|
| Spring | Summer | Autumn | Winter |
张三 | 期中 | 126 | 33 | 25 | 116 |
期末 | 12 | 19 | 92 | 26 | |
李四 | 期中 | 12 | 94 | 70 | 78 |
期末 | 125 | 72 | 66 | 63 | |
Sara | 期中 | 101 | 10 | 104 | 131 |
期末 | 132 | 17 | 32 | 122 |
使用product
最简单,推荐使用
In [6]:
df4 = 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')]))
df4
Out[6]:
|
|
| Spring | Summer | Autumn | Winter |
张三 | middle | A | 86 | 101 | 34 | 18 |
B | 18 | 61 | 99 | 50 | ||
end | A | 31 | 119 | 129 | 125 | |
B | 58 | 52 | 86 | 37 | ||
Sara | middle | A | 83 | 97 | 49 | 3 |
B | 147 | 16 | 45 | 92 | ||
end | A | 16 | 81 | 22 | 43 | |
B | 69 | 92 | 124 | 127 | ||
Lisa | middle | A | 146 | 9 | 21 | 89 |
B | 67 | 52 | 37 | 11 | ||
end | A | 2 | 27 | 119 | 75 | |
B | 61 | 26 | 74 | 65 |
============================================
练习8:
- 创建一个DataFrame,表示出张三李四期中期末各科成绩
============================================
2. 多层列索引
除了行索引index,列索引columns也能用同样的方法创建多层索引
In [7]:
df5 = 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'])
df5
Out[7]:
| 张三 | Sara | Lisa | |||||||||
| middle | end | middle | end | middle | end | ||||||
| A | B | A | B | A | B | A | B | A | B | A | B |
Spring | 109 | 47 | 31 | 119 | 61 | 11 | 78 | 54 | 46 | 18 | 80 | 73 |
Summer | 39 | 76 | 97 | 57 | 133 | 127 | 63 | 24 | 96 | 76 | 145 | 91 |
Autumn | 110 | 88 | 10 | 38 | 82 | 104 | 1 | 108 | 82 | 4 | 28 | 60 |
Winter | 98 | 115 | 111 | 35 | 51 | 6 | 25 | 149 | 50 | 99 | 37 | 3 |
3. 多层索引对象的索引与切片操作
1)Series的操作
【重要】对于Series来说,直接中括号[]与使用.loc()完全一样,因此,推荐使用中括号索引和切片。
In [8]:
s
Out[8]:
张三 期中 33
期末 65
李四 期中 139
期末 84
Michael 期中 88
期末 82
dtype: int64
In [10]:
#多层索引进行切片时,有些汉字,或者英文,不识别,运行异常,并不是代码的问题,自身的bug
s.index = pd.MultiIndex.from_product([['张三','李四','静静'],['期中','期末']])
s
Out[10]:
张三 期中 33
期末 65
李四 期中 139
期末 84
静静 期中 88
期末 82
dtype: int64
In [11]:
s['张三':'李四']
Out[11]:
张三 期中 33
期末 65
李四 期中 139
期末 84
dtype: int64
(1) 索引
In [12]:
s['张三']
Out[12]:
期中 33
期末 65
dtype: int64
In [13]:
#第一个参数,多层索引的第一维;第二个参数,第二维(['张三'有'期中'、'期末','张三'是多层索引的第一维)
s['张三','期中']
Out[13]:
33
In [ ]:
#以前的IDE环境调试,['张三','期中']作为一个参数;本人运行的版本已经不允许
s[['张三','期中']]
Out[13]:
报错 "['期中'] not in index"
In [14]:
#多层索引,有层的概念
s.loc['期中']
报错 KeyError: '期中'
In [15]:
s.loc['李四','期末']
Out[15]:
84
(2) 切片
In [19]:
s.iloc[0:3]
Out[19]:
张三 期中 40
期末 79
李四 期中 88
dtype: int64
In [20]:
s['张三':'Michael']
报错 UnsortedIndexError: 'Key length (1) was greater than MultiIndex lexsort depth (0)'
In [21]:
s.loc['张三':'Michael']
报错 UnsortedIndexError: 'Key length (1) was greater than MultiIndex lexsort depth (0)'
In [23]:
s2 = Series(data = np.random.randint(0,150,size = 6),index = pd.MultiIndex.from_product([list('ABC'),['e','f']]))
s2
Out[23]:
A e 102
f 134
B e 65
f 79
C e 126
f 29
dtype: int64
In [24]:
s2['A':'C']
A e 102
f 134
B e 65
f 79
C e 126
f 29
dtype: int64
In [25]:
s2.loc['A':'B']
Out[25]:
A e 102
f 134
B e 65
f 79
dtype: int64
2)DataFrame的操作
(1) 可以直接使用列名称来进行列索引
In [16]:
df3
Out[16]:
|
| Spring | Summer | Autumn | Winter |
张三 | 期中 | 126 | 33 | 25 | 116 |
期末 | 12 | 19 | 92 | 26 | |
李四 | 期中 | 12 | 94 | 70 | 78 |
期末 | 125 | 72 | 66 | 63 | |
Sara | 期中 | 101 | 10 | 104 | 131 |
期末 | 132 | 17 | 32 | 122 |
In [17]:
df3['Spring']['张三','期中']
Out[17]:
126
In [18]:
#DataFrame多层索引和之前索引类似
#df [] 代表着列索引
df3['Spring','李四']
报错 KeyError: ('Spring', '李四')
In [19]:
df3.index = pd.MultiIndex.from_product([list('ABC'),list('ab')])
df3
Out[19]:
|
| Spring | Summer | Autumn | Winter |
A | a | 126 | 33 | 25 | 116 |
b | 12 | 19 | 92 | 26 | |
B | a | 12 | 94 | 70 | 78 |
b | 125 | 72 | 66 | 63 | |
C | a | 101 | 10 | 104 | 131 |
b | 132 | 17 | 32 | 122 |
In [20]:
#使用切片
df3['A':'B']
Out[20]:
|
| Spring | Summer | Autumn | Winter |
A | a | 126 | 33 | 25 | 116 |
b | 12 | 19 | 92 | 26 | |
B | a | 12 | 94 | 70 | 78 |
b | 125 | 72 | 66 | 63 |
(2) 使用行索引需要用loc()等函数
【极其重要】推荐使用loc()函数
注意在对行索引的时候,若一级行索引还有多个,对二级行索引会遇到问题!也就是说,无法直接对二级索引进行索引,必须让二级索引变成一级索引后才能对其进行索引!
In [21]:
df3.loc['A']
Out[21]:
| Spring | Summer | Autumn | Winter |
a | 126 | 33 | 25 | 116 |
b | 12 | 19 | 92 | 26 |
In [22]:
df3.loc['B','a']
Out[22]:
Spring 12
Summer 94
Autumn 70
Winter 78
Name: (B, a), dtype: int64
In [23]:
df3.loc['a']
报错 KeyError: 'a'
In [24]:
df3.loc[['A','B']]
Out[24]:
|
| Spring | Summer | Autumn | Winter |
A | a | 126 | 33 | 25 | 116 |
b | 12 | 19 | 92 | 26 | |
B | a | 12 | 94 | 70 | 78 |
b | 125 | 72 | 66 | 63 |
In [25]:
df3.loc['A':'B']
Out[25]:
|
| Spring | Summer | Autumn | Winter |
A | a | 126 | 33 | 25 | 116 |
b | 12 | 19 | 92 | 26 | |
B | a | 12 | 94 | 70 | 78 |
b | 125 | 72 | 66 | 63 |
In [26]:
df3.iloc[0:3]
Out[26]:
|
| Spring | Summer | Autumn | Winter |
A | a | 126 | 33 | 25 | 116 |
b | 12 | 19 | 92 | 26 | |
B | a | 12 | 94 | 70 | 78 |
============================================
练习9:
分析比较Series和DataFrame各种索引的方式,熟练掌握.loc()方法
假设张三再一次在期中考试的时候因为特殊原因放弃英语考试,如何实现?
============================================
4. 索引的堆(stack)
stack()
unstack()
小技巧】使用stack()的时候,level等于哪一个,哪一个就消失,出现在行里。
In [30]:
df5
Out[30]:
| 张三 | Sara | Lisa | |||||||||
| middle | end | middle | end | middle | end | ||||||
| A | B | A | B | A | B | A | B | A | B | A | B |
Spring | 109 | 47 | 31 | 119 | 61 | 11 | 78 | 54 | 46 | 18 | 80 | 73 |
Summer | 39 | 76 | 97 | 57 | 133 | 127 | 63 | 24 | 96 | 76 | 145 | 91 |
Autumn | 110 | 88 | 10 | 38 | 82 | 104 | 1 | 108 | 82 | 4 | 28 | 60 |
Winter | 98 | 115 | 111 | 35 | 51 | 6 | 25 | 149 | 50 | 99 | 37 | 3 |
In [31]:
# stack() = 堆 ————>行
# 对多层索引的列而言,0,1,2:从上往下计数
df5.stack(level = 0)
Out[31]:
|
| end | middle | ||
|
| A | B | A | B |
Spring | Lisa | 80 | 73 | 46 | 18 |
Sara | 78 | 54 | 61 | 11 | |
张三 | 31 | 119 | 109 | 47 | |
Summer | Lisa | 145 | 91 | 96 | 76 |
Sara | 63 | 24 | 133 | 127 | |
张三 | 97 | 57 | 39 | 76 | |
Autumn | Lisa | 28 | 60 | 82 | 4 |
Sara | 1 | 108 | 82 | 104 | |
张三 | 10 | 38 | 110 | 88 | |
Winter | Lisa | 37 | 3 | 50 | 99 |
Sara | 25 | 149 | 51 | 6 | |
张三 | 111 | 35 | 98 | 115 |
In [32]:
df4.unstack(level=1)
Out[32]:
|
| Spring | Summer | Autumn | Winter | ||||
|
| end | middle | end | middle | end | middle | end | middle |
Lisa | A | 2 | 146 | 27 | 9 | 119 | 21 | 75 | 89 |
B | 61 | 67 | 26 | 52 | 74 | 37 | 65 | 11 | |
Sara | A | 16 | 83 | 81 | 97 | 22 | 49 | 43 | 3 |
B | 69 | 147 | 92 | 16 | 124 | 45 | 127 | 92 | |
张三 | A | 31 | 86 | 119 | 101 | 129 | 34 | 125 | 18 |
B | 58 | 18 | 52 | 61 | 86 | 99 | 37 | 50 |
【小技巧】使用unstack()的时候,level等于哪一个,哪一个就消失,出现在列里。
============================================
练习10:
使用unstack()将ddd变为两行,分别为期中期末
使用unstack()将ddd变为四行,分别为四个科目
============================================
5. 聚合操作
【注意】
需要指定axis
【小技巧】和unstack()相反,聚合的时候,axis等于哪一个,哪一个就会进行计算。
所谓的聚合操作:平均数,方差,最大值,最小值……
In [33]:
df3
Out[33]:
|
| Spring | Summer | Autumn | Winter |
A | a | 126 | 33 | 25 | 116 |
b | 12 | 19 | 92 | 26 | |
B | a | 12 | 94 | 70 | 78 |
b | 125 | 72 | 66 | 63 | |
C | a | 101 | 10 | 104 | 131 |
b | 132 | 17 | 32 | 122 |
In [34]:
df3.mean(axis = 'columns')
Out[34]:
A a 75.00
b 37.25
B a 63.50
b 81.50
C a 86.50
b 75.75
dtype: float64
In [35]:
df3
Out[35]:
|
| Spring | Summer | Autumn | Winter |
A | a | 126 | 33 | 25 | 116 |
b | 12 | 19 | 92 | 26 | |
B | a | 12 | 94 | 70 | 78 |
b | 125 | 72 | 66 | 63 | |
C | a | 101 | 10 | 104 | 131 |
b | 132 | 17 | 32 | 122 |
In [36]:
#数据离散的程度,
df3.std()
Out[36]:
Spring 57.277104
Summer 34.219390
Autumn 31.511374
Winter 40.859108
dtype: float64
In [38]:
# axis = 0 行,对行进行求和操作,行的数据被加和到一起,列名就显示为索引
df3.sum(axis = 0)
Out[38]:
Spring 508
Summer 245
Autumn 389
Winter 536
dtype: int64
In [39]:
df3.sum(axis = 1)
Out[39]:
A a 300
b 149
B a 254
b 326
C a 346
b 303
dtype: int64
In [40]:
df3.max()
Out[40]:
Spring 132
Summer 94
Autumn 104
Winter 131
dtype: int64
In [ ]:
============================================
练习11:
计算各个科目期中期末平均成绩
计算各科目张三李四的最高分
============================================
仅供参考学习,严禁转载!