前言
笔者在学完简单的Python入门知识,尝试通过一个例子将学习到的一些知识点进行总结与应用,在这里涉及到:
1.pandas读取xlsx文件数据,对数据进行合并与分组,pandas的一些统计函数,pandas官网;
2.应用matplotlib第三方库进行频率直方图、柱状图、并列柱状图的绘制,Matplotlib官网;
3.组合数据类型的使用(列表、集合、字典)
4.控制结构与函数的使用
目录
本文用到的Python库
import os
import time
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import turtle
import xlrd
filename='student.txt'
一、多重索引模块
def show():
student_lst=[]
if os.path.exists(filename):
with open(filename,'r',encoding='utf-8') as rfile:
students=rfile.readlines()
if students:
for item in students:
d=dict(eval(item))
student_lst.append(d)
show_student(student_lst)
number=0
for item in students:
d=eval(item)
d=pd.Series(d)
if number==0:
d1=d
else:
d1=pd.concat([d1,d],join='outer',axis=1)
number+=1
d2=d1.T
d2.index=list(range(d2.shape[0]))
df=d2
d1=df.groupby(by=[df["classid"],df["gender"]])
type_s=[]
me_s=[]
Ch=input('请选择一个科目:')
for i,j in d1:
type_s.append(i)
me_s.append(round((j[Ch]).astype(int).mean(),2))
name_list=['11班','12班','14班','15班','16班']
num_list=me_s[::2]
num_list1=me_s[1::2]
x =list(range(len(num_list)))
total_width, n = 0.6, 2
width = total_width / n
plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签
plt.rcParams['axes.unicode_minus']=False
plt.bar(x, num_list, width=width, label='boy',fc = 'y')
for i in range(len(x)):
x[i] = x[i] + width
plt.bar(x, num_list1, width=width, label='girl',tick_label = name_list,fc = 'r')
plt.legend()
plt.xlabel('班级')
plt.ylabel('{}课程考试班级平均成绩'.format(Ch))
plt.savefig('fenbutu.jpg')
plt.show()
df=d2
Ch=input('请选择一个科目:')
d3=df[Ch].astype(int).values
plt.hist(d3,d3.max()-d3.min()+1)
plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签
plt.rcParams['axes.unicode_minus']=False
plt.xlabel('分数')
plt.ylabel('人数')
plt.savefig('pinlvzhifangtu.jpg')
plt.show()
else:
print("暂未保存数据信息......")
按班级和性别两个选项,统计得到的C考试的平均分柱状图如下图所示:
下图是Python成绩的频率分布图:
二、排序模块
def sort():
with open(filename,'r',encoding='utf-8') as rfile:
student=rfile.readlines()
number=0
for item in student:
d=eval(item)
d=pd.Series(d)
if number==0:
d1=d
else:
d1=pd.concat([d1,d],join='outer',axis=1)
number+=1
d2=d1.T
d2.index=list(range(d2.shape[0]))
answer=input("按照什么排序(java,python,english,C)")
d2.sort_values(answer,inplace=True,ascending=False)
print(d2.head(10))
time.sleep(3)
C成绩前十名如下图所示:
三、学生信息统计模块
def total():
if os.path.exists(filename):
with open(filename,'r',encoding='utf-8') as rfile:
students=rfile.readlines()
if students:
print(f'一共有{len(students)}名学生')
number=0
for item in students:
d=eval(item)
d=pd.Series(d)
if number==0:
d1=d
else:
d1=pd.concat([d1,d],join='outer',axis=1)
number+=1
d2=d1.T
d2.index=list(range(d2.shape[0]))
d2.sort_values("java",inplace=True,ascending=False)
d3=d2.groupby(by="classid").count()["name"]
_x=d3.index
print(_x)
_y=d3.values
format_title='{:^12}\t{:^12}\t{:^12}\t{:^12}\t{:^12}\t'
format_data='{:^12}\t{:^12}\t{:^12}\t{:^12}\t{:^12}\t'
print(format_title.format(_x[0],_x[1],_x[2],_x[3],_x[4]))
print(format_data.format(_y[0],_y[1],_y[3],_y[3],_y[4]))
plt.figure(figsize=(8,4),dpi=80)
plt.bar(range(len(_x)),_y,width=0.1,color="orange")
plt.xticks(range(len(_x)),_x,fontsize=15,rotation=45)
plt.show()
else:
print('还没有录入学生信息数据')
else:
print("暂未保存数据信息......")
下图是统计到的各个班级的总人数
下面这个函数用来统计选择的科目的最大值,最小值,平均值,标准差,统计该门考试的每班考试成绩第一名
def tongji():
#if os.path.exists(filename):
with open(filename,'r',encoding='utf-8') as rfile:
students=rfile.readlines()
#else:
#print('还没有录入学生信息,即将返回主菜单!!!')
#return
number=0
for item in students:
d=eval(item)
d=pd.Series(d)
if number==0:
d1=d
else:
d1=pd.concat([d1,d],join='outer',axis=1)
number+=1
d2=d1.T
d2.index=list(range(d2.shape[0]))
d2.sort_values("java",inplace=True,ascending=False)
d3=d2.groupby(by="classid")
choice=input('请选择要查询的科目(Python,Java,English,C)')
for i,j in d3:
print('\t\t\t\t{}班的{}成绩统计结果'.format(i,choice))
format_title='{:^12}\t{:^12}\t{:^12}\t{:^12}\t'
format_data='{:^12}\t{:^12}\t{:^12}\t{:^12}\t'
print(format_title.format('最大值','最小值','平均值','标准差'))
print(format_data.format(j[choice].astype(int).max(),j[choice].astype(int).min(),\
round(j[choice].astype(int).mean(),2),round(j[choice].astype(int).std(),2)))
print('\t{}班{}考试成绩第一名是{}同学'.format(i,choice,j["name"][j[choice]==j[choice].max()].values))
print("*"*80)
统计结果如下图所示:
四、修改信息模块
程序按照这个流程进行计算,首先要判断文件是否存在,是否为空,文件若存在,接着以‘w’的方式打开txt文件,文件指针将从开头开始编辑文档,即原有内容会被删除。
def modify():
show()
if os.path.exists(filename):
with open(filename,'r',encoding='utf-8') as rfile:
student_old=rfile.readlines()
else:
return
student_id=input('请输入要修改的学生的ID:')
with open(filename,'w',encoding='utf-8') as wfile:
number=0
flag=[]
for item in student_old:
number+=1
d=eval(item)
if d['id']==int(student_id):
print('找到学生信息,可以修改他的信息了!')
flag.append(number)
chioce=[]
c_count=0
while True:
chioce1=input('请输入要修改的选项(id,name,classid,gender,english,python,java,C)')
c_count=c_count+1
answer=input('是否要增加其他的选项?y/n\n')
chioce.append(chioce1)
if answer=='y' or answer=='Y':
continue
else:
print('您选择了{}个选项,是{}'.format(c_count,chioce))
break
while True:
try:
for item in chioce:
d[item]=input('请输入{}:'.format(item))
except:
print('您的输入有误,请重新输入')
else:
break
wfile.write(str(d)+'\n')
print('修改成功')
else:
wfile.write(str(d)+'\n')
answer=input('是否继续修改其他学生信息?y/n\n')
if answer=='y':
modify()
五、录入信息模块
因为一个个地录入数据很麻烦,这里在excel用随机数产生了一个100*8的矩阵,后面基于这个矩阵进行计算。
应用xlrd和pandas库读取excel中的数据,并将读取的数据写入“student.txt”文件中。
import xlrd
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
def save(lst):
try:
stu_txt=open(filename,'a',encoding='utf-8')
except:
stu_txt=open(filename,'w',encoding='utf-8')
for item in lst:
stu_txt.write(str(item)+'\n')
stu_txt.close()
filename='student.txt'
df=pd.read_excel('学生信息管理系统.xlsx')
student_list=[]
for i in range(df.shape[0]):
student={'id':str(df["id"][i]),'name':str(df["name"][i]),"gender":str(df["gender"][i]),'classid':str(df["classid"][i]),\
'english':str(df["English"][i]),'python':str(df["Python"][i]),'java':str(df["Java"][i]),'C':str(df["C"][i])}
student_list.append(student)
save(student_list)
这里在录入数据时,需要判断数据是否空,判断输入数据是否有误。
def insert():
student_list=[]
while True:
id=input('请输入ID(如1001)')
if not id:
break
name=input('请输入姓名:')
if not name:
break
classid=input('请输入班级(如0011):')
if not classid:
break
gender=input('请输入性别:')
if not gender:
break
try:
english=int(input('请输入英语成绩:'))
python=int(input('请输入Python成绩'))
java=int(input('请输入Java成绩'))
C=int(input('请输入C成绩'))
except:
print('输入无效,不是整数类型,请重新输入')
continue
student={'id':id,'name':name,'gender':gender,'classid':classid,\
'english':english,'python':python,'java':java,'C':C}
student_list.append(student)
answer=input('是否继续添加?y/n\n')
if answer=='y' or answer=='Y':
continue
else:
break
save(student_list)
print('学生信息录入完毕')
六、将数据写入txt文件模块
6.1 Python open() 函数
最常用的有两个参数: open(filename, mode)。
第一个参数是包含文件名的字符串。第二个参数是另一个字符串,其中包含一些描述文件使用方式的字符。mode 参数是可选的;省略时默认为 ‘r’。
mode | 描述 |
---|---|
r | 只能读取 |
w | 只能写入(已存在的同名文件会被删除) |
a | 打开文件以追加内容,任何写入的数据会自动添加到文件的末尾 |
r+ | 打开文件进行读写 |
在处理文件对象时,最好使用 with 关键字。 优点是当子句体结束后文件会正确关闭,即使在某个时刻引发了异常。
6.2 函数
以“a”的方式打开文档,将新的信息增加到文档。
def save(lst):
try:
stu_txt=open(filename,'a',encoding='utf-8')
except:
stu_txt=open(filename,'w',encoding='utf-8')
for item in lst:
stu_txt.write(str(item)+'\n')
stu_txt.close()
七、查询信息模块
7.1 查询函数
def search():
student_query=[]
while True:
id=''
name=''
if os.path.exists(filename):
mode=input('ID查询请输入1,姓名查询请输入2:')
if mode=='1':
id=input('请输入学生ID:')
elif mode=='2':
name=input('请输入学生姓名:')
else:
print('您的输入有误,请重新输入')
search()
with open(filename,'r',encoding='utf-8') as rfile:
student=rfile.readlines()
for item in student:
d=eval(item)
if id!='':
if d['id']==int(id):
student_query.append(d)
elif name!='':
if d['name']==name:
student_query.append(d)
show_student(student_query)
student_query.clear()
answer=input('是否要继续查询?y/n\n')
if answer=='y' or answer=='Y':
continue
else:
break
else:
print('暂无保存学生信息')
return
7.2展示结果函数
7.2.1 print函数的使用
7.2.1.1不换行输出
当使用print函数时,它会自动打印一个换行符,这会导致输出提前进入下一行。如果不想在使用print函数后换行,可以在调用print函数时传递一个特殊的参数end=“anyendingstring”。
for i in range(30):
print(i,end='-')
输出结果为:
7.2.2.2 格式化字符串字面值
import math
for i in range(30):
print(i,end='-')
print('\n')
print(f'The value of pi is approximately {math.pi:.3f}.')
在 ‘:’ 后传递一个整数可以让该字段成为最小字符宽度。这在使列对齐时很有用。
import math
for i in range(30):
print(i,end='-')
print('\n')
print(f'The value of pi is approximately {math.pi:.3f}.')
print('我今年已经{:^10.3f}了。'.format(20))
print('半径为4厘米的圆的面积为{:^15}。'.format(str(round(math.pi*4*4,4))+'平方厘米'))
print("baidu","www","com",sep='.')
可以通过sep="string"来设置间隔符。
7.3函数
def show_student(lst):
if len(lst)==0:
print('没有查询到学生信息,无数据显示!!!')
return
format_title='{:^6}\t{:^12}\t{:^8}\t{:^8}\t{:^10}\t{:^10}\t{:^8}\t{:^8}\t{:^8}\t'
print(format_title.format('id','name','gender','class','english','python','java','C','总成绩'))
format_data='{:^6}\t{:^12}\t{:^8}\t{:^8}\t{:^10}\t{:^10}\t{:^8}\t{:^8}\t{:^8}\t'
for item in lst:
print(format_data.format(item.get('id'),item.get('name'),item.get('gender'),item.get('classid'),item.get('english'),\
item.get('python'),item.get('java'),item.get('C'),\
int(item.get('english'))+int(item.get('python'))+int(item.get('java'))+int(item.get('C'))))
八、主界面函数
def menum():
a='学生信息管理系统'
c1=a.center(81,'=')
print(c1)
b='功能菜单'
c2=b.center(84,'=')
print(c2)
print("\t\t\t\t 1.录入学生信息")
print("\t\t\t\t 2.查找学生信息")
print("\t\t\t\t 3.删除学生信息")
print("\t\t\t\t 4.修改学生信息")
print("\t\t\t\t 5.成绩排序")
print("\t\t\t\t 6.统计学生总人数,每个成绩平均分,最高分,最低分")
print("\t\t\t\t 7.显示所有学生信息,成绩分布图(按性别或按班级)")
print("\t\t\t\t 0.退出")
print("-"*86)
九、删除信息模块
def delete():
show_IDandName()
while True:
student_id=input('请输入要删除的学生的ID:')
if student_id!='':
if os.path.exists(filename):
with open(filename,'r',encoding='utf-8') as file:
student_old=file.readlines()
else:
student_old=[]
flag=False
if student_old:
with open(filename,'w',encoding='utf-8') as wfile:
d={}
for item in student_old:
d=dict(eval(item))
if d['id']!=student_id:
wfile.write(str(d)+'\n')
else:
flag=True
if flag:
print(f'id为{student_id}的学生信息已被删除')
else:
print(f'没有找到ID为{student_id}的学生信息')
else:
print('无学生信息')
break
answer=input('是否继续删除y/n\n?')
if answer=='y' or answer=='Y':
continue
else:
break
这个代码用来显示目前所有的学生信息ID和姓名。
def show_IDandName():
student_list=[]
with open(filename,'r',encoding='utf-8') as rfile:
student_old=rfile.readlines()
if student_old==[]:
print('没有查询到学生信息,无数据显示!!!')
return
for item in student_old:
d=eval(item)
student_list.append(d)
format_title='{:^6}\t{:^12}\t'
format_data='{:^6}\t{:^12}\t'
print(format_title.format('id','name'))
for item in student_list:
print(format_data.format(item.get('id'),item.get('name')))
十、主函数模块
def txtmain():
while True:
menum()
choice=int(input('请选择'))
if choice in list(range(8)):
if choice==0:
answer=input('您确定要退出系统吗?y/n\n')
if answer=='y' or answer=='Y':
print('谢谢您的使用!!!')
break
else:
continue
elif choice==1:
insert()
elif choice==2:
search()
elif choice==3:
delete()
elif choice==4:
modify()
elif choice==5:
sort()
elif choice==6:
total()
tongji()
elif choice==7:
show()
十一、用集合统计班级个数
import pandas as pd
import numpy as np
filename='student.txt'
with open(filename,'r',encoding='utf-8') as rfile:
students=rfile.readlines()
number=0
for item in students:
d=eval(item)
d=pd.Series(d)
if number==0:
d1=d
else:
d1=pd.concat([d1,d],join='outer',axis=1)
number+=1
d2=d1.T
d2.index=list(range(d2.shape[0]))
d3=set(d2["classid"])
t1=[i+'班' for i in d3]
print('总共有{}个班级,分别是{}'.format(len(d3),t1))
十二、系统运行截图
选择界面
在键盘中输入相应的数字,就可以进入相应的模块。
输入0,退出系统。