我来设计一个综合Python案例,分析足球比赛中哪支球队的防线更稳固可靠。

项目:足球防守数据分析系统
数据生成与加载
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
import warnings
warnings.filterwarnings('ignore')
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 生成模拟数据
np.random.seed(42)
def generate_defensive_data(team_name, num_matches=38):
"""生成球队防守数据"""
matches = []
for i in range(num_matches):
# 基础防守数据
data = {
'team': team_name,
'match': i + 1,
'goals_conceded': np.random.poisson(1.2) if team_name != 'TeamA' else np.random.poisson(0.9),
'shots_against': np.random.normal(10, 3),
'tackles': np.random.normal(20, 5),
'interceptions': np.random.normal(15, 4),
'clearances': np.random.normal(12, 3),
'blocks': np.random.normal(5, 2),
'aerial_duels_won': np.random.normal(55, 10),
'possession': np.random.normal(52, 8),
'fouls': np.random.normal(10, 3),
'yellow_cards': np.random.poisson(1.5),
'red_cards': np.random.poisson(0.1)
}
matches.append(data)
return pd.DataFrame(matches)
# 生成4支球队的数据
teams = ['TeamA', 'TeamB', 'TeamC', 'TeamD']
all_data = pd.concat([generate_defensive_data(team) for team in teams], ignore_index=True)
数据清洗与预处理
class DataCleaner:
"""数据清洗类"""
@staticmethod
def clean_data(df):
"""清洗数据"""
df_clean = df.copy()
# 处理异常值(使用IQR方法)
numeric_cols = df_clean.select_dtypes(include=[np.number]).columns
for col in numeric_cols:
Q1 = df_clean[col].quantile(0.25)
Q3 = df_clean[col].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 用边界值替换异常值
df_clean[col] = df_clean[col].clip(lower_bound, upper_bound)
# 处理缺失值
df_clean = df_clean.fillna(df_clean.median())
return df_clean
@staticmethod
def add_derived_features(df):
"""添加衍生特征"""
df = df.copy()
# 防守效率指数(综合考虑多个因素)
df['defense_efficiency'] = (
df['goals_conceded'].rank(method='average') * 0.3 +
(100 - df['shots_against'].rank(method='average')) * 0.2 +
df['tackles'].rank(method='average') * 0.15 +
df['interceptions'].rank(method='average') * 0.15 +
df['clearances'].rank(method='average') * 0.1 +
df['aerial_duels_won'].rank(method='average') * 0.1
)
# 防守强度评分
df['defense_strength'] = (
(df['goals_conceded'].mean() / (df['goals_conceded'] + 1)) * 100 +
(df['tackles'] + df['interceptions']) * 0.1 +
df['aerial_duels_won'] * 0.05
)
return df
# 清洗数据
cleaner = DataCleaner()
clean_data = cleaner.clean_data(all_data)
clean_data = cleaner.add_derived_features(clean_data)
数据分析与计算
class DefensiveAnalyzer:
"""防守分析器"""
def __init__(self, df):
self.df = df
self.teams = df['team'].unique()
def basic_stats(self):
"""基础统计分析"""
stats_df = []
for team in self.teams:
team_data = self.df[self.df['team'] == team]
stats = {
'team': team,
'avg_goals_conceded': team_data['goals_conceded'].mean(),
'goals_std': team_data['goals_conceded'].std(),
'avg_shots_against': team_data['shots_against'].mean(),
'clean_sheets': (team_data['goals_conceded'] == 0).sum(),
'tackles_per_match': team_data['tackles'].mean(),
'interceptions_per_match': team_data['interceptions'].mean(),
'clearances_per_match': team_data['clearances'].mean(),
'blocks_per_match': team_data['blocks'].mean(),
'aerial_duels_won_rate': team_data['aerial_duels_won'].mean(),
'avg_possession': team_data['possession'].mean(),
'fouls_per_match': team_data['fouls'].mean(),
'discipline_score': 100 - (team_data['yellow_cards'].mean() * 2 + team_data['red_cards'].mean() * 5)
}
stats_df.append(stats)
return pd.DataFrame(stats_df)
def reliability_score(self):
"""计算防守可靠性评分"""
scores = []
for team in self.teams:
team_data = self.df[self.df['team'] == team]
# 多个维度的评分
consistency = 100 / (1 + team_data['goals_conceded'].std())
avg_performance = 100 / (1 + team_data['goals_conceded'].mean())
recovery_ability = (team_data['goals_conceded'] <= 1).sum() / len(team_data) * 100
pressure_resistance = 100 / (1 + team_data['shots_against'].mean() / 10)
discipline = 100 - (team_data['yellow_cards'].mean() * 2 + team_data['red_cards'].mean() * 5)
# 综合评分(加权平均)
total_score = (
consistency * 0.25 +
avg_performance * 0.25 +
recovery_ability * 0.20 +
pressure_resistance * 0.15 +
discipline * 0.15
)
scores.append({
'team': team,
'consistency': consistency,
'avg_performance': avg_performance,
'recovery_ability': recovery_ability,
'pressure_resistance': pressure_resistance,
'discipline': discipline,
'reliability_score': total_score
})
return pd.DataFrame(scores)
def correlation_analysis(self):
"""相关性分析"""
corr_columns = ['goals_conceded', 'shots_against', 'tackles',
'interceptions', 'clearances', 'aerial_duels_won']
return self.df[corr_columns].corr()
def statistical_test(self):
"""统计显著性检验"""
results = {}
# 方差分析(ANOVA)
goals_by_team = [group['goals_conceded'].values
for name, group in self.df.groupby('team')]
anova_result = stats.f_oneway(*goals_by_team)
results['anova_f_statistic'] = anova_result.statistic
results['anova_p_value'] = anova_result.pvalue
# 两两t检验
t_test_results = []
for i in range(len(self.teams)):
for j in range(i+1, len(self.teams)):
team1 = self.teams[i]
team2 = self.teams[j]
t_stat, p_value = stats.ttest_ind(
self.df[self.df['team'] == team1]['goals_conceded'],
self.df[self.df['team'] == team2]['goals_conceded']
)
t_test_results.append({
'teams': f'{team1} vs {team2}',
't_statistic': t_stat,
'p_value': p_value,
'significant': p_value < 0.05
})
results['pairwise_tests'] = pd.DataFrame(t_test_results)
return results
# 执行分析
analyzer = DefensiveAnalyzer(clean_data)
basic_stats = analyzer.basic_stats()
reliability = analyzer.reliability_score()
correlations = analyzer.correlation_analysis()
statistical_results = analyzer.statistical_test()
可视化
def visualize_analysis(basic_stats, reliability, analyzer_data):
"""可视化分析结果"""
fig = plt.figure(figsize=(20, 15))
# 1. 进球失球对比图
ax1 = plt.subplot(3, 3, 1)
teams = basic_stats['team']
x = np.arange(len(teams))
bars1 = ax1.bar(x, basic_stats['avg_goals_conceded'],
color='skyblue', label='失球数')
bars2 = ax1.bar(x, basic_stats['goals_std'],
color='lightcoral', bottom=basic_stats['avg_goals_conceded'],
label='标准差')
for i, (bar1, bar2) in enumerate(zip(bars1, bars2)):
height = bar1.get_height() + bar2.get_height()
ax1.text(bar1.get_x() + bar1.get_width()/2, height + 0.1,
f'{bar1.get_height():.2f}', ha='center', va='bottom')
ax1.set_xticks(x)
ax1.set_xticklabels(teams)
ax1.set_ylabel('平均失球数')
ax1.set_title('平均失球数及波动范围')
ax1.legend()
ax1.grid(True, alpha=0.3)
# 2. 防守关键指标雷达图
ax2 = plt.subplot(3, 3, 2, projection='polar')
metrics = ['抢断', '拦截', '解围', '封堵', '控球率']
angles = np.linspace(0, 2 * np.pi, len(metrics), endpoint=False).tolist()
angles += angles[:1]
radar_data = basic_stats[['tackles_per_match', 'interceptions_per_match',
'clearances_per_match', 'blocks_per_match',
'avg_possession']].values
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4']
for idx, (team, values) in enumerate(zip(basic_stats['team'], radar_data)):
# 归一化
values_norm = values / values.mean()
values_norm = values_norm.tolist() + values_norm[:1]
ax2.plot(angles, values_norm, 'o-', linewidth=2,
label=team, color=colors[idx])
ax2.fill(angles, values_norm, alpha=0.25, color=colors[idx])
ax2.set_xticks(angles[:-1])
ax2.set_xticklabels(metrics)
ax2.set_title('防守关键指标对比')
ax2.legend(loc='upper right', bbox_to_anchor=(1.3, 1.0))
# 3. 可靠性评分对比
ax3 = plt.subplot(3, 3, 3)
scores = reliability.sort_values('reliability_score', ascending=False)
bars = ax3.bar(scores['team'], scores['reliability_score'],
color=['#4CAF50' if s > scores['reliability_score'].mean() else '#FF9800'
for s in scores['reliability_score']])
for bar, score in zip(bars, scores['reliability_score']):
ax3.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.5,
f'{score:.1f}', ha='center', va='bottom')
ax3.axhline(scores['reliability_score'].mean(), color='red',
linestyle='--', alpha=0.5, label='平均值')
ax3.set_xlabel('球队')
ax3.set_ylabel('可靠性评分')
ax3.set_title('防守可靠性综合评分')
ax3.legend()
ax3.set_ylim(0, scores['reliability_score'].max() * 1.2)
ax3.grid(True, alpha=0.3)
ax3.tick_params(axis='x', rotation=45)
# 4. 相关性热力图
ax4 = plt.subplot(3, 3, 4)
sns.heatmap(analyzer_data['correlations'], annot=True, fmt='.3f',
cmap='RdBu_r', center=0, ax=ax4, square=True)
ax4.set_title('防守指标相关性矩阵')
# 5. 零封场次对比
ax5 = plt.subplot(3, 3, 5)
clean_sheets = basic_stats[['team', 'clean_sheets']].sort_values('clean_sheets',
ascending=False)
bars = ax5.bar(clean_sheets['team'], clean_sheets['clean_sheets'],
color='#2196F3')
for bar, count in zip(bars, clean_sheets['clean_sheets']):
ax5.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.3,
f'{int(count)}', ha='center', va='bottom')
ax5.set_xlabel('球队')
ax5.set_ylabel('零封场次')
ax5.set_title('零封对手场次对比')
ax5.grid(True, alpha=0.3)
ax5.tick_params(axis='x', rotation=45)
# 6. 控球率与失球数散点图
ax6 = plt.subplot(3, 3, 6)
colors = plt.cm.Set1(np.linspace(0, 1, len(analyzer_data['df']['team'].unique())))
for idx, team in enumerate(analyzer_data['df']['team'].unique()):
team_data = analyzer_data['df'][analyzer_data['df']['team'] == team]
ax6.scatter(team_data['possession'], team_data['goals_conceded'],
alpha=0.6, label=team, color=colors[idx])
# 添加趋势线
z = np.polyfit(analyzer_data['df']['possession'],
analyzer_data['df']['goals_conceded'], 1)
p = np.poly1d(z)
ax6.plot(np.unique(analyzer_data['df']['possession']),
p(np.unique(analyzer_data['df']['possession'])),
"r--", alpha=0.5, label='趋势线')
ax6.set_xlabel('控球率 (%)')
ax6.set_ylabel('失球数')
ax6.set_title('控球率与失球数关系')
ax6.legend()
ax6.grid(True, alpha=0.3)
# 7. 防守效率分布箱线图
ax7 = plt.subplot(3, 3, 7)
defense_data = [analyzer_data['df'][analyzer_data['df']['team'] == team]['defense_strength']
for team in analyzer_data['df']['team'].unique()]
bp = ax7.boxplot(defense_data, labels=analyzer_data['df']['team'].unique())
ax7.set_xlabel('球队')
ax7.set_ylabel('防守强度')
ax7.set_title('防守强度分布')
ax7.grid(True, alpha=0.3)
ax7.tick_params(axis='x', rotation=45)
# 8. 统计检验结果
ax8 = plt.subplot(3, 3, 8)
ax8.axis('off')
p_values = statistical_results['pairwise_tests'][['teams', 'p_value', 'significant']]
# 创建表格
table_data = []
for _, row in p_values.iterrows():
table_data.append([row['teams'], f"{row['p_value']:.4f}",
"显著" if row['significant'] else "不显著"])
table = ax8.table(cellText=table_data,
colLabels=['对比球队', 'p值', '显著性'],
cellLoc='center', loc='center',
colWidths=[0.3, 0.15, 0.18])
table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1, 1.8)
ax8.set_title('统计检验结果(两两对比)')
# 9. 综合评分对比
ax9 = plt.subplot(3, 3, 9)
composite_scores = basic_stats.copy()
composite_scores['综合得分'] = (
(100 / (1 + composite_scores['avg_goals_conceded'])) * 0.3 +
(composite_scores['avg_possession'] / 100) * 100 * 0.2 +
(composite_scores['tackles_per_match'] /
composite_scores['tackles_per_match'].max()) * 100 * 0.2 +
(composite_scores['interceptions_per_match'] /
composite_scores['interceptions_per_match'].max()) * 100 * 0.15 +
(composite_scores['aerial_duels_won_rate'] /
composite_scores['aerial_duels_won_rate'].max()) * 100 * 0.15
)
composite_scores = composite_scores.sort_values('综合得分', ascending=False)
bars = ax9.bar(composite_scores['team'], composite_scores['综合得分'],
color=['#FF5733' if s > composite_scores['综合得分'].mean()
else '#33A8FF' for s in composite_scores['综合得分']])
for bar, score in zip(bars, composite_scores['综合得分']):
ax9.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 1,
f'{score:.1f}', ha='center', va='bottom')
ax9.set_xlabel('球队')
ax9.set_ylabel('综合得分')
ax9.set_title('防守综合能力对比')
ax9.grid(True, alpha=0.3)
ax9.tick_params(axis='x', rotation=45)
plt.tight_layout()
plt.show()
主程序执行
def main():
"""主程序"""
print("=" * 60)
print(" 足球防守数据分析报告")
print("=" * 60)
# 执行分析
analyzer = DefensiveAnalyzer(clean_data)
print("\n【1】基础数据统计:")
print("-" * 60)
basic_stats = analyzer.basic_stats()
display_cols = ['team', 'avg_goals_conceded', 'goals_std', 'clean_sheets',
'avg_possession', 'tackles_per_match', 'interceptions_per_match']
print(basic_stats[display_cols].to_string(index=False))
print("\n【2】各防守指标排名:")
print("-" * 60)
metrics = {
'avg_goals_conceded': '平均失球',
'clean_sheets': '零封场次',
'tackles_per_match': '场均抢断',
'interceptions_per_match': '场均拦截',
'aerial_duels_won_rate': '制空权'
}
for col, label in metrics.items():
ranked = basic_stats[['team', col]].sort_values(col, ascending=False if '抢断' in label or '拦截' in label or '制空' in label else True)
print(f"{label}排名: {' > '.join(ranked['team'])}")
print("\n【3】防守可靠性评分:")
print("-" * 60)
reliability = analyzer.reliability_score()
reliability_sorted = reliability.sort_values('reliability_score', ascending=False)
for _, row in reliability_sorted.iterrows():
print(f"{row['team']}: {row['reliability_score']:.2f} 分")
print("\n【4】统计显著性检验:")
print("-" * 60)
stat_results = analyzer.statistical_test()
print(f"ANOVA F值: {stat_results['anova_f_statistic']:.3f}")
print(f"ANOVA p值: {stat_results['anova_p_value']:.4f}")
if stat_results['anova_p_value'] < 0.05:
print("各队防守水平存在显著差异 (p < 0.05)")
else:
print("各队防守水平无显著差异 (p > 0.05)")
print("\n【5】最终排名结论:")
print("-" * 60)
# 综合所有指标进行最终排名
final_rank = []
for team in basic_stats['team']:
team_stats = basic_stats[basic_stats['team'] == team].iloc[0]
team_reliability = reliability[reliability['team'] == team].iloc[0]
score = (team_stats['avg_goals_conceded'] * -10 + # 失球越少越好
team_stats['clean_sheets'] * 2 +
team_reliability['reliability_score'])
final_rank.append({'team': team, 'final_score': score,
'reliability': team_reliability['reliability_score']})
# 排序并输出结果
final_df = pd.DataFrame(final_rank).sort_values('final_score', ascending=False)
rank_emojis = ['🥇', '🥈', '🥉', '🏅']
print("\n最终防守排名:")
for i, (_, row) in enumerate(final_df.iterrows()):
medal = rank_emojis[i] if i < 4 else ''
print(f"{medal} 第{i+1}名: {row['team']} (综合评分: {row['final_score']:.2f})")
# 输出最终结论
best_team = final_df.iloc[0]['team']
print(f"\n【{best_team} 的防线最稳固可靠!")
# 可视化
visualize_analysis(basic_stats, reliability,
{'df': clean_data, 'correlations': correlations})
return final_df
if __name__ == "__main__":
results = main()
这个综合案例包含了:
- 数据结构化处理:生成模拟数据,包含多个防守指标
- 数据清洗:处理异常值、缺失值、添加衍生特征
- 统计分析:基础统计、可靠性评分、相关性分析、统计检验
- 数据可视化:多种图表展示分析结果
- 综合评分:多个维度综合评估球队防守能力
运行后会输出详细的防守分析报告,包括各队排名、统计显著性检验结果,并生成直观的可视化图表,帮助我们判断哪支球队的防线最稳固可靠。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播