Python基于相似度查询球员:仅返回1个结果的问题求助
球员相似查询程序仅返回1个结果的问题排查与修复
问题分析
- 标准化逻辑错误:目标球员的统计数据标准化时,误用了自身的均值和标准差(单行数据的标准差为0,会引发除零错误,导致标准化结果异常),正确做法是用整个数据集的均值和标准差来标准化所有球员(包括目标球员)。
- 相似度结果索引错误:
similarity是n行1列的DataFrame,similarity.iloc[0,:]仅取了第一行数据,而非所有球员的相似度值,导致只能筛选出一个结果。 - 未清空历史搜索结果:多次搜索时,Treeview会保留之前的结果,没有重置。
- 缺失球员不存在的异常处理:输入不存在的球员名时,程序会直接报错,没有友好提示。
修正后的代码
import tkinter as tk import pandas as pd import os from tkinter import filedialog from tkinter import messagebox from tkinter import ttk def compare_players(player_name, data): # 检查球员是否存在 player = data[data['Player'] == player_name] if player.empty: return pd.DataFrame() # 获取数值型统计列 numeric_cols = data.select_dtypes(include=['float64']).columns data_stats = data[numeric_cols] # 用整个数据集的均值和标准差做标准化 data_stats_scaled = (data_stats - data_stats.mean()) / data_stats.std() # 标准化目标球员的数据 player_stats_scaled = (player[numeric_cols] - data_stats.mean()) / data_stats.std() # 计算余弦相似度(标准化后点积等于余弦相似度) similarity = data_stats_scaled.dot(player_stats_scaled.T).squeeze() # 排序取Top5(排除自身) top_indices = similarity.sort_values(ascending=False).index[1:6] top_5 = data.loc[top_indices] return top_5 def run_search(player_name, data): # 清空Treeview旧数据 for item in tree.get_children(): tree.delete(item) result = compare_players(player_name, data) if result.empty: messagebox.showwarning("提示", "未找到该球员或无相似球员") return for _, row in result[['Player', 'Team', 'Age']].iterrows(): tree.insert("", "end", values=(row['Player'], row['Team'], row['Age'])) def on_search(): player_name = entry.get().strip() if not player_name: messagebox.showwarning("提示", "请输入球员名称") return run_search(player_name, data) def load_data(): global data data = pd.DataFrame() for file in os.listdir(folder_path): if file.endswith(".xlsx"): file_path = os.path.join(folder_path, file) try: temp_data = pd.read_excel(file_path) data = pd.concat([data, temp_data], axis=0) except Exception as e: messagebox.showerror("错误", f"读取文件{file}失败:{str(e)}") # 重置索引避免concat后的索引混乱 data = data.reset_index(drop=True) # 选择数据文件夹 root = tk.Tk() root.withdraw() folder_path = filedialog.askdirectory(initialdir="./", title="选择包含Excel数据的文件夹") if not folder_path: messagebox.showerror("错误", "未选择文件夹,程序退出") exit() load_data() # 主窗口设置 root = tk.Tk() root.title("球员对比查询") root.geometry("600x400") label = tk.Label(root, text="输入球员名称:") entry = tk.Entry(root) search_button = tk.Button(root, text="搜索相似球员", command=on_search) label.pack(pady=5) entry.pack(pady=5) search_button.pack(pady=5) # 结果表格 tree = ttk.Treeview(root, columns=("Player", "Team", "Age"), show="headings") tree.heading("Player", text="球员名称") tree.heading("Team", text="所属球队") tree.heading("Age", text="年龄") tree.column("Player", width=200) tree.column("Team", width=200) tree.column("Age", width=100) tree.pack(side="left", fill="both", expand=True, padx=5, pady=5) # 添加滚动条 scrollbar = ttk.Scrollbar(root, orient="vertical", command=tree.yview) tree.configure(yscroll=scrollbar.set) scrollbar.pack(side="right", fill="y") root.mainloop()
关键修改说明
- 修正标准化逻辑:统一使用整个数据集的均值和标准差做标准化,避免单行数据的除零问题,保证相似度计算的合理性。
- 修正相似度结果处理:用
squeeze()将相似度结果转为一维数组,排序后从第2个元素开始取Top5(排除目标球员自身)。 - 添加结果清空逻辑:每次搜索前清空Treeview旧数据,避免结果叠加。
- 增加异常处理:覆盖球员名称为空、球员不存在、文件读取失败的场景,提升程序稳定性。
- 优化界面:添加滚动条、调整列宽,提升使用体验。
内容的提问来源于stack exchange,提问作者Atle Thuns
相关产品推荐
相关产品推荐

