You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

关键修改说明

  1. 修正标准化逻辑:统一使用整个数据集的均值和标准差做标准化,避免单行数据的除零问题,保证相似度计算的合理性。
  2. 修正相似度结果处理:用squeeze()将相似度结果转为一维数组,排序后从第2个元素开始取Top5(排除目标球员自身)。
  3. 添加结果清空逻辑:每次搜索前清空Treeview旧数据,避免结果叠加。
  4. 增加异常处理:覆盖球员名称为空、球员不存在、文件读取失败的场景,提升程序稳定性。
  5. 优化界面:添加滚动条、调整列宽,提升使用体验。

内容的提问来源于stack exchange,提问作者Atle Thuns

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 19:10:29