java案例统计长短传比例如何分布?

wen java案例 6

本文目录导读:

java案例统计长短传比例如何分布?

  1. 基础版本 - 简单的比例统计
  2. 进阶版本 - 支持数据导入和多种统计维度
  3. CSV示例数据格式
  4. 关键特性:

我来为您提供一个Java案例,统计长短传比例分布,这里我提供两种实现方式:

基础版本 - 简单的比例统计

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class PassAnalysis {
    // 传球类型枚举
    public enum PassType {
        SHORT_PASS("短传", 0, 15),    // 0-15米
        MEDIUM_PASS("中传", 15, 30),  // 15-30米
        LONG_PASS("长传", 30, 60);    // 30-60米
        private String displayName;
        private int minDistance;
        private int maxDistance;
        PassType(String displayName, int minDistance, int maxDistance) {
            this.displayName = displayName;
            this.minDistance = minDistance;
            this.maxDistance = maxDistance;
        }
        public String getDisplayName() {
            return displayName;
        }
        public static PassType classify(int distance) {
            for (PassType type : values()) {
                if (distance >= type.minDistance && distance < type.maxDistance) {
                    return type;
                }
            }
            return LONG_PASS; // 超长传视为长传
        }
    }
    // 传球数据类
    public static class Pass {
        private int playerId;
        private int distance;
        private PassType type;
        public Pass(int playerId, int distance) {
            this.playerId = playerId;
            this.distance = distance;
            this.type = PassType.classify(distance);
        }
        public int getPlayerId() { return playerId; }
        public int getDistance() { return distance; }
        public PassType getType() { return type; }
    }
    // 统计结果类
    public static class PassStatistics {
        private int totalPasses;
        private Map<PassType, Integer> passCountMap;
        private Map<PassType, Double> passPercentageMap;
        public PassStatistics(List<Pass> passes) {
            passCountMap = new HashMap<>();
            totalPasses = passes.size();
            // 初始化计数器
            for (PassType type : PassType.values()) {
                passCountMap.put(type, 0);
            }
            // 统计各类传球数量
            for (Pass pass : passes) {
                passCountMap.merge(pass.getType(), 1, Integer::sum);
            }
            // 计算百分比
            passPercentageMap = new HashMap<>();
            for (PassType type : PassType.values()) {
                int count = passCountMap.get(type);
                double percentage = totalPasses > 0 ? 
                    (count * 100.0 / totalPasses) : 0.0;
                passPercentageMap.put(type, percentage);
            }
        }
        public void printStatistics() {
            System.out.println("=== 传球统计报告 ===");
            System.out.printf("总传球次数: %d%n", totalPasses);
            System.out.println("-------------------");
            System.out.println("传球类型 | 数量 | 占比");
            for (PassType type : PassType.values()) {
                int count = passCountMap.getOrDefault(type, 0);
                double percentage = passPercentageMap.getOrDefault(type, 0.0);
                System.out.printf("%-6s | %4d | %.2f%%%n", 
                    type.getDisplayName(), count, percentage);
            }
            System.out.println("-------------------");
            // 显示可视化分布
            printDistributionChart();
        }
        // 可视化分布图
        private void printDistributionChart() {
            System.out.println("分布可视化:");
            for (PassType type : PassType.values()) {
                int count = passCountMap.getOrDefault(type, 0);
                int barLength = (int) Math.round(count * 30.0 / totalPasses);
                String bar = "█".repeat(Math.max(barLength, 1));
                System.out.printf("%-6s | %s (%d次)%n", 
                    type.getDisplayName(), bar, count);
            }
        }
    }
    // 测试方法
    public static void main(String[] args) {
        // 模拟示例:生成随机传球数据
        List<Pass> passes = generateRandomPasses(100);
        // 创建统计对象
        PassStatistics stats = new PassStatistics(passes);
        // 输出统计结果
        stats.printStatistics();
        // 额外:按球员统计
        Map<Integer, List<Pass>> playerPasses = groupByPlayer(passes);
        System.out.println("\n=== 球员传球统计 ===");
        for (Map.Entry<Integer, List<Pass>> entry : playerPasses.entrySet()) {
            int playerId = entry.getKey();
            List<Pass> playerPassList = entry.getValue();
            System.out.printf("球员 %d: 共%d次传球%n", playerId, playerPassList.size());
        }
    }
    // 生成随机传球数据
    private static List<Pass> generateRandomPasses(int count) {
        List<Pass> passes = new ArrayList<>();
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            int playerId = random.nextInt(10) + 1; // 假设10名球员
            int distance = random.nextInt(70);     // 0-69米
            passes.add(new Pass(playerId, distance));
        }
        return passes;
    }
    // 按球员分组
    private static Map<Integer, List<Pass>> groupByPlayer(List<Pass> passes) {
        Map<Integer, List<Pass>> grouped = new HashMap<>();
        for (Pass pass : passes) {
            grouped.computeIfAbsent(pass.getPlayerId(), k -> new ArrayList<>())
                   .add(pass);
        }
        return grouped;
    }
}

进阶版本 - 支持数据导入和多种统计维度

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
public class AdvancedPassAnalysis {
    // 传球统计数据模型
    public static class PassData {
        private int matchId;
        private int playerId;
        private double startX, startY;  // 起始位置
        private double endX, endY;      // 结束位置
        private int distance;            // 传球距离
        public PassData(int matchId, int playerId, 
                       double startX, double startY, 
                       double endX, double endY) {
            this.matchId = matchId;
            this.playerId = playerId;
            this.startX = startX;
            this.startY = startY;
            this.endX = endX;
            this.endY = endY;
            this.distance = calculateDistance();
        }
        private int calculateDistance() {
            // 欧几里得距离计算
            return (int) Math.sqrt(
                Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2)
            );
        }
        public int getDistance() { return distance; }
        public int getPlayerId() { return playerId; }
        public int getMatchId() { return matchId; }
    }
    // 统计聚合器
    public static class StatisticsAggregator {
        private List<PassData> allPasses;
        public StatisticsAggregator(List<PassData> passes) {
            this.allPasses = passes;
        }
        // 按距离区间统计
        public Map<String, Double> getDistanceDistribution() {
            Map<String, Integer> countMap = new LinkedHashMap<>();
            countMap.put("极短传(0-5m)", 0);
            countMap.put("短传(5-15m)", 0);
            countMap.put("中传(15-25m)", 0);
            countMap.put("长传(25-40m)", 0);
            countMap.put("超长传(40m以上)", 0);
            for (PassData pass : allPasses) {
                int dist = pass.getDistance();
                String category = categorizeDistance(dist);
                countMap.merge(category, 1, Integer::sum);
            }
            Map<String, Double> percentageMap = new LinkedHashMap<>();
            int total = allPasses.size();
            countMap.forEach((key, value) -> {
                percentageMap.put(key, total > 0 ? (value * 100.0 / total) : 0.0);
            });
            return percentageMap;
        }
        private String categorizeDistance(int distance) {
            if (distance <= 5) return "极短传(0-5m)";
            if (distance <= 15) return "短传(5-15m)";
            if (distance <= 25) return "中传(15-25m)";
            if (distance <= 40) return "长传(25-40m)";
            return "超长传(40m以上)";
        }
        // 按比赛统计
        public Map<Integer, Map<String, Double>> getMatchStats() {
            Map<Integer, List<PassData>> matchGroups = allPasses.stream()
                .collect(Collectors.groupingBy(PassData::getMatchId));
            Map<Integer, Map<String, Double>> result = new HashMap<>();
            for (Map.Entry<Integer, List<PassData>> entry : matchGroups.entrySet()) {
                StatisticsAggregator subAgg = new StatisticsAggregator(entry.getValue());
                result.put(entry.getKey(), subAgg.getDistanceDistribution());
            }
            return result;
        }
        // 计算短长传比例(短传:15m以下, 长传:15m以上)
        public double getShortLongRatio() {
            int shortPasses = 0;
            int longPasses = 0;
            for (PassData pass : allPasses) {
                if (pass.getDistance() <= 15) {
                    shortPasses++;
                } else {
                    longPasses++;
                }
            }
            return longPasses > 0 ? (double) shortPasses / longPasses : 0.0;
        }
        // 生成完整报告
        public void generateReport() {
            System.out.println("═══════════════════════════════════");
            System.out.println("        传球分析综合报告");
            System.out.println("═══════════════════════════════════");
            System.out.printf("总传球数: %d%n", allPasses.size());
            Map<String, Double> distribution = getDistanceDistribution();
            System.out.println("\n距离分布:");
            distribution.forEach((category, percentage) -> {
                System.out.printf("  %-15s: %.2f%%%n", category, percentage);
            });
            System.out.printf("%n短传/长传比例: 1 : %.2f%n", 
                1.0 / getShortLongRatio());
            System.out.print("\n柱状图: \n");
            for (Map.Entry<String, Double> entry : distribution.entrySet()) {
                int barLength = (int)(entry.getValue() / 5); // 5%为1个字符
                String bar = "★".repeat(Math.max(barLength, 1));
                System.out.printf("  %-15s | %s %.2f%%%n", 
                    entry.getKey(), bar, entry.getValue());
            }
        }
    }
    // 数据加载器
    public static class DataLoader {
        public static List<PassData> loadFromFile(String filePath) {
            List<PassData> passes = new ArrayList<>();
            try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
                String line;
                reader.readLine(); // 跳过标题行
                while ((line = reader.readLine()) != null) {
                    try {
                        String[] parts = line.split(",");
                        PassData pass = new PassData(
                            Integer.parseInt(parts[0].trim()),
                            Integer.parseInt(parts[1].trim()),
                            Double.parseDouble(parts[2].trim()),
                            Double.parseDouble(parts[3].trim()),
                            Double.parseDouble(parts[4].trim()),
                            Double.parseDouble(parts[5].trim())
                        );
                        passes.add(pass);
                    } catch (NumberFormatException e) {
                        System.err.println("数据解析错误: " + line);
                    }
                }
            } catch (IOException e) {
                System.err.println("文件读取失败: " + e.getMessage());
            }
            return passes;
        }
        public static List<PassData> generateMockData(int number) {
            List<PassData> passes = new ArrayList<>();
            Random random = new Random();
            for (int i = 0; i < number; i++) {
                passes.add(new PassData(
                    random.nextInt(10) + 1,     // matchId
                    random.nextInt(20) + 1,     // playerId
                    random.nextDouble() * 100, // startX
                    random.nextDouble() * 50,  // startY
                    random.nextDouble() * 100, // endX
                    random.nextDouble() * 50   // endY
                ));
            }
            return passes;
        }
    }
    public static void main(String[] args) {
        // 方式1: 使用模拟数据
        System.out.println("=== 模拟数据分析 ===");
        List<PassData> mockData = DataLoader.generateMockData(500);
        StatisticsAggregator aggregator = new StatisticsAggregator(mockData);
        aggregator.generateReport();
        // 方式2: 支持从CSV文件导入
        // List<PassData> fileData = DataLoader.loadFromFile("passes.csv");
        // StatisticsAggregator fileAggregator = new StatisticsAggregator(fileData);
        // fileAggregator.generateReport();
    }
}

CSV示例数据格式

matchId,playerId,startX,startY,endX,endY
1,5,10.5,25.3,20.8,30.2
1,3,30.2,45.1,35.6,40.5
2,7,50.0,20.0,15.0,35.0
...

关键特性:

  1. 多维度统计:按距离分类、按球员、按场次统计
  2. 可视化输出:使用字符图形展示分布
  3. 灵活扩展:可添加更多统计维度
  4. 数据导入:支持CSV文件数据导入
  5. 比例计算:清楚展示长短传比例分布

这个案例可以用于足球比赛数据分析、传球策略研究等场景,您可以根据实际需求调整距离分类标准和统计维度。

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