You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hnu202509120114 ffc35ce23b
ADD file via upload
2 months ago
README.md Update README.md 2 months ago
untitled4.py ADD file via upload 2 months ago
成绩分析系统 Add 成绩分析系统 2 months ago

README.md

-- coding: utf-8 --

""" Created on Tue Nov 14 22:32:50 2023

@author: 21011 """ from IPython.display import display, HTML import getpass import mysql.connector import asyncio import nest_asyncio import hashlib import pandas as pd import numpy as np import matplotlib.pyplot as plt from datetime import datetime from matplotlib.pyplot import MultipleLocator #%matplotlib inline plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 nest_asyncio.apply() def print_message(*message): print("【{}】 【{}】".format(datetime.now(), message))

def read_csv(): stus = pd.read_csv("stu.csv", index_col= False) #display(stus) return stus read_csv()

df = pd.read_csv("stu.csv") df.head() #display(df)

def add_stu(): while True: print_message("添加学生成绩!") # 添加学号 stu_id_flag = True while stu_id_flag: stu_id = input("请输入学号:") # 判断学号是否为空 if stu_id == "": print_message("学号不能为空,请重新输入!") continue # 判断学号是否正确 if len(stu_id) != 8: print_message("学号长度为8请重新输入") continue # 判断学号是否存在 stus = read_csv() stu_ids = stus["学号"].values.tolist() if int(stu_id) in stu_ids: print_message("该学号已经存在,请重新输入!") continue else: stu_id_flag = False # 添加学生姓名 stu_name_flag = True while stu_name_flag: name = input("请输入学生姓名:") if len(name) < 2 or len(name) > 10: print_message("学生姓名长度为2-10请重新输入") continue else: stu_name_flag = False subjects=["语文", "数学", "英语", "物理", "化学", "生物", "历史", "地理", "政治"]
scores={} # 添加各科成绩 for subject in subjects: stu_flag = True while stu_flag: scores[subject] = input("请输入"+subject+"成绩:") if str.isdigit(scores[subject]): if eval(scores[subject]) < 0 or eval(scores[subject]) > 100: print_message("成绩范围为0-100请重新输入") continue else: stu_flag = False else: print('请输入正确的分数') continue

            stu_dict = {"学号":stu_id,"姓名":name,"语文":scores['语文'],"数学":scores['数学'],"英语":scores['英语'],"物理":scores['物理'],"化学":scores['化学'],"生物":scores['生物'],"历史":scores['历史'],"地理":scores['地理'],"政治":scores['政治']}
            stu_df = pd.DataFrame(stu_dict,index=[0])
            new_stus = stus.append(stu_df, sort=False)
            new_stus.to_csv("stu.csv", index = False)
            print_message("添加学生成绩成功")
            #display(stu_df)     
    break

#add_stu()

def read_someone(student=''): if student=='': print_message("查询学生成绩!") stus = read_csv() #display(stus) stu_names = stus["姓名"].values.tolist() while True: stu_name = input("请输入学生姓名:") if stu_name not in stu_names: print_message("该学生不存在,请重新输入!") continue else: stu = stus.loc[(stus['姓名'] == stu_name),:] print_message("【{}】该学生成绩如下:".format(stu_name)) display(stu) break else: stus = read_csv() stu = stus.loc[(stus['姓名'] == student),:] print_message("【{}】该学生成绩如下:".format(student)) display(stu) #read_someone()

def update_someone(): print_message("修改学生成绩!") stus = read_csv() #display(stus) stu_names = stus["姓名"].values.tolist() while True: # 学生姓名输入逻辑 stu_name_flag = True while stu_name_flag: stu_name = input("请输入待修改成绩学生姓名:") if stu_name not in stu_names: print_message("该学生不存在,请重新输入!") continue else: stu_name_flag = False # 学生课程输入逻辑 stu_subject_flag = True while stu_subject_flag: subject = input("请输入【{}】要修改的科目:".format(stu_name)) if subject not in ["语文","数学","英语","物理","化学","生物","历史","地理","政治"]: print_message("课程错误,请重新输入") continue else: stu_subject_flag = False # 学生成绩输入逻辑 stu_grade_flag = True while stu_grade_flag: grade = input("请输入【{}】要修改的分数:".format(subject)) if int(grade) not in range(0,100+1): print_message("成绩输入超出,请重新输入") continue else: stu_grade_flag = False # 获取输入课程index subject_index = list(stus.columns).index(subject) # 获取学生index stu_index = stus.loc[(stus['姓名'] == stu_name),:].index[0] # 修改对应index上的成绩数值 stus.iloc[stu_index,subject_index] = int(grade) stus.to_csv("stu.csv", index = False) print_message("成绩修改完成") # 展示修改后的成绩 new_stu = stus.loc[(stus['姓名'] == stu_name),:] #display(new_stu) break

#update_someone()

def delete_someone(): print_message("删除学生成绩!") stus = read_csv() #display(stus) stu_names = stus["姓名"].values.tolist() while True: # 学生姓名输入逻辑 stu_name_flag = True while stu_name_flag: stu_name = input("请输入待删除成绩学生姓名:") if stu_name not in stu_names: print_message("该学生不存在,请重新输入!") continue else: stu_name_flag = False stu = stus.loc[(stus['姓名'] == stu_name),:] #display(stu) delete_flag = input("确认是否删除学生【{}】成绩y/n".format(stu_name_flag)) if delete_flag == "y": save_books = stus.drop(stus[stus['姓名']== stu_name].index) save_books.to_csv("stu.csv", index = False) #display(save_books) print_message("【{}】成绩删除成功".format(stu_name)) break else: print_message("退出删除") break

#delete_someone()

def grade_bar_sort(df): """学生总成绩柱状图""" # 获取学生的总成绩 grade = df.iloc[:, 2:].sum(axis=1) # 获取对应成绩的学生姓名 name = df.iloc[:, 1] # 数据合并 zf_df = pd.concat([name, grade], axis=1) zf_df.columns = ['name', 'gross_score']

# 根据学生总成绩进行降序排序
sort_df = zf_df.sort_values(by=['gross_score'], ascending=False)

print(sort_df)

width,height,size = 28, 12, 18
# 默认画布大小
plt.figure()                        
plt.figure(figsize=(width,height))
# 绘制柱形图
plt.bar(range(0, len(sort_df)*6, 6), sort_df.iloc[:, 1], width=4)
# 定义x轴的间隔rotation文字角度
plt.xticks(range(0, len(sort_df)*6, 6), sort_df.iloc[:, 0], rotation=90, fontsize=size)
# 柱子上的数字显示
for a,b in zip(np.arange(0, len(sort_df.iloc[:, 0])*6, 6), sort_df.iloc[:, 1]):   
     plt.text(a,b,'%d'%b,ha='center',va='bottom',fontsize=size);
plt.show();

#grade_bar_sort(df)

def grade_barh_sort(df): """学生总成绩水平柱状图""" # 获取学生总成绩 grade = df.iloc[:, 2:].sum(axis=1) # 获取学生成绩对应姓名 name = df.iloc[:, 1] # 数据合并 zf_df = pd.concat([name, grade], axis=1) zf_df.columns = ['name', 'gross_score'] # 根据学生总成绩进行降序排序 sort_df = zf_df.sort_values(by=['gross_score'])

print(sort_df)

width,height,size = 20, 24, 12
# 默认画布大小
plt.figure()                        
plt.figure(figsize=(width,height))
# 绘制水平柱状图
plt.barh(range(0, len(sort_df)*3, 3), sort_df.iloc[:, 1], height=2)
# 设置y轴的间隔
plt.yticks(range(0, len(sort_df)*3, 3), sort_df.iloc[:, 0], fontsize=size)
# 柱子上的数字显示
for a,b in zip(np.arange(0, len(sort_df.iloc[:, 0])*3, 3), sort_df.iloc[:, 1]):   
     plt.text(b+10,a-0.5,'%d'%b,ha='center',va='bottom',fontsize=size);
plt.show();

#grade_barh_sort(df)

打印数据后五行

#df.tail()

def grade_pass_count(df): """学生各科成绩等级比例扇形图""" # 获取学生各科成绩 subjects = df.iloc[:, 1:] width,height = 24, 18 # 默认画布大小
plt.figure(figsize=(width,height)) # 定义学生成绩等级 text = ["优秀","良好","中等","及格","不及格"] # 对每科学生成绩进行等级划分 for i,name in enumerate(subjects.iloc[:, 1:].columns): # 等级条件,>=90为优秀<90&>=80为良好<80&>=70为中等<70&>=60为及格<60为不及格 a = len(subjects[subjects[name]>=90]) b = len(subjects[(subjects[name]<90) & (subjects[name]>=80)]) c = len(subjects[(subjects[name]<80) & (subjects[name]>=70)]) d = len(subjects[(subjects[name]<70) & (subjects[name]>=60)]) e = len(subjects[subjects[name]<60])

    #print(name,a,b,c,d,e,text)
    data = [a,b,c,d,e]
    #print(data, text)
    # 绘制饼图
    plt.subplot(3, 3, i + 1)  # 3x3 网格中的第 (i+1) 个位置
    plt.pie(data, labels=text, autopct="%.2f%%")
    plt.title(name)
plt.show()

#grade_pass_count(df)

def grade_max_bar(df): """各科学生成绩前三柱状图""" # 获取学生各科成绩 subjects = df.iloc[:, 1:] # 获取各科的名字 names = list(subjects.iloc[:, 1:].columns) datas = [] # 获取各科成绩前三的数据列表 for name in subjects.iloc[:, 1:].columns: max3 = subjects.sort_values(by=name,ascending=False)'姓名', name[:3] d = [x[0] for x in list(max3name.values)] datas.append(d) # 转换成df结构 data_df = pd.DataFrame(np.array(datas)) width,height = 26, 18 # 默认画布大小 plt.figure()
plt.figure(figsize=(width,height))

x =list(range(0, len(names)*3, 3))
total_width, n = 0.8, 2
width = total_width / n

# 绘制各科第一名成绩柱形图
plt.bar(x, data_df[0], width=width, label='第一名',tick_label=names,fc = 'y')
# 柱子上的数字显示
for a,b in zip(np.arange(0, len(data_df[0])*3, 3), data_df[0]):   
     plt.text(a,b,'%d'%b,ha='center',va='bottom',fontsize=12);
for i in range(len(x)):
    x[i] = x[i] + width
# 绘制各科第一名成绩柱形图
plt.bar(x,data_df[1], width=width, label='第二名',tick_label=names, fc = 'r')
# 柱子上的数字显示
for a,b in zip(np.arange(0, len(data_df[1])*3, 3), data_df[1]):   
    plt.text(a+width,b,'%d'%b,ha='center',va='bottom',fontsize=12);
for i in range(len(x)):
    x[i] = x[i] + width
# 绘制各科第一名成绩柱形图
plt.bar(x,data_df[2], width=width, label='第三名',tick_label=names, fc = 'g')
# 柱子上的数字显示
for a,b in zip(np.arange(0, len(data_df[2])*3, 3), data_df[2]):   
    plt.text(a+width*2,b,'%d'%b,ha='center',va='bottom',fontsize=12);
plt.legend()
plt.show()

#grade_max_bar(df)

def grade_max_polt(df): """各科学生成绩前三折线图""" # 获取学生各科成绩 subjects = df.iloc[:, 1:] # 获取学生各科名字 names = list(subjects.iloc[:, 1:].columns) datas = [] # 获取各科成绩前三的数据列表 for name in subjects.iloc[:, 1:].columns: max3 = subjects.sort_values(by=name,ascending=False)'姓名', name[:3] d = [x[0] for x in list(max3name.values)] datas.append(d) # 转换为df数据类型 data_df = pd.DataFrame(np.array(datas)) width,height = 20, 10 # 默认画布大小 plt.figure()
plt.figure(figsize=(width,height)) # 绘制折线图 plt.plot(names, datas) plt.ylim(90, 100) # 设置图例 plt.legend(['第一名','第二名','第三名']) plt.show() #grade_max_polt(df)

def grade_max_bars(df): """各科学生成绩前三详细柱状图""" # 获取学生各科成绩 subjects = df.iloc[:, 1:] # 获取各科名字 infos = list(subjects.iloc[:, 1:].columns) names = [] k = [] n = 0 # 获取各科学生成绩前三、对应学生姓名 for name in subjects.iloc[:, 1:].columns: max3 = subjects.sort_values(by=name,ascending=False)'姓名', name[:3] d = [x[0] for x in max3'姓名'.values]

print(max3name.values[0].tolist())

    h = [x[0] for x in list(max3[[name]].values)]
    k.append(h)
    names.append(d)
    
    width,height = 20, 10
    # 默认画布大小
    plt.figure()                        
    plt.figure(figsize=(width,height))
    # 定义子图
    plt.subplot(331+n)
    # 绘制柱形图
    plt.bar(range(len(max3)), k[n], tick_label=names[n])
    # 显示柱形图数据
    for a,b in zip(np.arange(len(k[n])), k[n]):   
        plt.text(a,b,'%d'%b,ha='center',va='bottom',fontsize=12);
    n+=1
    # 显示每科标签名字
    plt.title(name)
    # 定义y轴范围
    plt.ylim(0,110)
plt.show()

#grade_max_bars(df)

def grade_polar(df,student): # 获取成绩 student_scores = df[df['姓名'] == student].iloc[:, 2:].values.flatten() student_scores = list(student_scores) student_scores.append(student_scores[0]) # 准备角度值,首尾相连 dim_num = 9 radians = np.linspace(0, 2 * np.pi, dim_num, endpoint=False) radians = np.concatenate((radians, [radians[0]])) # 绘制多边形(雷达图) plt.polar(radians,student_scores) #设置维度坐标(首尾相连) radar_labels =list(df.columns[2:]) radar_labels = np.concatenate((radar_labels, [radar_labels[0]])) # 设置极坐标的标签 angles = radians * 180/np.pi # 弧度转角度 plt.thetagrids(angles, labels=radar_labels) # 设置新的刻度标签 # 填充多边形 plt.fill(radians,student_scores,alpha=0.25) # 6.展示图表 plt.show()

async def grade_averge_polar(df): # 获取各科的平均成绩 grade = df.iloc[:, 2:].sum(axis=0)/(df.shape[0]) grade = np.concatenate((grade, [grade.iloc[0]])) # 准备角度值,首尾相连 dim_num = 9 radians = np.linspace(0, 2 * np.pi, dim_num, endpoint=False) radians = np.concatenate((radians, [radians[0]])) # 绘制多边形(雷达图) plt.polar(radians,grade) #设置维度坐标(首尾相连) radar_labels =list(df.columns[2:]) radar_labels = np.concatenate((radar_labels, [radar_labels[0]])) # 设置极坐标的标签 angles = radians * 180/np.pi # 弧度转角度 plt.thetagrids(angles, labels=radar_labels) # 设置新的刻度标签 # 填充多边形 plt.fill(radians,grade,alpha=0.25) # 6.展示图表 plt.show() #grade_averge_polar(df)

async def grade_average_line_plot(df): # 获取各科的平均成绩 grade = df.iloc[:, 2:].sum(axis=0)/(df.shape[0]) # 获取各科名字 subjects = list(df.columns[2:])

# 绘制折线图
plt.plot(subjects, grade, marker='o')  # 使用圆点标记每个数据点

# 设置图表标签和标题
plt.xlabel('科目')
plt.ylabel('平均分')
plt.title('各科平均成绩折线图')

# 展示图表
plt.show()

#grade_average_line_plot(df)

async def fetch_data(): df = pd.read_csv("stu.csv") df.head() return df

async def grade_average_bar_chart(df): # 获取各科的平均成绩 grade = df.iloc[:, 2:].mean(axis=0) # 获取各科名字 subjects = list(df.columns[2:])

# 绘制柱状图
plt.bar(subjects, grade)

# 设置图表标签和标题
plt.xlabel('科目')
plt.ylabel('平均分')
plt.title('各科平均成绩柱状图')

# 设置y轴范围从0开始
plt.ylim([0, max(grade)+10])

# 展示图表
plt.show()

#grade_average_bar_chart(df)

async def averge(): df = await fetch_data() await asyncio.gather( grade_averge_polar(df), grade_average_line_plot(df), grade_average_bar_chart(df) )

html = """

"""

#身份校验 def authenticate(): authorized_users = { "teacher": "ab3fe4003f14e3ef573417f95e47d4985c482eadd139c08b3758eeae7cc60b9d", #密码为 "password123" "student": "c0067d4af4e87f00dbac63b6156828237059172d1bbeac67427345d6a9fda484" #密码为 "password" }

user = input("请输入用户名: ")
password = getpass.getpass("Enter your password: ")

# 使用hashlib来计算密码的SHA-3散列值
hashed_password = hashlib.sha3_256(password.encode()).hexdigest()

if user in authorized_users and hashed_password == authorized_users[user]:
    print("身份验证成功!")
    return user
else:
    print("身份验证失败,请检查用户名和密码!")
    return False

def user_access(): attempts = 3 while attempts > 0: user=authenticate() if user: return user else: attempts -= 1 print(f"剩余尝试次数: {attempts}")

print("尝试次数超过限制,退出程序。")
return False

user1=user_access()

if_continue=True if user1=='teacher': print('Welcome!') while if_continue: read_csv() df = pd.read_csv("stu.csv") df.head() x=input('0:退出\n1:添加\n2:查找\n3:删除\n4:绘图\n') if x=='0': if_continue=False elif x=='1': add_stu() elif x=='2': read_someone() elif x=='3': delete_someone() elif x=='4': y=input('0:退出\n1:学生总成绩柱状图\n2学生总成绩水平柱状图\n3:学生各科成绩等级比例扇形图\n4:各科学生成绩前三柱状图\n5:各科学生成绩前三折线图\n6:各科学生成绩前三详细柱状图\n7:各科平均成绩图\n') if y=='0': if_continue=False elif y=='1': grade_bar_sort(df) elif y=='2': grade_barh_sort(df) elif y=='3': grade_pass_count(df) elif y=='4': grade_max_bar(df) elif y=='5': grade_max_polt(df) elif y=='6': grade_max_bars(df) elif y=='7': asyncio.run(averge()) pass else: print('请确保规范输入') continue else: print('请确保规范输入') continue elif user1=='student': stu=input('请输入姓名:') read_someone(stu) grade_polar(df,stu)