java案例统计回传次数反映保守程度?

wen java案例 4

本文目录导读:

java案例统计回传次数反映保守程度?

  1. 基础版:简单统计回传次数
  2. 进阶版:带时间段的动态分析
  3. 高级版:基于机器学习的预测模型
  4. 实际应用:比赛分析系统
  5. 关键指标说明
  6. 使用建议

在足球数据分析中,“回传次数”确实可以作为衡量球队保守程度(或控球倾向)的重要指标,以下是几个Java案例,从简单到复杂,展示如何统计并反映保守程度。

基础版:简单统计回传次数

import java.util.HashMap;
import java.util.Map;
public class PassAnalysisBasic {
    // 定义传球事件类
    static class PassEvent {
        String team;
        String from;
        String to;
        String passType; // "forward", "back", "side"
        int minute;
        public PassEvent(String team, String from, String to, String passType, int minute) {
            this.team = team;
            this.from = from;
            this.to = to;
            this.passType = passType;
            this.minute = minute;
        }
    }
    public static void main(String[] args) {
        // 模拟比赛数据
        PassEvent[] events = {
            new PassEvent("TeamA", "后卫", "门将", "back", 5),
            new PassEvent("TeamA", "门将", "后卫", "forward", 7),
            new PassEvent("TeamA", "中场", "后卫", "back", 10),
            new PassEvent("TeamA", "前锋", "中场", "back", 15),
            new PassEvent("TeamA", "中场", "前锋", "forward", 20),
            new PassEvent("TeamB", "后卫", "门将", "back", 25),
            new PassEvent("TeamB", "中场", "后卫", "back", 30),
            new PassEvent("TeamB", "门将", "后卫", "forward", 35)
        };
        analyzeConservatism(events);
    }
    public static void analyzeConservatism(PassEvent[] events) {
        Map<String, Integer> backPassCount = new HashMap<>();
        Map<String, Integer> totalPassCount = new HashMap<>();
        for (PassEvent event : events) {
            totalPassCount.merge(event.team, 1, Integer::sum);
            if (event.passType.equals("back")) {
                backPassCount.merge(event.team, 1, Integer::sum);
            }
        }
        System.out.println("=== 保守程度分析 ===");
        for (String team : totalPassCount.keySet()) {
            int backPasses = backPassCount.getOrDefault(team, 0);
            int totalPasses = totalPassCount.get(team);
            double ratio = (double) backPasses / totalPasses * 100;
            System.out.printf("%s: 回传%d次,占总传球%.1f%%%n", 
                team, backPasses, ratio);
            // 判断保守程度
            if (ratio > 50) {
                System.out.println("   → 非常保守");
            } else if (ratio > 30) {
                System.out.println("   → 比较保守");
            } else {
                System.out.println("   → 较为积极");
            }
        }
    }
}

进阶版:带时间段的动态分析

import java.util.*;
import java.util.stream.Collectors;
public class PassingStyleAnalyzer {
    // 传球事件
    static class PassEvent {
        String team;
        String passer;
        String receiver;
        double x1, y1; // 传球位置
        double x2, y2; // 接球位置
        int minute;
        boolean isBackPass() {
            // 如果接球点的x坐标小于传球点(假设进攻方向为+x),则为回传
            return x2 < x1;
        }
        double getPassDistance() {
            return Math.sqrt(Math.pow(x2-x1, 2) + Math.pow(y2-y1, 2));
        }
    }
    // 比赛数据
    static class MatchData {
        List<PassEvent> passes;
        String homeTeam;
        String awayTeam;
        Map<String, TeamStats> analyze() {
            Map<String, TeamStats> stats = new HashMap<>();
            stats.put(homeTeam, new TeamStats(homeTeam));
            stats.put(awayTeam, new TeamStats(awayTeam));
            for (PassEvent pass : passes) {
                TeamStats teamStats = stats.get(pass.team);
                teamStats.totalPasses++;
                if (pass.isBackPass()) {
                    teamStats.backPasses++;
                    teamStats.backPassDistance += pass.getPassDistance();
                    // 按时间段统计
                    int period = getPeriod(pass.minute);
                    teamStats.backPassesByPeriod[period]++;
                }
            }
            calculateMetrics(stats);
            return stats;
        }
        int getPeriod(int minute) {
            if (minute <= 15) return 0;
            if (minute <= 30) return 1;
            if (minute <= 45) return 2;
            if (minute <= 60) return 3;
            if (minute <= 75) return 4;
            return 5;
        }
        void calculateMetrics(Map<String, TeamStats> stats) {
            for (TeamStats team : stats.values()) {
                team.backPassRatio = (double) team.backPasses / team.totalPasses * 100;
                team.avgBackPassDistance = team.backPasses > 0 ? 
                    team.backPassDistance / team.backPasses : 0;
            }
        }
    }
    // 球队统计
    static class TeamStats {
        String teamName;
        int totalPasses = 0;
        int backPasses = 0;
        double backPassDistance = 0;
        double backPassRatio = 0;
        double avgBackPassDistance = 0;
        int[] backPassesByPeriod = new int[6];
        public TeamStats(String name) {
            this.teamName = name;
        }
        // 保守程度评分 (0-100)
        double getConservatismScore() {
            double score = 0;
            // 回传比例权重40%
            score += Math.min(backPassRatio, 100) * 0.4;
            // 回传距离权重30% (短距离回传更保守)
            double distanceScore = Math.max(0, 30 - avgBackPassDistance) * 2;
            score += Math.min(distanceScore, 30);
            // 时间段分布权重30% (上半场回传多更保守)
            double earlyPeriodScore = (backPassesByPeriod[0] + backPassesByPeriod[1]) * 
                                     30.0 / Math.max(1, backPasses);
            score += Math.min(earlyPeriodScore, 30);
            return Math.min(score, 100);
        }
        String getStyle() {
            double score = getConservatismScore();
            if (score >= 70) return "极度保守";
            if (score >= 50) return "保守";
            if (score >= 30) return "平衡";
            if (score >= 15) return "积极";
            return "极具攻击性";
        }
        @Override
        public String toString() {
            return String.format("%s: 回传比例=%.1f%%, 平均回传距离=%.1fm, 保守得分=%.1f, 风格= %s",
                teamName, backPassRatio, avgBackPassDistance, getConservatismScore(), getStyle());
        }
    }
}

高级版:基于机器学习的预测模型

import java.util.*;
import java.util.stream.*;
public class ConservativeStylePredictor {
    // 特征向量
    static class TeamFeatures {
        double backPassRatio;
        double avgBackPassDistance;  
        double possessionRate;
        double passAccuracy;
        int counterAttackCount;
        int totalShots;
        double[] toArray() {
            return new double[] {
                backPassRatio, avgBackPassDistance, possessionRate,
                passAccuracy, counterAttackCount, totalShots
            };
        }
    }
    // 简单的逻辑回归分类器
    static class LRClassifier {
        double[] weights = new double[6];
        double bias = 0;
        double learningRate = 0.01;
        double predict(TeamFeatures features) {
            double[] x = features.toArray();
            double z = bias;
            for (int i = 0; i < x.length; i++) {
                z += weights[i] * x[i];
            }
            return 1.0 / (1.0 + Math.exp(-z)); // sigmoid
        }
        // 训练模型
        void train(List<TeamFeatures> samples, List<Double> labels) {
            for (int epoch = 0; epoch < 1000; epoch++) {
                for (int i = 0; i < samples.size(); i++) {
                    TeamFeatures features = samples.get(i);
                    double prediction = predict(features);
                    double error = labels.get(i) - prediction;
                    // 梯度下降更新
                    double[] x = features.toArray();
                    for (int j = 0; j < weights.length; j++) {
                        weights[j] += learningRate * error * x[j];
                    }
                    bias += learningRate * error;
                }
            }
        }
    }
    public static void main(String[] args) {
        // 示例:训练数据集(历史比赛数据)
        List<TeamFeatures> historyData = new ArrayList<>();
        List<Double> labels = new ArrayList<>();
        // 添加训练样本
        // 保守球队样本
        historyData.add(createFeatures(60, 5, 55, 85, 3, 12));
        labels.add(1.0);
        // 积极球队样本  
        historyData.add(createFeatures(25, 15, 45, 75, 12, 25));
        labels.add(0.0);
        // 训练模型
        LRClassifier model = new LRClassifier();
        model.train(historyData, labels);
        // 预测当前比赛的保守程度
        TeamFeatures currentMatch = createFeatures(40, 8, 50, 80, 6, 18);
        double conservatismProb = model.predict(currentMatch);
        System.out.printf("该球队保守程度概率: %.2f%n", conservatismProb);
        System.out.println(conservatismProb > 0.5 ? 
            "推荐策略: 加强前场逼抢" : "推荐策略: 准备反击战术");
    }
    static TeamFeatures createFeatures(double ratio, double distance, 
                                       double possession, double accuracy,
                                       int counters, int shots) {
        TeamFeatures f = new TeamFeatures();
        f.backPassRatio = ratio;
        f.avgBackPassDistance = distance;
        f.possessionRate = possession;
        f.passAccuracy = accuracy;
        f.counterAttackCount = counters;
        f.totalShots = shots;
        return f;
    }
}

实际应用:比赛分析系统

public class MatchAnalysisSystem {
    public static void main(String[] args) {
        // 创建比赛数据
        MatchData match = new MatchData();
        match.homeTeam = "FC Barcelona";
        match.awayTeam = "Real Madrid";
        // 填充传球数据(示例)
        match.passes = generatePassData();
        // 分析
        Map<String, TeamStats> results = match.analyze();
        // 输出报告
        System.out.println("=== 比赛保守程度分析报告 ===");
        results.values().forEach(System.out::println);
        // 对比分析
        TeamStats barca = results.get("FC Barcelona");
        TeamStats madrid = results.get("Real Madrid");
        compareTeams(barca, madrid);
    }
    static void compareTeams(TeamStats a, TeamStats b) {
        System.out.println("\n=== 双方对比 ===");
        System.out.printf("回传比例: %s %.1f%% vs %s %.1f%%%n", 
            a.teamName, a.backPassRatio, b.teamName, b.backPassRatio);
        System.out.printf("平均回传距离: %.1fm vs %.1fm%n", 
            a.avgBackPassDistance, b.avgBackPassDistance);
        System.out.printf("保守风格: %s vs %s%n",
            a.getStyle(), b.getStyle());
    }
    private static List<PassEvent> generatePassData() {
        // 这里可以接入真实数据源,如API或数据库
        Random rand = new Random();
        List<PassEvent> passes = new ArrayList<>();
        String[] teams = {"FC Barcelona", "Real Madrid"};
        String[] positions = {"门将", "后卫", "中场", "前锋"};
        for (int i = 0; i < 200; i++) {
            PassEvent pass = new PassEvent();
            pass.team = teams[rand.nextInt(2)];
            pass.passer = positions[rand.nextInt(4)];
            pass.receiver = positions[rand.nextInt(4)];
            // 模拟位置,x坐标越大越靠近对方球门
            pass.x1 = rand.nextDouble() * 105;
            pass.x2 = rand.nextDouble() * 105;
            pass.y1 = rand.nextDouble() * 68;
            pass.y2 = rand.nextDouble() * 68;
            pass.minute = rand.nextInt(90) + 1;
            passes.add(pass);
        }
        return passes;
    }
}

关键指标说明

指标 说明 保守程度关联
回传比例 回传次数/总传球次数 比例越高越保守
平均回传距离 每次回传的直线距离 距离越短越保守
时间段分布 上半场vs下半场回传次数 上半场多更保守
回传方向 到中间/边路/底线 中路回传更保守

使用建议

  1. 数据质量:确保传球数据准确,包括方向和位置
  2. 样本量:至少需要整场比赛数据才有意义
  3. 多维度分析:结合控球率、射门数等其他指标
  4. 动态监控:实时更新数据,观察战术变化

这些案例可以从不同角度反映球队的保守程度,你可以根据具体需求选择适合的方案来实现。

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