实用脚本统计长短传比例如何分布?

wen 实用脚本 5

本文目录导读:

实用脚本统计长短传比例如何分布?

  1. 使用方法
  2. 输出示例
  3. 功能特点
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
足球传球长短传比例统计脚本
支持从CSV或纯文本数据中读取传球记录,统计短传/中传/长传的比例分布。
"""
import csv
import sys
import os
from collections import Counter
from typing import List, Dict, Tuple
# ==================== 配置参数 ====================
# 传球距离分类阈值(单位:码或米,请根据你的数据统一单位)
SHORT_PASS_MAX = 15      # 小于等于此距离为短传
LONG_PASS_MIN = 30       # 大于等于此距离为长传
# 中间范围(15 < 距离 < 30)自动归为中传
# ==================== 核心统计函数 ====================
def classify_pass(distance: float) -> str:
    """根据距离对传球进行分类"""
    if distance <= SHORT_PASS_MAX:
        return "短传"
    elif distance >= LONG_PASS_MIN:
        return "长传"
    else:
        return "中传"
def parse_csv(file_path: str) -> List[float]:
    """从CSV文件中读取传球距离数据(支持'distance'列或第一列)"""
    distances = []
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            # 使用DictReader自动读取表头
            reader = csv.DictReader(f)
            # 如果CSV没有表头,则手动指定第一列为距离
            if not reader.fieldnames:
                f.seek(0)
                reader = csv.reader(f)
                for row in reader:
                    if row and row[0].strip():
                        try:
                            distances.append(float(row[0]))
                        except ValueError:
                            print(f"警告: 无法解析行 '{row}' 中的数据,已跳过")
            else:
                # 优先查找常见列名
                distance_col = None
                possible_names = ['distance', 'Distance', '距离', 'pass_length', 'length', 'dist']
                for name in possible_names:
                    if name in reader.fieldnames:
                        distance_col = name
                        break
                if not distance_col:
                    # 默认使用第一列
                    distance_col = reader.fieldnames[0]
                    print(f"提示: 未找到标准距离列名,默认使用 '{distance_col}' 列")
                for row in reader:
                    try:
                        val = row[distance_col].strip()
                        if val:
                            distances.append(float(val))
                    except (ValueError, KeyError):
                        print(f"警告: 第 {reader.line_num} 行距离数据无效")
    except FileNotFoundError:
        print(f"错误: 文件 '{file_path}' 不存在")
        sys.exit(1)
    except Exception as e:
        print(f"读取文件时发生错误: {e}")
        sys.exit(1)
    return distances
def parse_txt(file_path: str) -> List[float]:
    """从纯文本文件中读取数字(每行一个距离,或空格分隔)"""
    distances = []
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            for line_num, line in enumerate(f, 1):
                # 支持逗号或空格分隔的多值行
                parts = line.replace(',', ' ').split()
                for part in parts:
                    try:
                        distances.append(float(part))
                    except ValueError:
                        print(f"警告: 第 {line_num} 行 '{part}' 不是有效数字,已忽略")
    except FileNotFoundError:
        print(f"错误: 文件 '{file_path}' 不存在")
        sys.exit(1)
    return distances
def load_data(file_path: str) -> List[float]:
    """根据文件扩展名自动选择解析方法"""
    ext = os.path.splitext(file_path)[1].lower()
    if ext == '.csv':
        return parse_csv(file_path)
    else:  # 默认按文本处理
        return parse_txt(file_path)
def compute_distribution(distances: List[float]) -> Tuple[Dict[str, int], Dict[str, float]]:
    """计算长短传比例分布"""
    if not distances:
        print("错误: 没有有效的传球距离数据")
        sys.exit(1)
    # 统计分类
    classification = Counter(classify_pass(d) for d in distances)
    total = len(distances)
    # 计算百分比
    percentages = {k: (v / total) * 100 for k, v in classification.items()}
    return classification, percentages
# ==================== 输出格式化 ====================
def print_report(distances: List[float], counts: Dict[str, int], percentages: Dict[str, float]):
    """打印清晰的分析报告"""
    total = len(distances)
    print("\n" + "="*50)
    print(f"传球距离统计分析报告")
    print("="*50)
    print(f"总传球次数: {total}")
    print(f"分类标准: 短传 ≤ {SHORT_PASS_MAX} | 中传 ({SHORT_PASS_MAX} < d < {LONG_PASS_MIN}) | 长传 ≥ {LONG_PASS_MIN}")
    print("-"*50)
    # 按顺序输出三类
    for category in ['短传', '中传', '长传']:
        count = counts.get(category, 0)
        pct = percentages.get(category, 0)
        bar_len = int(pct / 2)  # 简化可视化,每'#'代表2%
        print(f"{category}: {count:5d} 次 ({pct:5.1f}%) {'#' * bar_len}")
    # 额外统计信息
    print("-"*50)
    if distances:
        avg = sum(distances) / len(distances)
        max_d = max(distances)
        min_d = min(distances)
        print(f"平均传球距离: {avg:.1f}")
        print(f"最长传球: {max_d:.1f}")
        print(f"最短传球: {min_d:.1f}")
    # 长短传比值(短传/长传)
    short = counts.get('短传', 0)
    long = counts.get('长传', 0)
    if long > 0:
        ratio = short / long
        print(f"短传/长传比例: {ratio:.2f} : 1")
    else:
        print("短传/长传比例: 无长传数据")
    print("="*50)
# ==================== 主程序入口 ====================
def main():
    # 命令行参数处理
    if len(sys.argv) < 2:
        print("用法: python pass_analysis.py <数据文件> [--thresholds 短传阈值 长传阈值]")
        print("示例: python pass_analysis.py passes.csv")
        print("      python pass_analysis.py passes.txt --thresholds 10 25")
        sys.exit(1)
    file_path = sys.argv[1]
    # 可选阈值参数
    global SHORT_PASS_MAX, LONG_PASS_MIN
    if '--thresholds' in sys.argv:
        idx = sys.argv.index('--thresholds')
        try:
            SHORT_PASS_MAX = float(sys.argv[idx+1])
            LONG_PASS_MIN = float(sys.argv[idx+2])
        except (IndexError, ValueError):
            print("错误: --thresholds 需要两个数值参数")
            sys.exit(1)
    # 加载数据
    print(f"正在读取文件: {file_path}")
    distances = load_data(file_path)
    print(f"成功读取 {len(distances)} 条传球数据")
    # 统计与输出
    counts, percentages = compute_distribution(distances)
    print_report(distances, counts, percentages)
if __name__ == "__main__":
    main()

使用方法

  1. 数据准备:将传球距离数据保存为 CSV 或纯文本文件

    • CSV 格式示例(支持 distance 列名或直接用第一列):
      distance
      12.5
      28.3
      45.2
      8.7
    • 纯文本格式示例(每行一个数字,或空格分隔):
      5 28.3 45.2
      8.7 19.4 33.1
  2. 运行脚本

    python pass_analysis.py 传球数据.csv
  3. 自定义阈值(可选):

    python pass_analysis.py 传球数据.csv --thresholds 10 25

输出示例

==================================================
传球距离统计分析报告
==================================================
总传球次数: 156
分类标准: 短传 ≤ 15 | 中传 (15 < d < 30) | 长传 ≥ 30
--------------------------------------------------
短传:    78 次 ( 50.0%) #########################
中传:    52 次 ( 33.3%) #################
长传:    26 次 ( 16.7%) #########
--------------------------------------------------
平均传球距离: 21.4
最长传球: 67.2
最短传球: 3.1
短传/长传比例: 3.00 : 1
==================================================

功能特点

  • 自动识别文件类型:根据扩展名选择解析方式
  • 灵活阈值设置:通过命令行参数调整长短传分类标准
  • 容错处理:自动跳过无效数据并给出警告
  • 可视化输出:用条状图直观展示比例分布
  • 额外统计:包含平均距离、最大/最小值和短长传比值

您可以根据实际数据格式调整 parse_csvparse_txt 函数,或修改分类阈值来适配您的分析需求。

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