完成以下程序的設計:某體操比賽共有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 = '去掉不合格評委和相應評分后得出運動員排名:\n'
for sps in range(0,10):
self.fin2_text += '第{:2d}名為{:2d}號運動員,得分為{:.2f} \n'.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小白,如有錯誤還請指出。