本文目录导读:

我来为您提供一个统计长短传比例分布的Python案例。
基础版本:简单统计分析
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from collections import Counter
# 示例数据:模拟传球数据
def generate_sample_data():
"""生成模拟传球数据"""
np.random.seed(42)
# 生成1000个传球数据
passes = []
for i in range(1000):
# 随机生成传球距离(5-50米)
distance = np.random.uniform(5, 50)
# 根据距离分类
if distance <= 15:
pass_type = '短传'
elif distance <= 25:
pass_type = '中传'
else:
pass_type = '长传'
passes.append({
'player_id': np.random.randint(1, 20),
'distance': distance,
'pass_type': pass_type,
'success': np.random.choice([True, False], p=[0.85, 0.15])
})
return pd.DataFrame(passes)
# 统计分析函数
def analyze_pass_distribution(df):
"""分析传球类型分布"""
print("="*60)
print("传球类型分布统计")
print("="*60)
# 总体分布
type_counts = df['pass_type'].value_counts()
type_percentages = df['pass_type'].value_counts(normalize=True) * 100
print("\n📊 传球类型总体分布:")
for pass_type in ['短传', '中传', '长传']:
if pass_type in type_counts.index:
count = type_counts[pass_type]
percentage = type_percentages[pass_type]
print(f" {pass_type}: {count}次 ({percentage:.1f}%)")
# 按球员统计
print("\n👥 按球员统计:")
player_stats = df.groupby('player_id').agg({
'pass_type': ['count', lambda x: (x == '短传').sum(),
lambda x: (x == '长传').sum()]
}).round(2)
# 计算比例
for player in df['player_id'].unique():
player_data = df[df['player_id'] == player]
total = len(player_data)
short_passes = len(player_data[player_data['pass_type'] == '短传'])
long_passes = len(player_data[player_data['pass_type'] == '长传'])
if total > 0:
short_ratio = short_passes / total * 100
long_ratio = long_passes / total * 100
print(f" 球员{player}: 短传{short_ratio:.1f}% / 长传{long_ratio:.1f}%")
return type_counts, type_percentages
# 创建图表
def plot_distribution(df):
"""创建图表展示分布"""
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 1. 传球类型饼图
ax1 = axes[0, 0]
type_counts = df['pass_type'].value_counts()
type_counts.plot.pie(
ax=ax1,
autopct='%1.1f%%',
colors=['#4CAF50', '#FFC107', '#FF5722']
)
ax1.set_title('传球类型分布')
# 2. 传球距离分布直方图
ax2 = axes[0, 1]
colors = ['green' if t == '短传' else 'orange' if t == '中传' else 'red'
for t in df['pass_type']]
ax2.hist(df['distance'], bins=30, color='steelblue', alpha=0.6)
ax2.axvline(x=15, color='green', linestyle='--', alpha=0.8, label='短传阈值')
ax2.axvline(x=25, color='red', linestyle='--', alpha=0.8, label='长传阈值')
ax2.set_xlabel('传球距离(米)')
ax2.set_ylabel('频次')
ax2.set_title('传球距离分布')
ax2.legend()
# 3. 球员传球风格散点图
ax3 = axes[1, 0]
player_short_ratio = []
player_long_ratio = []
for player in df['player_id'].unique():
player_data = df[df['player_id'] == player]
if len(player_data) > 0:
short_ratio = len(player_data[player_data['pass_type'] == '短传']) / len(player_data) * 100
long_ratio = len(player_data[player_data['pass_type'] == '长传']) / len(player_data) * 100
player_short_ratio.append(short_ratio)
player_long_ratio.append(long_ratio)
ax3.scatter(player_short_ratio, player_long_ratio, alpha=0.6)
ax3.set_xlabel('短传比例 (%)')
ax3.set_ylabel('长传比例 (%)')
ax3.set_title('球员传球风格')
# 4. 短传成功率对比
ax4 = axes[1, 1]
success_rates = df.groupby('pass_type')['success'].mean() * 100
success_rates.plot(kind='bar', ax=ax4, color=['#4CAF50', '#FFC107', '#FF5722'])
ax4.set_title('各类型传球成功率')
ax4.set_xlabel('传球类型')
ax4.set_ylabel('成功率 (%)')
ax4.set_ylim(80, 100)
plt.tight_layout()
plt.show()
# 主执行
if __name__ == "__main__":
# 生成数据
df = generate_sample_data()
# 统计分析
analyze_pass_distribution(df)
# 绘制图表
plot_distribution(df)
# 输出详细统计结果
print("\n📊 详细统计结果:")
print(df.groupby('pass_type').agg({
'distance': ['mean', 'std', 'min', 'max'],
'success': 'mean'
}).round(2))
进阶版本:更复杂的分析
import pandas as pd
import numpy as np
from scipy import stats
class PassAnalyzer:
"""传球数据高级分析器"""
def __init__(self, data):
self.df = data
self.calculate_metrics()
def calculate_metrics(self):
"""计算高级指标"""
self.df['pass_precision'] = np.random.uniform(70, 95, len(self.df)) # 传球精度
# 计算传球稳定性
self.df['pass_risk'] = self.df['distance'].apply(
lambda x: 0.1 if x < 10 else 0.3 if x < 20 else 0.5
)
def statistical_tests(self):
"""统计检验"""
print("\n🧪 统计检验结果:")
# 短传和长传距离的显著性检验
short_passes = self.df[self.df['pass_type'] == '短传']['pass_precision']
long_passes = self.df[self.df['pass_type'] == '长传']['pass_precision']
t_stat, p_value = stats.ttest_ind(short_passes, long_passes)
print(f"短传vs长传精度t检验: t={t_stat:.3f}, p={p_value:.3f}")
# 卡方检验
contingency_table = pd.crosstab(self.df['pass_type'], self.df['success'])
chi2, chi2_p, dof, expected = stats.chi2_contingency(contingency_table)
print(f"卡方检验: χ²={chi2:.3f}, p={chi2_p:.3f}")
def compare_players(self):
"""比较不同球员的传球风格"""
print("\n🏃 球员传球风格比较:")
player_summary = []
for player in self.df['player_id'].unique():
player_data = self.df[self.df['player_id'] == player]
if len(player_data) >= 10: # 确保样本量
avg_distance = player_data['distance'].mean()
success_rate = player_data['success'].mean() * 100
short_count = len(player_data[player_data['pass_type'] == '短传'])
long_count = len(player_data[player_data['pass_type'] == '长传'])
player_summary.append({
'player_id': player,
'avg_distance': avg_distance,
'success_rate': success_rate,
'short_passes': short_count,
'long_passes': long_count,
'short_ratio': short_count / len(player_data) * 100,
'long_ratio': long_count / len(player_data) * 100
})
summary_df = pd.DataFrame(player_summary)
print(summary_df.to_string(index=False))
return summary_df
def generate_report(self):
"""生成综合报告"""
print("\n" + "="*60)
print("🗒️ 传球数据分析报告")
print("="*60)
# 总体统计
print(f"\n📈 总体统计指标:")
print(f" - 总传球数: {len(self.df)}")
print(f" - 平均传球距离: {self.df['distance'].mean():.2f}米")
print(f" - 传球成功率: {self.df['success'].mean()*100:.1f}%")
# 类型分布
print(f"\n🎯 类型分布:")
for pass_type in ['短传', '中传', '长传']:
count = len(self.df[self.df['pass_type'] == pass_type])
percentage = count / len(self.df) * 100
print(f" - {pass_type}: {percentage:.1f}% ({count}次)")
# 推荐建议
print(f"\n💡 分析建议:")
short_ratio = len(self.df[self.df['pass_type'] == '短传']) / len(self.df) * 100
if short_ratio > 60:
print(" - 球队偏向短传控制型打法")
elif short_ratio < 40:
print(" - 球队偏向长传进攻型打法")
else:
print(" - 球队打法较为均衡")
# 使用示例
if __name__ == "__main__":
# 生成测试数据
df = generate_sample_data()
# 创建分析对象
analyzer = PassAnalyzer(df)
# 执行分析
analyzer.statistical_tests()
analyzer.compare_players()
analyzer.generate_report()
可视化增强版本
import seaborn as sns
from matplotlib.colors import LinearSegmentedColormap
# 高级可视化
def advanced_visualization(df):
"""高级可视化分析"""
fig, axes = plt.subplots(3, 2, figsize=(18, 14))
# 1. 热力图:球员×传球类型
ax1 = axes[0, 0]
pivot_table = df.pivot_table(
index='player_id',
columns='pass_type',
values='distance',
aggfunc='count'
).fillna(0)
sns.heatmap(pivot_table, ax=ax1, annot=True, cmap='YlOrRd', fmt='g')
ax1.set_title('球员传球类型热力图')
# 2. 箱线图:传球距离分布
ax2 = axes[0, 1]
sns.boxplot(data=df, x='pass_type', y='distance', ax=ax2,
palette=['#4CAF50', '#FFC107', '#FF5722'])
ax2.set_title('各类型传球距离分布')
# 3. 时间序列(如果有多场比赛数据)
ax3 = axes[1, 0]
if 'match_id' not in df.columns:
df['match_id'] = 1 # 默认单场
match_stats = df.groupby(['match_id', 'pass_type']).size().unstack().fillna(0)
match_stats.plot(kind='line', ax=ax3, marker='o')
ax3.set_title('比赛传球类型趋势')
# 4. 雷达图:球员综合能力
ax4 = axes[1, 1]
# 选择一个典型球员示例
player = df.iloc[0]['player_id']
player_data = df[df['player_id'] == player]
categories = ['短传', '中传', '长传', '成功率', '平均距离']
values = [
len(player_data[player_data['pass_type'] == '短传']) / len(player_data) * 20,
len(player_data[player_data['pass_type'] == '中传']) / len(player_data) * 20,
len(player_data[player_data['pass_type'] == '长传']) / len(player_data) * 20,
player_data['success'].mean() * 20,
player_data['distance'].mean() / 5
]
angles = np.linspace(0, 2 * np.pi, len(categories), endpoint=False).tolist()
values += values[:1]
angles += angles[:1]
ax4 = plt.subplot(3, 2, 4, polar=True)
ax4.plot(angles, values)
ax4.fill(angles, values, alpha=0.3)
ax4.set_xticks(angles[:-1])
ax4.set_xticklabels(categories)
ax4.set_title(f'球员{player}能力雷达图')
# 5. 密度图:传球距离概率密度
ax5 = axes[2, 0]
for pass_type in ['短传', '中传', '长传']:
subset = df[df['pass_type'] == pass_type]
sns.kdeplot(subset['distance'], ax=ax5, label=pass_type, shade=True)
ax5.set_title('传球距离概率密度分布')
# 6. 相关性矩阵
ax6 = axes[2, 1]
numeric_df = df[['distance', 'pass_precision', 'pass_risk', 'success']]
corr_matrix = numeric_df.corr()
sns.heatmap(corr_matrix, ax=ax6, annot=True, cmap='coolwarm', fmt='.2f')
ax6.set_title('传球指标相关性矩阵')
plt.tight_layout()
plt.show()
这个案例包含了:
- 基础统计分析:传球类型分布、比例计算
- 高级分析:统计检验、球员风格比较
- 多样化可视化:饼图、直方图、热力图、雷达图等
您可以根据实际数据格式调整字段名和阈值标准,需要更具体的功能吗?