本文目录导读:

我来为您创建一个足球比赛禁区内外射门统计的Python案例。
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
from matplotlib.font_manager import FontProperties
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
class FootballShotAnalyzer:
def __init__(self):
# 球场尺寸(单位:米)
self.field_length = 105
self.field_width = 68
# 禁区尺寸(标准禁区)
self.penalty_area_length = 16.5
self.penalty_area_width = 40.32
# 球门尺寸
self.goal_width = 7.32
def generate_sample_data(self):
"""生成示例射门数据"""
# 格式:球队A和球队B的射门数据
# 坐标基于进攻方向(假设进攻方向为从左到右)
team_a_shots = [
# (x坐标, y坐标, 射门结果, 球员)
(85, 30, 'goal', '前锋1'),
(88, 35, 'goal', '前锋2'),
(78, 25, 'save', '中场1'),
(92, 40, 'wide', '前锋1'),
(83, 20, 'block', '中场2'),
(95, 32, 'goal', '前锋2'),
(80, 38, 'save', '前锋1'),
(75, 28, 'wide', '中场3'),
(90, 33, 'block', '前锋3'),
(87, 37, 'save', '中场1'),
]
team_b_shots = [
(82, 32, 'goal', '前锋4'),
(79, 29, 'save', '前锋5'),
(91, 36, 'save', '中场4'),
(86, 34, 'wide', '前锋4'),
(93, 31, 'block', '前锋5'),
(77, 27, 'goal', '前锋6'),
(89, 39, 'save', '中场5'),
(84, 30, 'goal', '前锋4'),
(96, 33, 'wide', '前锋6'),
(81, 35, 'block', '中场4'),
]
return {
'team_a': {'shots': team_a_shots, 'name': '主队'},
'team_b': {'shots': team_b_shots, 'name': '客队'}
}
def is_in_penalty_area(self, x, y):
"""判断射门位置是否在禁区内"""
# 判断坐标是否在禁区内(基于进攻方向)
if x >= 105 - self.penalty_area_length: # 在禁区内
if abs(y - self.field_width/2) <= self.penalty_area_width/2:
return True
return False
def analyze_shots(self, data):
"""分析射门数据"""
analysis = {}
for team_key, team_data in data.items():
team_shots = team_data['shots']
team_name = team_data['name']
# 统计限定在对方半场(x > 50)
filter_shots = [shot for shot in team_shots if shot[0] > 50]
in_area = []
out_area = []
for shot in filter_shots:
x, y, result, player = shot
if self.is_in_penalty_area(x, y):
in_area.append(shot)
else:
out_area.append(shot)
analysis[team_key] = {
'team_name': team_name,
'in_area': in_area,
'out_area': out_area,
'in_area_count': len(in_area),
'out_area_count': len(out_area),
'in_area_goals': sum(1 for s in in_area if s[2] == 'goal'),
'out_area_goals': sum(1 for s in out_area if s[2] == 'goal')
}
return analysis
def plot_comparison(self, analysis):
"""绘制禁区内外射门对比图"""
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(14, 10))
teams = list(analysis.keys())
teams_name = [analysis[team]['team_name'] for team in teams]
in_counts = [analysis[team]['in_area_count'] for team in teams]
out_counts = [analysis[team]['out_area_count'] for team in teams]
# 1. 射门次数对比柱状图
x = np.arange(len(teams))
width = 0.35
bars1 = ax1.bar(x - width/2, in_counts, width, label='禁区内', color='#2196F3')
bars2 = ax1.bar(x + width/2, out_counts, width, label='禁区外', color='#FFC107')
ax1.set_xlabel('球队')
ax1.set_ylabel('射门次数')
ax1.set_title('禁区内外射门次数对比')
ax1.set_xticks(x)
ax1.set_xticklabels(teams_name)
ax1.legend()
# 在柱状图上添加数值
for bar in bars1:
height = bar.get_height()
ax1.text(bar.get_x() + bar.get_width()/2., height,
f'{int(height)}', ha='center', va='bottom')
for bar in bars2:
height = bar.get_height()
ax1.text(bar.get_x() + bar.get_width()/2., height,
f'{int(height)}', ha='center', va='bottom')
# 2. 饼图对比
ax2.pie([in_counts[0], out_counts[0]],
labels=['禁区内', '禁区外'],
autopct='%1.1f%%',
colors=['#2196F3', '#FFC107'])
ax2.set_title(f'{teams_name[0]}射门分布')
ax4.pie([in_counts[1], out_counts[1]],
labels=['禁区内', '禁区外'],
autopct='%1.1f%%',
colors=['#4CAF50', '#FF5722'])
ax4.set_title(f'{teams_name[1]}射门分布')
# 3. 球场示意图
self.plot_field(ax3, analysis)
plt.tight_layout()
return fig
def plot_field(self, ax, analysis):
"""绘制球场示意图"""
# 绘制球场
ax.set_xlim(0, self.field_length)
ax.set_ylim(0, self.field_width)
ax.set_aspect('equal')
ax.set_title('射门位置分布图')
# 绘制球场边界
ax.add_patch(patches.Rectangle((0, 0), self.field_length, self.field_width,
fill=False, edgecolor='green', linewidth=2))
# 绘制中线
ax.axvline(x=self.field_length/2, color='green', linewidth=1)
# 绘制禁区(右上角,进攻方向)
penalty_start = self.field_length - self.penalty_area_length
penalty_y_start = (self.field_width - self.penalty_area_width)/2
ax.add_patch(patches.Rectangle((penalty_start, penalty_y_start),
self.penalty_area_length, self.penalty_area_width,
fill=False, edgecolor='green', linewidth=1.5))
# 绘制球门
goal_y_start = (self.field_width - self.goal_width)/2
ax.plot([self.field_length, self.field_length],
[goal_y_start, goal_y_start + self.goal_width],
color='red', linewidth=3)
# 绘制各球员射门位置
colors_map = {
'team_a': '#2196F3',
'team_b': '#4CAF50'
}
markers_map = {
'goal': 'o',
'save': 's',
'wide': '^',
'block': 'D'
}
for team_key, team_data in analysis.items():
color = colors_map[team_key]
# 绘制禁区内射门
for shot in team_data['in_area']:
x, y, result, player = shot
marker = markers_map.get(result, 'o')
ax.scatter(x, y, c=color, marker=marker, s=100,
edgecolors='black', linewidths=1, alpha=0.7)
# 绘制禁区外射门
for shot in team_data['out_area']:
x, y, result, player = shot
marker = markers_map.get(result, 'o')
ax.scatter(x, y, c=color, marker=marker, s=100,
edgecolors='black', linewidths=1, alpha=1.0,
facecolors='none')
# 添加图例
legend_elements = [
plt.Line2D([0], [0], marker='o', color='w', label='进球',
markerfacecolor='blue', markersize=10),
plt.Line2D([0], [0], marker='s', color='w', label='扑出',
markerfacecolor='blue', markersize=10),
plt.Line2D([0], [0], marker='^', color='w', label='射偏',
markerfacecolor='blue', markersize=10),
plt.Line2D([0], [0], marker='D', color='w', label='被封堵',
markerfacecolor='blue', markersize=10)
]
ax.legend(handles=legend_elements, loc='upper left')
# 添加禁区标注
ax.text(penalty_start + 5, self.field_width/2 + 25, '禁区',
color='green', fontsize=10)
def print_summary(self, analysis):
"""打印分析摘要"""
print("="*60)
print("射门统计报告")
print("="*60)
for team_key, data in analysis.items():
print(f"\n{data['team_name']}统计:")
print(f" 总射门次数: {data['in_area_count'] + data['out_area_count']}")
print(f" 禁区内射门: {data['in_area_count']} 次")
print(f" 禁区外射门: {data['out_area_count']} 次")
print(f" 禁区内进球: {data['in_area_goals']} 个")
print(f" 禁区外进球: {data['out_area_goals']} 个")
if data['in_area_count'] > 0:
in_rate = data['in_area_goals'] / data['in_area_count'] * 100
print(f" 禁区内进球转化率: {in_rate:.1f}%")
if data['out_area_count'] > 0:
out_rate = data['out_area_goals'] / data['out_area_count'] * 100
print(f" 禁区外进球转化率: {out_rate:.1f}%")
print(" " + "-"*40)
print(f" 禁区内射门结果分布:")
self.print_result_distribution(data['in_area'])
print(f" 禁区外射门结果分布:")
self.print_result_distribution(data['out_area'])
def print_result_distribution(self, shots):
"""打印射门结果分布"""
results = {'goal': 0, 'save': 0, 'wide': 0, 'block': 0}
result_names = {'goal': '进球', 'save': '被扑出', 'wide': '射偏', 'block': '被封堵'}
for shot in shots:
results[shot[2]] += 1
for result, count in results.items():
if count > 0:
print(f" {result_names[result]}: {count} 次")
# 主程序
def main():
analyzer = FootballShotAnalyzer()
# 生成数据(实际使用时可以替换为自己的数据)
data = analyzer.generate_sample_data()
# 分析数据
analysis = analyzer.analyze_shots(data)
# 打印统计摘要
analyzer.print_summary(analysis)
# 绘制对比图表
fig = analyzer.plot_comparison(analysis)
plt.show()
# 额外分析:可视化对比数据表格
print("\n" + "="*60)
print("数据可视化对比表")
print("="*60)
print(f"{'指标':<20} {'主队':<15} {'客队':<15} {'差值':<10}")
print("-"*60)
team_a = analysis['team_a']
team_b = analysis['team_b']
metrics = [
('总射门次数', team_a['in_area_count'] + team_a['out_area_count'],
team_b['in_area_count'] + team_b['out_area_count']),
('禁区内射门', team_a['in_area_count'], team_b['in_area_count']),
('禁区外射门', team_a['out_area_count'], team_b['out_area_count']),
('禁区内进球', team_a['in_area_goals'], team_b['in_area_goals']),
('禁区外进球', team_a['out_area_goals'], team_b['out_area_goals'])
]
for name, a_val, b_val in metrics:
diff = a_val - b_val
diff_str = f"{diff:+d}" if diff != 0 else "0"
print(f"{name:<20} {a_val:<15} {b_val:<15} {diff_str:<10}")
if __name__ == "__main__":
main()
这个案例的主要功能:
功能特点:
- 数据模拟:生成两队的射门数据,包括位置坐标、射门结果和球员信息
- 区域判定:自动判断射门位置是否在禁区内
- 统计分析:计算禁区内外射门次数、进球率等指标
- 统计报告:打印详细的射门统计信息
- 可视化图表:
- 柱状图对比两队禁区内外射门次数
- 饼图显示每队的射门分布
- 球场示意图标注射门位置
可自定义:
您可以修改generate_sample_data()方法中的team_a_shots和team_b_shots列表来输入实际比赛数据,坐标格式为(x, y, result, player),其中x、y是球场坐标,result是射门结果(goal/save/wide/block),player是球员名。
运行程序后,您会看到详细的统计分析结果和直观的可视化图表,帮助您快速了解比赛中禁区内外射门的情况对比。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播