综合python案例,哪队的防线更稳固可靠?

wen python案例 5

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

综合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()

这个综合案例包含了:

  1. 数据结构化处理:生成模拟数据,包含多个防守指标
  2. 数据清洗:处理异常值、缺失值、添加衍生特征
  3. 统计分析:基础统计、可靠性评分、相关性分析、统计检验
  4. 数据可视化:多种图表展示分析结果
  5. 综合评分:多个维度综合评估球队防守能力

运行后会输出详细的防守分析报告,包括各队排名、统计显著性检验结果,并生成直观的可视化图表,帮助我们判断哪支球队的防线最稳固可靠。

抱歉,评论功能暂时关闭!