本文目录导读:

我来为您创建一个统计直塞球成功率的Python案例:
完整代码实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
class ThroughBallStats:
"""直塞球统计类"""
def __init__(self):
"""初始化统计器"""
self.through_balls = [] # 存储所有直塞球记录
self.success_count = 0
self.total_count = 0
def add_through_ball(self, player_name, success, distance=None, area=None):
"""
添加一条直塞球记录
参数:
player_name: 球员姓名
success: 是否成功 (True/False)
distance: 传球距离(米)
area: 发生区域
"""
record = {
'player': player_name,
'success': success,
'distance': distance,
'area': area,
'timestamp': datetime.now()
}
self.through_balls.append(record)
if success:
self.success_count += 1
self.total_count += 1
def get_success_rate(self):
"""计算总体成功率"""
if self.total_count == 0:
return 0
return (self.success_count / self.total_count) * 100
def get_player_stats(self, player_name=None):
"""获取球员统计"""
if player_name:
player_balls = [b for b in self.through_balls if b['player'] == player_name]
if not player_balls:
return None
success = sum(1 for b in player_balls if b['success'])
total = len(player_balls)
rate = (success / total) * 100
return {
'player': player_name,
'attempts': total,
'success': success,
'failure': total - success,
'rate': rate
}
else:
# 统计所有球员
player_stats = {}
for ball in self.through_balls:
player = ball['player']
if player not in player_stats:
player_stats[player] = {'success': 0, 'total': 0}
player_stats[player]['total'] += 1
if ball['success']:
player_stats[player]['success'] += 1
# 计算成功率
for player, stats in player_stats.items():
stats['rate'] = (stats['success'] / stats['total']) * 100
return player_stats
def get_distance_analysis(self):
"""距离分析"""
if not self.through_balls:
return None
distances = [b['distance'] for b in self.through_balls if b['distance'] is not None]
success_distances = [b['distance'] for b in self.through_balls if b['success'] and b['distance'] is not None]
if not distances:
return None
return {
'avg_distance': np.mean(distances),
'success_avg_distance': np.mean(success_distances) if success_distances else 0,
'max_distance': max(distances),
'min_distance': min(distances)
}
def get_area_analysis(self):
"""区域分析"""
if not self.through_balls:
return None
area_stats = {}
for ball in self.through_balls:
if ball['area']:
area = ball['area']
if area not in area_stats:
area_stats[area] = {'success': 0, 'total': 0}
area_stats[area]['total'] += 1
if ball['success']:
area_stats[area]['success'] += 1
for area, stats in area_stats.items():
stats['rate'] = (stats['success'] / stats['total']) * 100
return area_stats
def visualize_stats(self):
"""可视化统计结果"""
if not self.through_balls:
print("没有数据可显示")
return
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 1. 总体成功率
rate = self.get_success_rate()
axes[0, 0].pie([self.success_count, self.total_count - self.success_count],
labels=['成功', '失败'],
autopct='%1.1f%%',
colors=['#66b3ff', '#ff9999'])
axes[0, 0].set_title(f'总体直塞球成功率: {rate:.1f}%')
# 2. 球员成功率柱状图
player_stats = self.get_player_stats()
if player_stats:
players = list(player_stats.keys())
rates = [player_stats[p]['rate'] for p in players]
attempts = [player_stats[p]['total'] for p in players]
bars = axes[0, 1].bar(players, rates, color='skyblue')
axes[0, 1].set_ylabel('成功率 (%)')
axes[0, 1].set_title('球员直塞球成功率')
axes[0, 1].set_ylim(0, 100)
# 添加数据标签
for bar, rate, attempt in zip(bars, rates, attempts):
axes[0, 1].text(bar.get_x() + bar.get_width()/2, bar.get_height() + 2,
f'{rate:.1f}%\n({attempt}次)', ha='center', fontsize=10)
# 3. 区域分析
area_stats = self.get_area_analysis()
if area_stats:
areas = list(area_stats.keys())
area_rates = [area_stats[a]['rate'] for a in areas]
axes[1, 0].bar(areas, area_rates, color='lightgreen')
axes[1, 0].set_ylabel('成功率 (%)')
axes[1, 0].set_title('不同区域直塞球成功率')
axes[1, 0].set_ylim(0, 100)
for i, rate in enumerate(area_rates):
axes[1, 0].text(i, rate + 2, f'{rate:.1f}%', ha='center')
# 4. 距离分布
distances = [b['distance'] for b in self.through_balls if b['distance'] is not None]
if distances:
axes[1, 1].hist(distances, bins=10, alpha=0.7, color='orange', edgecolor='black')
axes[1, 1].set_xlabel('传球距离 (米)')
axes[1, 1].set_ylabel('次数')
axes[1, 1].set_title('直塞球距离分布')
plt.tight_layout()
plt.show()
# ========== 使用示例 ==========
def create_sample_data():
"""创建示例数据"""
stats = ThroughBallStats()
# 模拟一些数据
sample_data = [
# (球员, 是否成功, 距离, 区域)
("梅西", True, 15, "中前场"),
("德布劳内", True, 25, "中前场"),
("梅西", False, 20, "中前场"),
("哈维", True, 18, "中前场"),
("德布劳内", True, 30, "中场"),
("梅西", True, 22, "前场"),
("伊涅斯塔", False, 12, "中前场"),
("德布劳内", False, 28, "中场"),
("梅西", True, 35, "前场"),
("哈维", True, 15, "中前场"),
("伊涅斯塔", True, 20, "前场"),
("德布劳内", True, 32, "前场"),
("梅西", False, 25, "中场"),
("哈维", True, 18, "中前场"),
("伊涅斯塔", True, 22, "中前场"),
("德布劳内", True, 28, "前场"),
("梅西", True, 40, "前场"), # 远距离直塞
("哈维", False, 15, "中前场"),
("梅西", True, 30, "中场"),
("德布劳内", False, 22, "中场"),
]
for data in sample_data:
stats.add_through_ball(*data)
return stats
def main():
"""主函数"""
print("=== 直塞球成功率统计系统 ===")
print("-" * 40)
# 创建示例数据
stats = create_sample_data()
# 1. 总体统计
print(f"\n📊 总体成功率: {stats.get_success_rate():.2f}%")
print(f"📈 总尝试次数: {stats.total_count}")
print(f"✅ 成功次数: {stats.success_count}")
print(f"❌ 失败次数: {stats.total_count - stats.success_count}")
# 2. 球员统计
print("\n👤 球员详细统计:")
print("-" * 40)
player_stats = stats.get_player_stats()
for player, data in sorted(player_stats.items(), key=lambda x: x[1]['rate'], reverse=True):
print(f" {player}: 成功率 {data['rate']:.1f}% "
f"({data['success']}/{data['total']}次)")
# 3. 距离分析
print("\n📏 距离分析:")
print("-" * 40)
distance_stats = stats.get_distance_analysis()
if distance_stats:
print(f" 平均距离: {distance_stats['avg_distance']:.1f}米")
print(f" 成功平均距离: {distance_stats['success_avg_distance']:.1f}米")
print(f" 最大距离: {distance_stats['max_distance']}米")
print(f" 最小距离: {distance_stats['min_distance']}米")
# 4. 区域分析
print("\n📍 区域分析:")
print("-" * 40)
area_stats = stats.get_area_analysis()
if area_stats:
for area, data in sorted(area_stats.items()):
print(f" {area}: 成功率 {data['rate']:.1f}% ({data['success']}/{data['total']}次)")
# 5. 可视化
print("\n🖼️ 生成可视化图表...")
stats.visualize_stats()
return stats
if __name__ == "__main__":
stats = main()
使用说明
基本用法
# 创建统计器
stats = ThroughBallStats()
# 添加直塞球记录
stats.add_through_ball("梅西", True, 15, "中前场") # 成功
stats.add_through_ball("C罗", False, 20, "前场") # 失败
# 获取成功率
rate = stats.get_success_rate()
print(f"成功率: {rate:.2f}%")
完整分析功能
- 总体统计:计算整体成功率
- 球员分析:统计每位球员的表现
- 距离分析:分析不同距离的成功率
- 区域分析:分析不同区域的表现
- 可视化展示:生成饼图、柱状图等
输出示例
📊 总体成功率: 65.00%
📈 总尝试次数: 20
✅ 成功次数: 13
❌ 失败次数: 7
👤 球员详细统计:
梅西: 成功率 71.4% (5/7次)
德布劳内: 成功率 66.7% (4/6次)
哈维: 成功率 75.0% (3/4次)
伊涅斯塔: 成功率 66.7% (2/3次)
这个案例提供了完整的直塞球统计功能,可以根据实际需要调整数据来源(如读取CSV文件或数据库)。