本文目录导读:

我来为您设计一个统计赛季累计数据对比的Python案例,这个案例将模拟NBA/篮球赛季的数据统计和对比分析:
基础数据类设计
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
import warnings
warnings.filterwarnings('ignore')
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
class PlayerStats:
"""球员赛季数据类"""
def __init__(self, name, team):
self.name = name
self.team = team
self.games = []
self.total_stats = {
'points': 0, 'rebounds': 0, 'assists': 0,
'steals': 0, 'blocks': 0, 'turnovers': 0,
'fga': 0, 'fgm': 0, '3pa': 0, '3pm': 0,
'fta': 0, 'ftm': 0, 'minutes': 0
}
def add_game(self, game_stats):
"""添加单场比赛数据"""
self.games.append(game_stats)
for key in self.total_stats:
self.total_stats[key] += game_stats.get(key, 0)
def get_averages(self):
"""计算场均数据"""
games_played = len(self.games)
if games_played == 0:
return {}
averages = {}
for key, value in self.total_stats.items():
averages[key] = round(value / games_played, 2)
# 计算命中率
if self.total_stats['fga'] > 0:
averages['fg_pct'] = round(self.total_stats['fgm'] / self.total_stats['fga'] * 100, 1)
if self.total_stats['3pa'] > 0:
averages['3p_pct'] = round(self.total_stats['3pm'] / self.total_stats['3pa'] * 100, 1)
if self.total_stats['fta'] > 0:
averages['ft_pct'] = round(self.total_stats['ftm'] / self.total_stats['fta'] * 100, 1)
return averages
模拟赛季数据生成
class SeasonStats:
"""赛季统计类"""
def __init__(self, season):
self.season = season
self.players = {}
def generate_simulated_data(self, num_players=10, games_per_player=20):
"""生成模拟数据"""
np.random.seed(42)
teams = ['湖人', '勇士', '火箭', '凯尔特人', '雄鹿',
'快船', '太阳', '掘金', '热火', '76人']
for i in range(num_players):
player_name = f"球员{i+1}"
team = teams[i % len(teams)]
player = PlayerStats(player_name, team)
# 生成球员能力值
ability = np.random.uniform(0.5, 1.0)
for game in range(games_per_player):
# 模拟单场比赛数据
minutes = np.random.uniform(20, 40)
points = int(ability * np.random.normal(20, 5) * minutes/30)
rebounds = int(ability * np.random.normal(8, 3) * minutes/30)
assists = int(ability * np.random.normal(6, 2))
steals = int(ability * np.random.normal(2, 1))
blocks = int(ability * np.random.normal(1, 0.5))
turnovers = int(np.random.normal(3, 1))
# 投篮数据
fga = int(np.random.normal(18, 4))
fgm = int(fga * (0.4 + ability * 0.1 + np.random.normal(0, 0.1)))
fgm = max(0, min(fga, fgm))
threepa = int(np.random.normal(7, 2))
threepm = int(threepa * (0.3 + ability * 0.1))
threepm = max(0, min(threepa, threepm))
fta = int(np.random.normal(5, 2))
ftm = int(fta * (0.75 + ability * 0.1))
ftm = max(0, min(fta, ftm))
game_stats = {
'game': game + 1,
'points': max(0, points),
'rebounds': max(0, rebounds),
'assists': max(0, assists),
'steals': max(0, steals),
'blocks': max(0, blocks),
'turnovers': max(0, turnovers),
'fga': fga, 'fgm': fgm,
'3pa': threepa, '3pm': threepm,
'fta': fta, 'ftm': ftm,
'minutes': round(minutes, 1)
}
player.add_game(game_stats)
self.players[player_name] = player
return self
def get_player_comparison(self, player_names=None):
"""获取球员数据对比"""
if player_names is None:
player_names = list(self.players.keys())
comparison_data = []
for name in player_names:
if name in self.players:
player = self.players[name]
stats = player.get_averages()
stats['name'] = name
stats['team'] = player.team
stats['games'] = len(player.games)
comparison_data.append(stats)
return pd.DataFrame(comparison_data)
数据分析和可视化
class SeasonAnalyzer:
"""赛季分析器"""
def __init__(self, season_stats):
self.season_stats = season_stats
def create_comparison_report(self, player_names):
"""生成对比报告"""
df = self.season_stats.get_player_comparison(player_names)
# 统计摘要
summary = {
'场均得分王': df.loc[df['points'].idxmax(), 'name'],
'场均篮板王': df.loc[df['rebounds'].idxmax(), 'name'],
'场均助攻王': df.loc[df['assists'].idxmax(), 'name'],
'场均抢断王': df.loc[df['steals'].idxmax(), 'name'],
'场均盖帽王': df.loc[df['blocks'].idxmax(), 'name'],
'最高命中率': df.loc[df['fg_pct'].idxmax(), 'name'],
'最高三分命中率': df.loc[df['3p_pct'].idxmax(), 'name']
}
return df, summary
def plot_player_comparison(self, player_names, metrics=['points', 'rebounds', 'assists']):
"""绘制球员对比图表"""
df = self.season_stats.get_player_comparison(player_names)
# 创建雷达图
if len(metrics) >= 3:
self._create_radar_chart(df, metrics)
# 创建柱状图
self._create_bar_chart(df, metrics)
# 创建热力图
self._create_heatmap(df)
def _create_radar_chart(self, df, metrics):
"""创建雷达图"""
# 标准化数据用于雷达图
normalized = df[metrics].copy()
for col in metrics:
if col in ['fg_pct', '3p_pct', 'ft_pct']:
normalized[col] = normalized[col] / 100
elif self.season_stats.players[df.iloc[0]['name']].total_stats[col if col != 'fg_pct' else 'fga'] > 0:
max_val = normalized[col].max()
if max_val > 0:
normalized[col] = normalized[col] / max_val
# 雷达图
angles = np.linspace(0, 2 * np.pi, len(metrics), endpoint=False).tolist()
angles += angles[:1]
fig, ax = plt.subplots(figsize=(10, 8), subplot_kw=dict(polar=True))
for idx, player in df.iterrows():
values = normalized.loc[idx].tolist()
values += values[:1]
ax.plot(angles, values, 'o-', linewidth=2, label=player['name'])
ax.fill(angles, values, alpha=0.25)
ax.set_xticks(angles[:-1])
ax.set_xticklabels(metrics)
ax.set_title(f'{self.season_stats.season}赛季球员数据对比 - 雷达图', fontsize=14)
ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.0))
plt.tight_layout()
plt.show()
def _create_bar_chart(self, df, metrics):
"""创建柱状图"""
fig, axes = plt.subplots(1, len(metrics), figsize=(15, 6))
for i, metric in enumerate(metrics):
if len(metrics) > 1:
ax = axes[i]
else:
ax = axes
data = df.sort_values(metric, ascending=False)
bars = ax.bar(data['name'], data[metric], alpha=0.8)
# 添加数值标签
for bar, value in zip(bars, data[metric]):
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.5,
f'{value:.1f}', ha='center', va='bottom', fontsize=8)
ax.set_title(f'{metric}对比')
ax.set_ylabel(metric)
ax.set_xticklabels(data['name'], rotation=45)
plt.suptitle(f'{self.season_stats.season}赛季数据对比', fontsize=14)
plt.tight_layout()
plt.show()
def _create_heatmap(self, df):
"""创建热力图"""
# 选择要显示的数据
columns = ['points', 'rebounds', 'assists', 'steals', 'blocks', 'fg_pct', '3p_pct']
columns = [col for col in columns if col in df.columns]
plot_df = df.set_index('name')[columns]
# 标准化每列以便可视化
normalized = plot_df.copy()
for col in columns:
if col in ['fg_pct', '3p_pct']:
normalized[col] = normalized[col] / 100
else:
normalized[col] = (normalized[col] - normalized[col].min()) / \
(normalized[col].max() - normalized[col].min())
plt.figure(figsize=(10, 8))
sns.heatmap(normalized, annot=True, fmt='.3f', cmap='YlOrRd',
cbar_kws={'label': '得分占比'})
plt.title(f'{self.season_stats.season}赛季球员综合表现热力图')
plt.tight_layout()
plt.show()
主程序示例
def main():
"""主程序"""
print("=" * 60)
print("赛季累计数据统计与对比分析系统")
print("=" * 60)
# 生成 2023-24 赛季模拟数据
season = SeasonStats("2023-24")
season.generate_simulated_data(num_players=5, games_per_player=15)
# 创建分析器
analyzer = SeasonAnalyzer(season)
# 获取球员对比数据
player_names = list(season.players.keys())
df, summary = analyzer.create_comparison_report(player_names)
print("\n球员场均数据对比:")
print(df[['name', 'team', 'games', 'points', 'rebounds', 'assists',
'steals', 'blocks', 'fg_pct', '3p_pct', 'ft_pct']].to_string(index=False))
print("\n赛季亮点:")
for title, player in summary.items():
print(f" {title}: {player}")
# 生成统计图表
print("\n生成可视化图表...")
analyzer.plot_player_comparison(player_names,
metrics=['points', 'rebounds', 'assists'])
# 输出详细统计报告
print("\n详细赛季统计报告:")
for player_name in player_names:
player = season.players[player_name]
stats = player.get_averages()
print(f"\n{player_name} ({player.team}) - {len(player.games)}场比赛")
print(f" 场均: {stats['points']}分, {stats['rebounds']}篮板, {stats['assists']}助攻")
print(f" 命中率: 投篮{stats.get('fg_pct', 0)}%, 三分{stats.get('3p_pct', 0)}%, "
f"罚球{stats.get('ft_pct', 0)}%")
print(f" 效率值: {stats['points'] + stats['rebounds'] + stats['assists'] + "
f"stats['steals'] + stats['blocks']}")
if __name__ == "__main__":
main()
输出示例
运行该程序将产生:
- 球员场均数据对比表格
- 赛季亮点汇总
- 雷达图、柱状图和热力图
- 每位球员的详细统计报告
这个案例展示了如何:
- 使用面向对象思想设计数据模型
- 模拟生成赛季数据
- 计算场均数据和命中率
- 使用pandas进行数据对比分析
- 使用matplotlib和seaborn创建多种可视化图表
- 提供直观的数据对比和排名
您可以根据实际需求调整数据结构、添加更多统计指标(如正负值、效率值等),或增加更复杂的分析方法。