完成以下程序的设计:某体操比赛共有10名运动员参加,12名评委将根据运动员表现进行评分(满分10分),请编写Python程序,解决下列问题:
1).每个运动员评分中去掉一个最高分和一个最低分,计算平均成绩,然后给出运动员排名;
2).尽量减少人为因素,组委会筛选出打最高分和最低分次数最多的前两位评委,如果某位运动员的最高分或最低分是由筛选出的评委打的,就去掉这个评分,然后计算平均成绩后排名。(与原题目不同,根据老师的要求改编)
博主是python小白,如有错误还请指出。
思路:将数据转换为矩阵储存来做
这里用类来做
定义GUI界面:
import re #后续进行数据处理使用
import numpy as np #后续进行数据处理使用
from tkinter import * #GUI需要调用
from tkinter import messagebox
from tkinter.filedialog import *
class show_rank(Frame):
def __init__(self,master = None):
Frame.__init__(self,master)
self.grid()
self.CreateWindows()
def CreateWindows(self): #创建子组件
self.arm1 = Frame(self) #界面分为上中下三个Frame,arm1放第一行按钮
self.arm1.pack()
self.arm2 = Frame(self) #arm2放第二行标签和文本框
self.arm2.pack()
self.arm3 = Frame(self) #arm3放第第三行按钮
self.arm3.pack()
self.str1 = StringVar() #创建StringVar()对象,str1
self.str1.set('A') #设置初始值为’查看排名‘
self.way1 = Radiobutton(self.arm1, text = '查看排名', value = 'A', variable = self.str1) #单选按钮
self.way2 = Radiobutton(self.arm1, text = '优化', value = 'B', variable = self.str1)
self.find_file = askopenfilename(title='askopenfilename', filetypes=[('运动员得分数据','.txt')]) #选择文件
self.lab1 = Label(self.arm2, text = '文件路径') #创建label组件对象,显示文本为‘文件路径’
self.mas1 = Message(self.arm2, bg = 'black', fg = 'white', width = 200) #创建message组件对象,背景为黑,字体为白色
self.mas1.config(text = self.find_file) #显示文本为文件的绝对路径
self.butselect = Button(self.arm3, text = '查看', width = 8) #创建’查看’按钮
self.butselect['command'] = self.get_rank
self.butquit = Button(self.arm3,text='退出',width = 8,command=root.destroy) #创建‘取消’按钮
self.butselect.pack(side = LEFT) #pack调整位置
self.butquit.pack(side = LEFT)
self.way1.pack(side = LEFT)
self.way2.pack(side = LEFT)
self.lab1.pack(side = LEFT)
self.mas1.pack(side = LEFT)
def get_rank(self): #定义查看事件的处理程序
self.data_solve() #处理数据
if self.str1.get() == 'A': #选择直接输出排名(第一问)
self.get_rank1() #计算排名
messagebox.showinfo('排名',self.fin1_text)
if self.str1.get() == 'B': #选择优化后输出排名(第二问)
self.get_rank2() #计算排名
messagebox.showinfo('排名',self.fin2_text)
数据处理:
将导入的文件转换为float类型的矩阵,每一行存放运动员的得分。
def data_solve(self): #读取数据源
filename = self.find_file
with open(filename) as f: #打开文件
self.data1 = f.read() #读取文件
self.data2 = list(map(float,re.findall('d.d',self.data1))) #将文本中的数字(float)提出
step = 12 #将每个运动员的得分分离开
self.data2 = np.mat([self.data2[i:i+step] for i in range(0,len(self.data2),step)])
self.Grades1 = self.data2.tolist() #第一组数据,第一问用
self.Grades2 = list.copy(self.Grades1) #第二组数据,第二问用
self.Grades3 = list.copy(self.Grades1) #第三组数据,第三问用
第一问:每个运动员评分中去掉一个最高分和一个最低分,计算平均成绩,然后给出运动员排名。
def data_solve(self): #读取数据源
filename = self.find_file
with open(filename) as f: #打开文件
self.data1 = f.read() #读取文件
self.data2 = list(map(float,re.findall('d.d',self.data1))) #将文本中的数字(float)提出
step = 12 #将每个运动员的得分分离开
self.data2 = np.mat([self.data2[i:i+step] for i in range(0,len(self.data2),step)])
self.Grades1 = self.data2.tolist() #第一组数据,第一问用
#self.Grades_mas = np.transpose(self.data2).tolist() #将每个评为的评分分离开
self.Grades2 = list.copy(self.Grades1) #第二组数据,第二问用
self.Grades3 = list.copy(self.Grades1) #第三组数据,第三问用
第二问:尽量减少人为因素,组委会筛选出打最高分和最低分次数最多的前两位评委,如果某位运动员的最高分或最低分是由筛选出的评委打的,就去掉这个评分,然后计算平均成绩后排名。
def get_rank2(self): #优化后得出排名
master_max = np.zeros(12,dtype=int).tolist() #判断打最高分异常的教师
master_min = np.zeros(12,dtype=int).tolist() #判断打最低分异常的教师
for mas in range(0,10):
master_max[self.Grades2[mas].index(max(self.Grades2[mas]))] += 1 #记录打最高分的评委
master_max[self.Grades1[mas].index(max(self.Grades1[mas]))] += 1 #记录打第二高分的评委
master_min[self.Grades2[mas].index(min(self.Grades2[mas]))] += 1 #记录打最低分的评委
master_min[self.Grades1[mas].index(min(self.Grades1[mas]))] += 1 #记录打第二低分的评委
illegal_master_max = [] #存放打最高分不合格的评委
illegal_master_min = [] #存放打最低分不合格的评委
while (True):
illegal_master_max.append(master_max.index(max(master_max))) #选出高分中不合格评为
illegal_master_min.append(master_min.index(max(master_min))) #选出低分中不合格评为
if (len(illegal_master_max) == 2) and (len(illegal_master_min) == 2): #选出前两名后退出
break
master_max[master_max.index(max(master_max))] = 0 #将当前打高分最多的评委赋值为0,方便判断下一位打高分最多的评委
master_min[master_min.index(max(master_min))] = 0 #将当前打低分最多的评委赋值为0,方便判断下一位打低分最多的评委
temp2 = [] #存放运动员的平均分
for sp in range(0,10):
Grade_max_master = self.Grades3[sp].index(max(self.Grades3[sp])) #得到运动员得最高分对应评委的下标
Grade_min_master = self.Grades3[sp].index(min(self.Grades3[sp])) #得到运动员得最低分对应评委的下标
if Grade_max_master in illegal_master_max : #判断最高分是否由不合格评委打的
self.Grades3[sp].remove(max(self.Grades3[sp]))
if Grade_min_master in illegal_master_min : #判断最低分是否由不合格评委打的
self.Grades3[sp].remove(min(self.Grades3[sp]))
temp2.append(np.mean(self.Grades3[sp])) #计算优化后各运动员的平均分
self.fina2 = sorted(enumerate(temp2), key=lambda x:x[1]) #得到每个运动员的排名
self.fin2_text = '去掉不合格评委和相应评分后得出运动员排名:
'
for sps in range(0,10):
self.fin2_text += '第{:2d}名为{:2d}号运动员,得分为{:.2f}
'.format(sps+1,self.fina2[9-sps][0]+1,self.fina2[9-sps][1])
主程序:
root = Tk()
root.title('查看排名系统') #定义GUI标题
root.geometry('300x100+800+400') #定义GUI界面大小和显示位置
win = show_rank(master=root) #创建类对象win
win.mainloop()
实验数据:
8.9 9.3 7.9 9.0 8.8 6.5 8.4 6.6 8.2 9.1 9.2 8.8
9.0 7.8 8.7 8.9 9.0 7.6 8.1 6.5 9.6 7.7 6.9 7.5
5.8 7.4 5.3 7.3 9.1 7.9 6.7 6.8 7.8 8.0 7.6 8.1
9.0 7.9 8.3 9.2 7.8 9.2 6.4 6.9 5.8 7.7 8.2 9.0
9.0 8.6 6.9 7.5 5.8 8.6 7.4 6.8 8.4 7.8 9.2 6.7
7.5 9.7 8.9 9.6 7.8 6.5 7.1 8.0 6.6 8.0 8.5 8.9
8.7 7.9 8.8 9.2 7.6 9.1 6.8 9.0 7.8 9.4 8.3 9.2
8.9 7.8 8.7 8.6 8.5 7.4 6.5 9.4 7.7 8.9 6.9 8.4
7.8 8.5 7.6 6.6 8.7 7.8 9.5 7.8 9.9 7.3 8.9 7.7
8.9 7.9 8.8 9.0 7.9 9.2 8.7 8.7 8.9 7.9 8.7 7.7
第一次在CSDN发表文章,不怎么会用Markdown,记录一下。
博主是python小白,如有错误还请指出。