多级索引(也称层次化索引)是pandas的重要功能,可以在Series、DataFrame对象上拥有2个以及2个以上的索引。
实质上,单级索引对应Index对象,多级索引对应MultiIndex对象。
一、Series对象的多级索引
import pandas as pd
import numpy as np
se1=pd.Series(np.random.randn(4),index=[list("aabb"),[1,2,1,2]])
Out[6]:
a 1 0.357171
2 0.084055
b 1 -0.678752
2 0.132007
dtype: float64
se1['a']
Out[7]:
1 0.357171
2 0.084055
dtype: float64
se1['a':'b']
Out[8]:
a 1 0.357171
2 0.084055
b 1 -0.678752
2 0.132007
dtype: float64
se1[:, 1]
Out[9]:
a 0.357171
b -0.678752
dtype: float64
se1[:, 2]
Out[10]:
a 0.084055
b 0.132007
dtype: float64
二、DataFrame对象的多级索引
import numpy as np
df = pd.DataFrame(np.random.randint(0, 150, size=(6,3)), columns=['语文', '数学', 'Python'], index=[['Michal', 'Michal', 'Kobe','Kobe', 'James', 'James'],['Mid','End', 'Mid', 'End','Mid', 'End']])
Out[25]:
语文 数学 Python
Michal Mid 100 43 73
End 11 18 60
Kobe Mid 104 66 54
End 30 120 134
James Mid 135 77 56
End 45 127 63
df = pd.DataFrame(np.random.randint(0, 150, size=(6,3)), columns=['语文', '数学', 'Python'], index=pd.MultiIndex.from_arrays([['Michal', 'Michal', 'Kobe','Kobe', 'James', 'James'],['Mid','End', 'Mid', 'End','Mid', 'End']]))
Out[27]:
语文 数学 Python
Michal Mid 56 46 104
End 83 57 95
Kobe Mid 48 94 45
End 22 99 49
James Mid 65 66 91
End 69 101 84
df = pd.DataFrame(np.random.randint(0, 150, size=(6,3)), columns=['语文', '数学', 'Python'], index=pd.MultiIndex.from_tuples([('Michal','期中'), ('Michal','期末'), ('Kobe','期中'), ('Kobe','期末'), ('James','期中'), ('James','期末')]))
Out[29]:
语文 数学 Python
Michal 期中 10 107 48
期末 113 49 147
Kobe 期中 116 138 29
期末 7 64 53
James 期中 1 30 21
期末 70 76 108
df = pd.DataFrame(np.random.randint(0, 150, size=(6,3)), columns=['语文', '数学', 'Python'], index=pd.MultiIndex.from_product([['Michal','Kobe','James'],['Mid','End']]))
Out[31]:
语文 数学 Python
Michal Mid 85 89 17
End 21 4 23
Kobe Mid 54 117 108
End 37 20 79
James Mid 56 47 82
End 45 57 126
2. 多层列索引
df = pd.DataFrame(np.random.randint(0, 150, size=(3,6)), index=['语文', '数学', 'Python'], columns=pd.MultiIndex.from_product([['Michal','Kobe','James'],['Mid','End']]))
Out[34]:
Michal Kobe James
Mid End Mid End Mid End
语文 74 84 76 142 36 87
数学 44 90 57 143 78 68
Python 79 46 120 47 128 145
3. 索引赋值,设置名称和交换
df1=pd.DataFrame(np.arange(12).reshape(4,3),index=[list("AABB"),[1,2,1,2]],columns=[list("XXY"),[10,11,10]])
Out[11]:
X Y
10 11 10
A 1 0 1 2
2 3 4 5
B 1 6 7 8
2 9 10 11
df1.columns.names=['XY','sum']
df1.index.names=['AB','num']
Out[12]:
XY X Y
sum 10 11 10
AB num
A 1 0 1 2
2 3 4 5
B 1 6 7 8
2 9 10 11
df1.index=pd.MultiIndex.from_arrays([list("AABB"),[3,4,3,4]],names=["AB","num"])
Out[13]:
XY X Y
sum 10 11 10
AB num
A 3 0 1 2
4 3 4 5
B 3 6 7 8
4 9 10 11
df1.swaplevel('AB','num')
Out[14]:
XY X Y
sum 10 11 10
num AB
3 A 0 1 2
4 A 3 4 5
3 B 6 7 8
4 B 9 10 11
4. 获取索引值
df = pd.DataFrame(np.random.randint(0, 150, size=(6,3)), columns=['语文', '数学', 'Python'], index=pd.MultiIndex.from_product([['Michal','Kobe','James'],['Mid','End']]))
Out[38]:
语文 数学 Python
Michal Mid 65 134 85
End 94 91 48
Kobe Mid 118 142 141
End 2 32 106
James Mid 29 11 127
End 16 93 99
df.index
Out[39]:
MultiIndex([('Michal', 'Mid'),
('Michal', 'End'),
( 'Kobe', 'Mid'),
( 'Kobe', 'End'),
( 'James', 'Mid'),
( 'James', 'End')],
# loc获取
df.loc['James', :]
Out[42]:
语文 数学 Python
Mid 29 11 127
End 16 93 99
df[df.index.get_level_values(0) == 'Michal']
Out[45]:
语文 数学 Python
Michal Mid 65 134 85
End 94 91 48
df[df.index.get_level_values(1) == 'Mid']
Out[46]:
语文 数学 Python
Michal Mid 65 134 85
Kobe Mid 118 142 141
James Mid 29 11 127
df.loc[('James', 'Mid'), :]
Out[41]:
语文 29
数学 11
Python 127
Name: (James, Mid), dtype: int32
三、案例:考试数据分析
1. 计算每个学生的总成绩
2. 计算每个学生各学期的总成绩
3. 各门课程平均成绩
4. 各学期大于本课程平均成绩的学生姓名及成绩
import pandas as pd
exam_data = pd.read_excel('试题.xlsx', sheet_name='试题数据')
exam_data
Out[3]:
姓名 课程 学期 成绩
0 王大伟 大学英语 1 92
1 王大伟 大学英语 2 85
2 王大伟 大学英语 3 83
3 王大伟 大学英语 4 90
4 王大伟 高等数学 1 91
5 王大伟 高等数学 2 86
6 王大伟 高等数学 3 98
7 王大伟 高等数学 4 84
8 王大伟 大学体育 1 78
9 王大伟 大学体育 2 91
# 读取时设置
exam_data = pd.read_excel('试题.xlsx', sheet_name='试题数据', index_col=[0, 1])
exam_data
Out[5]:
学期 成绩
姓名 课程
王大伟 大学英语 1 92
大学英语 2 85
大学英语 3 83
大学英语 4 90
高等数学 1 91
高等数学 2 86
高等数学 3 98
高等数学 4 84
大学体育 1 78
大学体育 2 91
大学体育 3 80
大学体育 4 90
孙力 大学英语 1 87
大学英语 2 79
大学英语 3 93
大学英语 4 78
高等数学 1 87
高等数学 2 93
高等数学 3 85
高等数学 4 89
大学体育 1 77
大学体育 2 83
大学体育 3 99
大学体育 4 88
张明 大学英语 1 88
大学英语 2 94
大学英语 3 96
大学英语 4 87
高等数学 1 97
高等数学 2 89
高等数学 3 94
高等数学 4 86
大学体育 1 87
大学体育 2 85
大学体育 3 86
大学体育 4 92
# 设置索引列
exam_data.set_index(keys=['姓名', '课程'])
Out[21]:
学期 成绩
姓名 课程
王大伟 大学英语 1 92
大学英语 2 85
大学英语 3 83
大学英语 4 90
高等数学 1 91
高等数学 2 86
高等数学 3 98
高等数学 4 84
大学体育 1 78
大学体育 2 91
大学体育 3 80
大学体育 4 90
孙力 大学英语 1 87
大学英语 2 79
大学英语 3 93
大学英语 4 78
高等数学 1 87
高等数学 2 93
高等数学 3 85
高等数学 4 89
大学体育 1 77
大学体育 2 83
大学体育 3 99
大学体育 4 88
张明 大学英语 1 88
大学英语 2 94
大学英语 3 96
大学英语 4 87
高等数学 1 97
高等数学 2 89
高等数学 3 94
高等数学 4 86
大学体育 1 87
大学体育 2 85
大学体育 3 86
大学体育 4 92
当然,这里我们不需要对其设置索引
exam_data = pd.read_excel('试题.xlsx', sheet_name='试题数据')
# 1. 计算每个学生总成绩
student_total_score = exam_data.groupby(by=['姓名']).agg(
{'成绩': sum}).rename(columns={'成绩': '总成绩'})
print('1. 学生总成绩:\n', student_total_score)
1. 学生总成绩:
孙力 1038
张明 1081
王大伟 1048
# 2. 每个学生各学期的总成绩
student_semester_total = exam_data.groupby(by=['姓名', '学期']).agg(
{'成绩': sum}).rename({'成绩': ' 总成绩'})
print('\n2. 学生每个学期总成绩:\n', student_semester_total)
2. 学生每个学期总成绩:
姓名 学期
孙力 1 251
2 255
3 277
4 255
张明 1 272
2 268
3 276
4 265
王大伟 1 261
2 262
3 261
4 264
3. 各门课程平均成绩
# 3. 各门课程平均成绩
course_avg_score = exam_data.groupby(by=['课程'])['成绩'].mean()
print('\n3. 各门课程平均成绩:\n', course_avg_score)
3. 各门课程平均成绩:
大学体育 86.333333
大学英语 87.666667
高等数学 89.916667
Name: 成绩, dtype: float64
def judge_score(row):
return row['成绩'] > course_avg_score[row['课程']]
greater_than_avg_student = exam_data[exam_data.apply(judge_score, axis=1)].set_index(keys=['姓名', '课程'])
print('\n4. 各学期大于本课程平均成绩的学生姓名及成绩: \n', greater_than_avg_student)
4. 各学期大于本课程平均成绩的学生姓名及成绩:
学期 成绩
姓名 课程
王大伟 大学英语 1 92
大学英语 4 90
高等数学 1 91
高等数学 3 98
大学体育 2 91
大学体育 4 90
孙力 大学英语 3 93
高等数学 2 93
大学体育 3 99
大学体育 4 88
张明 大学英语 1 88
大学英语 2 94
大学英语 3 96
高等数学 1 97
高等数学 3 94
大学体育 1 87
大学体育 4 92
# 输出文件
with pd.ExcelWriter(path="结果.xlsx") as writer:
exam_data.to_excel(excel_writer=writer, sheet_name='试题数据', encoding='utf-8', index=False)
student_total_score.to_excel(excel_writer=writer, sheet_name='学生总成绩', encoding='utf-8')
student_semester_total.to_excel(excel_writer=writer, sheet_name='每个学生各学期总成绩', encoding='utf-8')
course_avg_score.to_excel(excel_writer=writer, sheet_name='各门课程平均成绩', encoding='utf-8')
greater_than_avg_student.to_excel(excel_writer=writer, sheet_name='各学期大于本课程平均成绩的学生姓名及成绩', encoding='utf-8')
writer.save()
HTML5 输入y继续输入数字 html数字输入框
2、表单元素-输入框输入框使用input标签。<input>标签,根据type属性的不同,会有不同的表现样式。默认type="text",也就是文本输入框。2.1、文本输入框单行的文本区域,(输入中的换行会被自动去除)。<input type="text"
name="username"
maxlength="6"
readonly="readonly"