如何绘制球员分数每日变化?保持标签唯一不受索引/人员变动影响
结构可变DataFrame下的球员分数追踪绘图方案
问题描述
我有一个分数追踪脚本,每日生成并导出为JSON格式的DataFrame,通过以下代码读取这类JSON文件:
import json import datetime import pandas as pd import matplotlib.pyplot as plt import os # Directory where the JSON files are located json_dir = 'data/teamName' # Update with your actual directory path # Get the list of JSON files in the directory json_files = [f for f in os.listdir(json_dir) if f.endswith('.json')] data = [] for json_file in json_files: with open(os.path.join(json_dir, json_file), 'r') as f: player_stats = pd.read_json(f,keep_default_dates=True)
为演示场景,提供示例脚本生成每日数据:
import datetime import pandas as pd day1 = datetime.datetime.strptime("01/01/2023", "%d/%m/%Y") day2 = datetime.datetime.strptime("02/01/2023", "%d/%m/%Y") day3 = datetime.datetime.strptime("03/01/2023", "%d/%m/%Y") listPlayers =["Player1", "Player2", "Player3", "Player2", "Player1", "Player3", "Player1", "Player5", "Player3"] listScores = [1.2, 3.4, 5.0,3.0, 1.4, 6.0,3, 2, 6.5] listDays = [day1,day1,day1, day2, day2, day2, day3,day3,day3] for i in range(1,4): myDF = pd.DataFrame({"Name":listPlayers[(i-1)*3:3*i], "Scores":listScores[(i-1)*3:3*i],"Days":listDays[(i-1)*3:3*i]}) print(myDF) print("break")
需求:绘制单个球员分数及团队分数的每日变化曲线,要求即使球员索引变动、离队或新球员加入(如第3天Player2被Player5替换,仍需展示Player2在第1、2天的数据),每个球员都拥有唯一标签。请问该需求是否可实现?
解决方案:完全可以实现
核心思路是先整合所有历史数据,以**球员姓名(Name列)**作为唯一标识,而非索引或位置,再基于整合后的数据完成绘图。具体步骤如下:
1. 整合所有每日JSON数据
修改读取代码,将所有文件的DataFrame合并为一个完整数据集:
import json import datetime import pandas as pd import matplotlib.pyplot as plt import os json_dir = 'data/teamName' json_files = [f for f in os.listdir(json_dir) if f.endswith('.json')] # 初始化空列表存储所有数据 all_data = [] for json_file in json_files: file_path = os.path.join(json_dir, json_file) with open(file_path, 'r') as f: df = pd.read_json(f, keep_default_dates=True) all_data.append(df) # 合并所有数据为一个大DataFrame full_df = pd.concat(all_data, ignore_index=True) # 确保日期格式正确 full_df['Days'] = pd.to_datetime(full_df['Days'])
2. 整理数据(可选:规范日期与球员维度)
用透视表整理数据,自动为每个球员创建独立列,缺失数据留空:
# 创建透视表:行=日期,列=球员,值=分数 pivot_df = full_df.pivot(index='Days', columns='Name', values='Scores') # 按日期排序,保证时间顺序正确 pivot_df = pivot_df.sort_index()
3. 绘制单个球员分数曲线
基于透视表绘图,每个球员自动生成唯一标签的曲线:
plt.figure(figsize=(10, 6)) # 遍历每个球员列,绘制对应分数曲线 for player in pivot_df.columns: plt.plot(pivot_df.index, pivot_df[player], marker='o', label=player) plt.xlabel('日期') plt.ylabel('分数') plt.title('单个球员每日分数变化') plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') plt.grid(True) plt.tight_layout() plt.show()
4. 计算并绘制团队分数曲线
可以选择每日平均分、总分等作为团队指标:
# 计算每日团队平均分(自动忽略缺失值) team_avg = pivot_df.mean(axis=1) plt.figure(figsize=(10, 6)) plt.plot(team_avg.index, team_avg, marker='s', color='red', linewidth=2, label='团队平均分') plt.xlabel('日期') plt.ylabel('分数') plt.title('团队每日平均分数变化') plt.legend() plt.grid(True) plt.show()
关键说明
- 所有操作以球员姓名为唯一标识,完全不受索引位置、球员离队/新增的影响。
- 透视表会自动处理数据缺失,绘图时仅连接球员有分数记录的日期,保留完整历史数据展示。
内容的提问来源于stack exchange,提问作者Guilherme Theis
相关产品推荐
相关产品推荐

