捷克1-1战平南非

作者:







使用Python分析世界杯比赛数据:以捷克1-1战平南非为例


使用Python分析世界杯比赛数据:以捷克1-1战平南非为例

简介

足球比赛的数据分析已成为现代体育的重要组成部分。本文将通过一个具体案例——2026年世界杯A组第二轮捷克1-1战平南非的比赛,教你如何使用Python进行比赛数据收集、处理和分析。你将学习到从网页抓取比赛数据、清理数据、进行可视化分析的基本流程,并了解如何利用数据得出有趣的结论。

即使你不是体育迷,这个教程也能帮你掌握数据处理的实用技能,这些技能可以应用于各种领域的数据分析任务。

前置准备

在开始之前,请确保你已经准备好以下环境和工具:

  1. Python环境:建议安装Python 3.8或更高版本
  2. 代码编辑器:机械键盘 可以提升编码效率,推荐使用VS Code或PyCharm
  3. 必要的Python库
  4. requests:用于网络请求
  5. beautifulsoup4:用于解析HTML
  6. pandas:数据处理和分析
  7. matplotlib:数据可视化
  8. seaborn:更美观的统计图表

安装这些库的命令:

pip install requests beautifulsoup4 pandas matplotlib seaborn
  1. 可靠的网络连接:用于获取在线数据
  2. 数据存储:确保有足够的空间存储处理后的数据

如果你需要一台性能良好的笔记本电脑来运行这些代码,可以考虑购买具备足够内存和处理能力的型号。

步骤一:获取比赛基础数据

首先,我们需要获取比赛的基本信息。这里我们模拟从体育网站获取数据的过程,实际应用中可能需要根据具体网站调整解析逻辑。

import requests
from bs4 import BeautifulSoup
import pandas as pd
import json
from datetime import datetime

def fetch_match_basic_info():
    """获取比赛基础信息"""
    # 模拟比赛数据(实际应用中会从网站解析)
    match_data = {
        "tournament": "2026 FIFA World Cup",
        "group": "A",
        "round": "Group Stage - Matchday 2",
        "date": "2025-06-19",
        "time": "02:00 (UTC+8)",
        "venue": "MetLife Stadium, New Jersey",
        "attendance": 65432,
        "referee": "Michael Oliver (England)",
        "weather": "Clear, 22°C"
    }

    # 比赛基本信息
    match_info = {
        "home_team": "Czech Republic",
        "away_team": "South Africa",
        "final_score": "1-1",
        "home_score": 1,
        "away_score": 1,
        "home_scorers": ["Patrik Schick 38'"],
        "away_scorers": ["Percy Tau 65'"],
        "competition_stage": "Group Stage"
    }

    return {**match_data, **match_info}

# 获取并打印比赛信息
match_info = fetch_match_basic_info()
print("比赛基本信息:")
for key, value in match_info.items():
    print(f"{key}: {value}")

步骤二:获取详细比赛统计数据

接下来,我们获取更详细的比赛统计,包括控球率、射门次数、传球成功率等关键指标。

def fetch_match_statistics():
    """获取比赛详细统计数据"""
    stats_data = {
        "home_team_stats": {
            "team": "Czech Republic",
            "possession": 52.3,
            "total_shots": 14,
            "shots_on_target": 5,
            "shots_off_target": 9,
            "blocked_shots": 3,
            "corner_kicks": 7,
            "offsides": 2,
            "fouls": 12,
            "yellow_cards": 2,
            "red_cards": 0,
            "passes": 487,
            "pass_accuracy": 84.2,
            "crosses": 18,
            "cross_accuracy": 33.3,
            "duels_won": 62,
            "aerial_duels_won": 15,
            "tackles": 18,
            "interceptions": 10
        },
        "away_team_stats": {
            "team": "South Africa",
            "possession": 47.7,
            "total_shots": 10,
            "shots_on_target": 4,
            "shots_off_target": 6,
            "blocked_shots": 2,
            "corner_kicks": 4,
            "offsides": 3,
            "fouls": 15,
            "yellow_cards": 3,
            "red_cards": 0,
            "passes": 423,
            "pass_accuracy": 81.8,
            "crosses": 12,
            "cross_accuracy": 25.0,
            "duels_won": 58,
            "aerial_duels_won": 18,
            "tackles": 21,
            "interceptions": 8
        },
        "key_stats": {
            "expected_goals": {"Czech Republic": 1.42, "South Africa": 1.18},
            "big_chances": {"Czech Republic": 3, "South Africa": 2},
            "save_percentage": {"Czech Republic": 75.0, "South Africa": 80.0}
        }
    }

    return stats_data

# 获取统计数据
match_stats = fetch_match_statistics()

# 将数据转换为DataFrame便于分析
home_stats = pd.DataFrame([match_stats["home_team_stats"]])
away_stats = pd.DataFrame([match_stats["away_team_stats"]])

print("\n比赛统计数据:")
print("=" * 50)
print("捷克队统计:")
for key, value in match_stats["home_team_stats"].items():
    if key != "team":
        print(f"{key}: {value}")
print("\n南非队统计:")
for key, value in match_stats["away_team_stats"].items():
    if key != "team":
        print(f"{key}: {value}")

步骤三:数据清洗与预处理

实际获取的数据可能包含缺失值或异常值,我们需要进行清洗和预处理。

def clean_and_preprocess_data(stats_data):
    """清洗和预处理比赛数据"""

    # 创建比较DataFrame
    comparison_df = pd.DataFrame({
        'Statistic': list(stats_data['home_team_stats'].keys())[1:],  # 排除team字段
        'Czech Republic': list(stats_data['home_team_stats'].values())[1:],
        'South Africa': list(stats_data['away_team_stats'].values())[1:]
    })

    # 添加差异列
    comparison_df['Difference'] = comparison_df['Czech Republic'] - comparison_df['South Africa']

    # 添加优势方标记
    comparison_df['Advantage'] = comparison_df['Difference'].apply(
        lambda x: 'Czech Republic' if x > 0 else 'South Africa' if x < 0 else 'Even'
    )

    # 计算百分比类型数据的标准化值
    percentage_stats = ['possession', 'pass_accuracy', 'cross_accuracy', 'save_percentage']

    for stat in percentage_stats:
        if stat in comparison_df['Statistic'].values:
            idx = comparison_df[comparison_df['Statistic'] == stat].index[0]
            comparison_df.loc[idx, 'Czech Republic'] = f"{comparison_df.loc[idx, 'Czech Republic']}%"
            comparison_df.loc[idx, 'South Africa'] = f"{comparison_df.loc[idx, 'South Africa']}%"

    return comparison_df

# 清洗数据
comparison_df = clean_and_preprocess_data(match_stats)

print("\n数据对比表:")
print(comparison_df.to_string(index=False))

步骤四:数据可视化分析

使用图表可以更直观地展示比赛数据。我们将创建多个可视化图表来分析比赛。

import matplotlib.pyplot as plt
import seaborn as sns

def create_match_visualizations(stats_data):
    """创建比赛数据可视化图表"""

    # 设置中文字体支持
    plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
    plt.rcParams['axes.unicode_minus'] = False

    # 创建图表
    fig, axes = plt.subplots(2, 2, figsize=(15, 12))

    # 1. 基础统计对比条形图
    basic_stats = ['total_shots', 'shots_on_target', 'corner_kicks', 'fouls']
    home_values = [stats_data['home_team_stats'][stat] for stat in basic_stats]
    away_values = [stats_data['away_team_stats'][stat] for stat in basic_stats]

    x = range(len(basic_stats))
    width = 0.35

    axes[0, 0].bar([i - width/2 for i in x], home_values, width, label='捷克', color='#D32F2F')
    axes[0, 0].bar([i + width/2 for i in x], away_values, width, label='南非', color='#1B5E20')
    axes[0, 0].set_xlabel('统计项目')
    axes[0, 0].set_ylabel('数量')
    axes[0, 0].set_title('基础比赛统计对比')
    axes[0, 0].set_xticks(x)
    axes[0, 0].set_xticklabels(['总射门', '射正', '角球', '犯规'])
    axes[0, 0].legend()
    axes[0, 0].grid(True, alpha=0.3)

    # 2. 控球率饼图
    possession_data = [stats_data['home_team_stats']['possession'], 
                       stats_data['away_team_stats']['possession']]
    labels = ['捷克', '南非']
    colors = ['#D32F2F', '#1B5E20']

    axes[0, 1].pie(possession_data, labels=labels, colors=colors, autopct='%1.1f%%', 
                   startangle=90, textprops={'fontsize': 12})
    axes[0, 1].set_title('控球率对比')

    # 3. 传球成功率对比
    pass_stats = ['passes', 'pass_accuracy']
    pass_data = {
        '捷克': [stats_data['home_team_stats']['passes'], 
                stats_data['home_team_stats']['pass_accuracy']],
        '南非': [stats_data['away_team_stats']['passes'], 
                stats_data['away_team_stats']['pass_accuracy']]
    }

    pass_df = pd.DataFrame(pass_data, index=['传球次数', '传球成功率(%)'])
    pass_df.plot(kind='bar', ax=axes[1, 0], color=['#D32F2F', '#1B5E20'])
    axes[1, 0].set_title('传球数据对比')
    axes[1, 0].set_ylabel('数值')
    axes[1, 0].tick_params(axis='x', rotation=0)
    axes[1, 0].grid(True, alpha=0.3)

    # 4. 预期进球(xG)对比
    xg_data = [stats_data['key_stats']['expected_goals']['Czech Republic'],
               stats_data['key_stats']['expected_goals']['South Africa']]

    bars = axes[1, 1].bar(labels, xg_data, color=colors)
    axes[1, 1].set_title('预期进球(xG)对比')
    axes[1, 1].set_ylabel('xG值')
    axes[1, 1].grid(True, alpha=0.3)

    # 添加数值标签
    for bar, value in zip(bars, xg_data):
        height = bar.get_height()
        axes[1, 1].text(bar.get_x() + bar.get_width()/2., height + 0.05,
                f'{value:.2f}', ha='center', va='bottom', fontsize=12)

    plt.tight_layout()
    plt.savefig('match_analysis.png', dpi=300, bbox_inches='tight')
    plt.show()

    print("\n可视化图表已保存为 'match_analysis.png'")

# 创建可视化
create_match_visualizations(match_stats)

步骤五:使用机器学习进行比赛模式分析

我们可以使用简单的聚类分析来识别比赛中的不同阶段和模式。

“`python
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import numpy as np

def analyze_match_patterns():
“”“分析比赛模式”“”
# 模拟比赛时间段数据(每5分钟为一个时间段)
time_periods = list(range(0, 95, 5)) # 0-90分钟,每5分钟

# 模拟每个时间段的事件数据
np.random.seed(42)  # 保证结果可重现

# 捷克队每个时间段的进攻活动
czech_attack = np.random.poisson(2.5, len(time_periods))
czech_attack[7] = 4  # 第35-40分钟(进球时段)进攻活动增加
czech_attack[8] = 3  # 第40-45分钟

# 南非队每个时间段的进攻活动
south_africa_attack = np.random.poisson(1.8, len(time_periods))
south_africa_attack[12] = 4  # 第60-65分钟(进球时段)进攻活动增加
south_africa_attack[13] = 3  # 第65-70分钟

# 创建数据矩阵
X = np.column_stack([czech_attack, south_africa_attack])

# 标准化数据
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 使用K-means聚类分析
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
clusters = kmeans.fit_predict(X_scaled)

# 可视化聚类结果
plt.figure(figsize=(12, 6))

# 按聚类着色
colors = ['red', 'blue', 'green']
for i in range(3):
    mask = clusters == i
    plt.scatter(np.array(time_periods)[mask], X[mask, 0], 
               color=colors[i], label=f'阶段 {i+1}', alpha=0.7, s=100)
    plt.scatter(np.array(time_periods)[mask], X[mask, 1], 
               color=colors[i], alpha=0.7, s=100, marker='x')

plt.xlabel('比赛时间(分钟)')
plt.ylabel('进攻活动指数')
plt.title('比赛模式聚类分析')
plt.legend(['捷克进攻', '南非进攻'])
plt.grid(True, alpha=0.3)

# 添加进球时间标记
plt.axvline(x=38, color='gray', linestyle='--', alpha=0.5)
plt.text(38, max(X[:, 0]), '捷克进球', rotation=90, alpha=0.7)

plt.axvline(x=65, color='gray', linestyle='--', alpha=0.5)
plt.text(65, max(X[:, 0]), '南非进球', rotation=90, alpha=0.7)

plt.tight_layout()
plt.savefig('match_patterns.png', dpi=300)
plt.show()

# 分析聚类结果
print("\n比赛阶段分析:")
for i in range(3):
    cluster_mask = clusters == i
    cluster_times = np.array(time_periods)[cluster_mask]

    if len(cluster_times) > 0:
        print(f"\n