本文目录导读:

我来创建一个统计假动作晃过防守次数的Python案例,这个案例将包含数据定义、统计逻辑和可视化展示。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from datetime import datetime
class DribblingAnalytics:
"""篮球/足球假动作晃过防守统计系统"""
def __init__(self, player_name):
self.player_name = player_name
self.moves = [] # 存储所有动作记录
self.stats = {}
def add_move(self, date, opponent, move_type, successful, defender_name="",
period=1, minute=0, notes=""):
"""
添加一次假动作记录
参数:
date: 日期
opponent: 对手
move_type: 假动作类型
successful: 是否成功晃过 (True/False)
defender_name: 防守球员
period: 节数/半场
minute: 比赛时间
notes: 备注
"""
move = {
'日期': date,
'对手': opponent,
'假动作类型': move_type,
'成功晃过': successful,
'防守球员': defender_name,
'节数': period,
'时间': minute,
'备注': notes
}
self.moves.append(move)
print(f"✓ 已记录: {date} vs {opponent} - {move_type} {'成功' if successful else '失败'}")
def get_total_moves(self):
"""获取总动作次数"""
return len(self.moves)
def get_successful_moves(self):
"""获取成功晃过次数"""
return sum(1 for move in self.moves if move['成功晃过'])
def get_failed_moves(self):
"""获取失败次数"""
return sum(1 for move in self.moves if not move['成功晃过'])
def get_success_rate(self):
"""计算成功率"""
total = self.get_total_moves()
if total == 0:
return 0
return (self.get_successful_moves() / total) * 100
def stats_by_move_type(self):
"""按假动作类型统计"""
stats = {}
for move in self.moves:
move_type = move['假动作类型']
if move_type not in stats:
stats[move_type] = {'总次数': 0, '成功次数': 0, '失败次数': 0}
stats[move_type]['总次数'] += 1
if move['成功晃过']:
stats[move_type]['成功次数'] += 1
else:
stats[move_type]['失败次数'] += 1
# 计算成功率
for move_type in stats:
total = stats[move_type]['总次数']
successful = stats[move_type]['成功次数']
stats[move_type]['成功率'] = (successful / total * 100) if total > 0 else 0
return stats
def stats_by_opponent(self):
"""按对手统计"""
stats = {}
for move in self.moves:
opponent = move['对手']
if opponent not in stats:
stats[opponent] = {'总次数': 0, '成功次数': 0}
stats[opponent]['总次数'] += 1
if move['成功晃过']:
stats[opponent]['成功次数'] += 1
return stats
def get_most_difficult_defender(self):
"""找出最难突破的防守球员"""
defender_stats = {}
for move in self.moves:
defender = move['防守球员']
if not defender:
continue
if defender not in defender_stats:
defender_stats[defender] = {'面对次数': 0, '成功次数': 0}
defender_stats[defender]['面对次数'] += 1
if move['成功晃过']:
defender_stats[defender]['成功次数'] += 1
# 找出最难突破的
if not defender_stats:
return None
hardest_defender = min(defender_stats.items(),
key=lambda x: x[1]['成功次数'] / x[1]['面对次数'] if x[1]['面对次数'] > 0 else 0)
return hardest_defender
def generate_report(self):
"""生成统计报告"""
print("\n" + "=" * 50)
print(f"📊 {self.player_name} 假动作统计分析报告")
print("=" * 50)
# 基本统计
total = self.get_total_moves()
success = self.get_successful_moves()
failed = self.get_failed_moves()
rate = self.get_success_rate()
print(f"\n📈 基本统计:")
print(f" 总假动作次数: {total}")
print(f" 成功晃过: {success} 次")
print(f" 未成功: {failed} 次")
print(f" 成功率: {rate:.1f}%")
# 按类型统计
print("\n🎯 按假动作类型:")
type_stats = self.stats_by_move_type()
for move_type, stats in type_stats.items():
print(f" {move_type}:")
print(f" 总次数: {stats['总次数']}")
print(f" 成功: {stats['成功次数']}")
print(f" 成功率: {stats['成功率']:.1f}%")
# 按对手统计
print("\n🏆 按对手统计:")
opp_stats = self.stats_by_opponent()
for opp, stats in opp_stats.items():
print(f" vs {opp}: 总{stats['总次数']}次, 成功{stats['成功次数']}次")
# 最难防守球员
hardest = self.get_most_difficult_defender()
if hardest:
print(f"\n🛡️ 最难突破的防守球员: {hardest[0]}")
print(f" 面对次数: {hardest[1]['面对次数']}")
print(f" 成功突破: {hardest[1]['成功次数']}次")
def visualize_stats(self):
"""可视化统计结果"""
if not self.moves:
print("暂无数据可可视化")
return
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 1. 成功/失败饼图
ax1 = axes[0, 0]
labels = ['成功晃过', '未成功']
sizes = [self.get_successful_moves(), self.get_failed_moves()]
colors = ['#2ecc71', '#e74c3c']
ax1.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
ax1.set_title('假动作成功率')
# 2. 按类型柱状图
ax2 = axes[0, 1]
type_stats = self.stats_by_move_type()
types = list(type_stats.keys())
success_counts = [type_stats[t]['成功次数'] for t in types]
fail_counts = [type_stats[t]['失败次数'] for t in types]
x = np.arange(len(types))
width = 0.35
ax2.bar(x - width/2, success_counts, width, label='成功', color='#2ecc71')
ax2.bar(x + width/2, fail_counts, width, label='失败', color='#e74c3c')
ax2.set_xlabel('假动作类型')
ax2.set_ylabel('次数')
ax2.set_title('各类型假动作统计')
ax2.set_xticks(x)
ax2.set_xticklabels(types, rotation=45)
ax2.legend()
# 3. 按对手成功率
ax3 = axes[1, 0]
opp_stats = self.stats_by_opponent()
opponents = list(opp_stats.keys())
success_rates = [(opp_stats[o]['成功次数'] / opp_stats[o]['总次数'] * 100)
for o in opponents]
ax3.bar(opponents, success_rates, color='#3498db')
ax3.set_xlabel('对手')
ax3.set_ylabel('成功率 (%)')
ax3.set_title('对每个对手的成功率')
ax3.set_ylim(0, 100)
ax3.tick_params(axis='x', rotation=45)
# 4. 月度趋势
ax4 = axes[1, 1]
# 按日期排序
sorted_moves = sorted(self.moves, key=lambda x: x['日期'])
months = pd.Series([m['日期'] for m in sorted_moves])
monthly_success = months.groupby(months).apply(
lambda x: sum(1 for m in sorted_moves if m['日期'] == x.name and m['成功晃过'])
)
monthly_total = months.groupby(months).size()
if len(monthly_total) > 1:
ax4.plot(monthly_total.index, monthly_total.values, 'o-', label='总次数', color='#3498db')
ax4.plot(monthly_success.index, monthly_success.values, 'o-', label='成功次数', color='#2ecc71')
ax4.set_xlabel('日期')
ax4.set_ylabel('次数')
ax4.set_title('按日期统计')
ax4.legend()
ax4.tick_params(axis='x', rotation=45)
else:
ax4.text(0.5, 0.5, '数据不足', ha='center', va='center')
ax4.set_title('按日期统计')
plt.tight_layout()
plt.show()
def save_to_csv(self, filename="dribbling_stats.csv"):
"""保存数据到CSV文件"""
if not self.moves:
print("暂无数据可保存")
return
df = pd.DataFrame(self.moves)
df.to_csv(filename, index=False, encoding='utf-8-sig')
print(f"✅ 数据已保存到 {filename}")
# 使用示例
if __name__ == "__main__":
# 创建球员实例
player = DribblingAnalytics("张三")
# 添加一些示例数据
# 模拟一场比赛
player.add_move("2024-01-15", "雷霆队", "背后变向", True, "迪克森", 1, 5)
player.add_move("2024-01-15", "雷霆队", "胯下运球", True, "斯密斯", 2, 12)
player.add_move("2024-01-15", "雷霆队", "转身过人", False, "迪克森", 3, 8)
player.add_move("2024-01-15", "雷霆队", "交叉步", True, "约翰逊", 4, 15)
# 第二场比赛
player.add_move("2024-01-22", "勇士队", "背后变向", False, "库里", 1, 10)
player.add_move("2024-01-22", "勇士队", "胯下运球", True, "汤普森", 2, 7)
player.add_move("2024-01-22", "勇士队", "转身过人", True, "格林", 1, 3)
# 第三场比赛
player.add_move("2024-02-05", "湖人队", "背后变向", True, "詹姆斯", 2, 10)
player.add_move("2024-02-05", "湖人队", "交叉步", True, "戴维斯", 1, 6)
player.add_move("2024-02-05", "湖人队", "转身过人", False, "詹姆斯", 4, 15)
# 生成报告
print("🎮 正在生成统计报告...")
player.generate_report()
# 保存数据
player.save_to_csv()
# 可视化展示(需要matplotlib支持)
try:
player.visualize_stats()
except:
print("\n⚠️ 无法显示图表,可直接在Jupyter环境中查看")
# 额外的分析
print("\n🔍 更详细的分析:")
# 找出成功率最高的假动作
type_stats = player.stats_by_move_type()
best_type = max(type_stats.items(), key=lambda x: x[1]['成功率'])
print(f"最擅长的假动作: {best_type[0]} (成功率 {best_type[1]['成功率']:.1f}%)")
# 按节次分析
period_stats = {}
for move in player.moves:
period = move['节数']
if period not in period_stats:
period_stats[period] = {'总': 0, '成功': 0}
period_stats[period]['总'] += 1
if move['成功晃过']:
period_stats[period]['成功'] += 1
print("\n各节次表现:")
for period, stats in sorted(period_stats.items()):
rate = (stats['成功'] / stats['总'] * 100) if stats['总'] > 0 else 0
print(f" 第{period}节: {stats['总']}次假动作, 成功{stats['成功']}次, 成功率{rate:.1f}%")
这个案例包含以下功能:
主要功能:
-
数据记录:可以记录每次假动作的详细信息
-
自动统计:
- 总动作次数
- 成功晃过次数
- 成功率计算
- 按类型/对手/防守球员分类统计
-
可视化展示:
- 成功/失败比例饼图
- 按假动作类型的柱状图
- 对每个对手的成功率
- 按时间的趋势图
-
报告生成:自动生成详细的分析报告
使用方式:
# 更简单的使用示例
player = DribblingAnalytics("李四")
# 快速记录
player.add_move("2024-03-01", "火箭队", "背后变向", True)
player.add_move("2024-03-01", "火箭队", "转身过人", False)
# 获取统计结果
print(f"成功次数: {player.get_successful_moves()}")
print(f"成功率: {player.get_success_rate():.1f}%")
输出示例:
📈 基本统计:
总假动作次数: 10
成功晃过: 7 次
未成功: 3 次
成功率: 70.0%
🎯 按假动作类型:
背后变向:
总次数: 3
成功: 2
成功率: 66.7%
这个系统可以帮助运动员或教练员追踪假动作的使用情况,找出最有效的技术动作,并针对弱点进行改进。