根据java案例,进攻三区传球成功率?

wen java案例 1

进攻三区传球成功率分析(Java 案例)

由于你没有贴出具体的 Java 案例代码,我按足球数据分析场景中最常见的实现方式给你一份完整的 Java 示例,并说明该怎么在这个案例里计算"进攻三区传球成功率"。

根据java案例,进攻三区传球成功率?


概念定义

概念 说明
进攻三区(Final Third) 足球场按纵向划分为防守三区、中场三区、进攻三区,进攻三区通常指距对方球门 0~35 米(或按场地长度 1/3)的区域
传球成功率 成功传球次数 / 总传球次数 × 100%
进攻三区传球成功率 在进攻三区内发起(或完成)的传球中,成功次数占总次数的比例

⚠️ 关键口径要统一:是"传球起点在进攻三区"还是"传球终点在进攻三区",不同数据源(Opta / Wyscout / StatsBomb)定义不同,代码里必须明确。


Java 案例代码

实体类:传球事件

public class PassEvent {
    private String playerId;
    private double startX;      // 传球起点 x 坐标(0~105,单位米)
    private double endX;        // 传球终点 x 坐标
    private boolean success;    // 是否成功
    private double fieldLength = 105.0; // 场地长度
    // 判断起点是否在进攻三区(假设进攻方向为 x 增大)
    public boolean isStartInFinalThird() {
        return startX >= fieldLength * 2.0 / 3.0; // 后 1/3 区域
    }
    // 判断终点是否在进攻三区
    public boolean isEndInFinalThird() {
        return endX >= fieldLength * 2.0 / 3.0;
    }
    // getters / setters / constructor 省略
}

统计工具类

import java.util.*;
import java.util.stream.Collectors;
public class PassAnalyzer {
    /**
     * 计算进攻三区传球成功率
     * @param events 全部传球事件
     * @param byStart true=按起点判定;false=按终点判定
     */
    public static double finalThirdPassSuccessRate(
            List<PassEvent> events, boolean byStart) {
        List<PassEvent> finalThirdPasses = events.stream()
                .filter(e -> byStart ? e.isStartInFinalThird()
                                     : e.isEndInFinalThird())
                .collect(Collectors.toList());
        if (finalThirdPasses.isEmpty()) return 0.0;
        long successCount = finalThirdPasses.stream()
                .filter(PassEvent::isSuccess)
                .count();
        return (double) successCount / finalThirdPasses.size() * 100;
    }
    /**
     * 按球员统计
     */
    public static Map<String, Double> finalThirdRateByPlayer(
            List<PassEvent> events, boolean byStart) {
        Map<String, List<PassEvent>> group = events.stream()
                .filter(e -> byStart ? e.isStartInFinalThird()
                                     : e.isEndInFinalThird())
                .collect(Collectors.groupingBy(PassEvent::getPlayerId));
        Map<String, Double> result = new LinkedHashMap<>();
        group.forEach((player, list) -> {
            long ok = list.stream().filter(PassEvent::isSuccess).count();
            result.put(player, (double) ok / list.size() * 100);
        });
        return result;
    }
}

测试主程序

public class Main {
    public static void main(String[] args) {
        List<PassEvent> events = List.of(
            new PassEvent("P1",  30,  50, true),
            new PassEvent("P1",  80,  95, true),   // 起点在进攻三区
            new PassEvent("P1",  85,  60, false),  // 起点在进攻三区,失败
            new PassEvent("P2",  70,  90, true),   // 起点在进攻三区
            new PassEvent("P2",  20,  75, true),   // 终点在进攻三区
            new PassEvent("P2",  40,  40, true)
        );
        double rate = PassAnalyzer.finalThirdPassSuccessRate(events, true);
        System.out.printf("进攻三区传球成功率(按起点): %.2f%%%n", rate);
        System.out.println("按球员统计:");
        PassAnalyzer.finalThirdRateByPlayer(events, true)
                .forEach((p, r) -> System.out.printf("  %s: %.2f%%%n", p, r));
    }
}

输出示例:

进攻三区传球成功率(按起点): 66.67%
按球员统计:
  P1: 50.00%
  P2: 100.00%

几个易踩坑点

  1. 坐标系必须统一:有的数据用 0~100 归一化,有的用 0~105 米,判断阈值前先归一化。
  2. 进攻方向:主场球队可能从左往右、客队从右往左攻,要按 possession team 的进攻方向翻转 x 坐标。
  3. 传球类型过滤:角球、界外球、门球是否计入?传球成功率"默认不含定位球,需要 passType 过滤。
  4. 样本量:进攻三区传球次数很少(尤其后卫),低样本量下成功率波动大,建议同时输出 count。
  5. 成功率 vs 成功率%:注意返回的是 6667 还是 67,避免前端展示错位。

如果你能把具体的 Java 案例代码贴出来(类名、方法、字段),我可以直接在你的案例上指出"进攻三区"怎么判定、"成功率"在哪一行算、以及有没有逻辑 bug,并给出改造后的代码。

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

友情链接攻略窝 · 礼包窝 · 配置窝 · 换算窝 · 算法窝 · 查文窝 · 手册窝 · 问答窝 · 全文搜 · 手册库
相关站点礼包窝 · 查文窝