本文目录导读:

我来帮你分析Python中显示横传转移球次数的案例,这通常用于足球数据分析。
基础案例:统计横传转移球次数
import pandas as pd
import numpy as np
# 创建模拟传球数据
def create_pass_data():
data = {
'pass_id': range(1, 11),
'x_start': [20, 25, 30, 35, 40, 45, 50, 55, 60, 65],
'y_start': [30, 35, 42, 48, 45, 38, 35, 40, 45, 42],
'x_end': [25, 30, 35, 40, 45, 50, 55, 60, 65, 70],
'y_end': [28, 32, 38, 45, 42, 35, 32, 37, 42, 40],
'team': ['TeamA'] * 5 + ['TeamB'] * 5
}
return pd.DataFrame(data)
def analyze_sideways_passes(df, y_threshold=15):
"""
统计横传转移球(横向传球)
参数:
df: 传球数据
y_threshold: 横向转移的阈值(米),超过此值认为是横传转移
返回:
横传转移球次数及详细信息
"""
# 计算传球的横向距离(y坐标变化)
df['y_distance'] = abs(df['y_end'] - df['y_start'])
# 判断是否为横传转移(横向移动大,纵向移动小)
df['x_distance'] = abs(df['x_end'] - df['x_start'])
df['is_sideways_pass'] = (df['y_distance'] > y_threshold) & (df['x_distance'] > 5)
# 统计次数
total_sideways = df['is_sideways_pass'].sum()
# 按球队分组统计
team_stats = df.groupby('team').agg(
total_passes=('pass_id', 'count'),
sideways_passes=('is_sideways_pass', 'sum'),
sideways_percentage=('is_sideways_pass', 'mean')
).reset_index()
return total_sideways, team_stats
# 执行分析
pass_data = create_pass_data()
total_sideways, team_stats = analyze_sideways_passes(pass_data)
print(f"横传转移球总次数: {total_sideways}")
print("\n按球队统计:")
print(team_stats)
print("\n详细信息:")
print(pass_data[['pass_id', 'team', 'y_distance', 'is_sideways_pass']])
更高级的项目案例
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
class PassAnalyzer:
def __init__(self, data_file=None):
self.data = None
self.sideways_passes = None
def load_data(self, file_path):
"""加载传球数据"""
# 假设数据包含: pass_id, x_start, y_start, x_end, y_end, team, player
self.data = pd.read_csv(file_path)
self.data['y_distance'] = abs(self.data['y_end'] - self.data['y_start'])
self.data['x_distance'] = abs(self.data['x_end'] - self.data['x_start'])
def identify_sideways_passes(self, threshold=15):
"""识别横传转移球"""
# 定义横传特征:横向移动大于阈值且非角球/边线球
self.data['pass_angle'] = np.arctan2(
self.data['y_distance'],
self.data['x_distance'] + 1e-6
) * 180 / np.pi
self.data['is_sideways'] = (
(self.data['pass_angle'] > 60) &
(self.data['pass_angle'] < 120) &
(self.data['x_distance'] < 40) # 排除长传
)
self.sideways_passes = self.data[self.data['is_sideways']]
return len(self.sideways_passes)
def analyze_by_zone(self):
"""按球场区域分析"""
# 划分区域(左路、中路、右路)
self.data['zone'] = pd.cut(
self.data['y_start'],
bins=[0, 25, 50, 75, 100],
labels=['Left', 'Center-Left', 'Center-Right', 'Right']
)
zone_analysis = pd.DataFrame()
for zone in ['Left', 'Center-Left', 'Center-Right', 'Right']:
zone_data = self.data[self.data['zone'] == zone]
if len(zone_data) > 0:
sideways_count = zone_data['is_sideways'].sum()
total_count = len(zone_data)
zone_analysis[zone] = {
'total_passes': total_count,
'sideways_passes': sideways_count,
'percentage': (sideways_count / total_count) * 100
}
return zone_analysis
def visualize_distribution(self):
"""可视化传球分布"""
if self.sideways_passes is None:
return self.identify_sideways_passes()
fig, axs = plt.subplots(1, 2, figsize=(15, 5))
# 时间分布
if 'minute' in self.data.columns:
time_data = self.sideways_passes.groupby('minute').size()
axs[0].plot(time_data.index, time_data.values, 'o-')
axs[0].set_title('Sideways Passes by Minute')
axs[0].set_xlabel('Minute')
axs[0].set_ylabel('Count')
# 位置分布热力图
heatmap_data = self.data[self.data['is_sideways']]
if len(heatmap_data) > 0:
x = heatmap_data['x_end'].values
y = heatmap_data['y_end'].values
# 创建热力图
hist, xedges, yedges = np.histogram2d(y, x, bins=(10, 10))
axs[1].imshow(hist.T, origin='lower', cmap='hot')
axs[1].set_title('Sideways Passes Heatmap')
axs[1].set_xlabel('X position')
axs[1].set_ylabel('Y position')
plt.tight_layout()
plt.show()
# 使用示例
analyzer = PassAnalyzer()
analyzer.data = create_pass_data() # 使用之前的数据
# 识别横传转移球
sideways_count = analyzer.identify_sideways_passes()
print(f"横传转移球次数: {sideways_count}")
# 按区域分析
zone_analysis = analyzer.analyze_by_zone()
print("\n区域分析结果:")
for zone, stats in zone_analysis.items():
print(f"{zone}: 传球{stats['total_passes']}次, 横传{stats['sideways_passes']}次, 占比{stats['percentage']:.2f}%")
# 可视化(可选)
# analyzer.visualize_distribution()
关键概念说明
-
横传转移球特征:
- 横向传球距离大(Y轴变化)
- 纵向传球距离相对较小
- 用于改变进攻方向
-
判断逻辑:
is_sideways = (y_distance > threshold) & (x_distance < max_x)
-
适用场景:
- 足球比赛分析
- 球队战术研究
- 球员决策模式分析
如果需要处理真实比赛数据,通常需要:
- 轨迹坐标数据
- 事件时间戳
- 球员和球队标识
需要我详细解释某个部分或提供特定数据格式的处理方法吗?