本文目录导读:

我来为您提供一个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 ...
关键特性:
- 多维度统计:按距离分类、按球员、按场次统计
- 可视化输出:使用字符图形展示分布
- 灵活扩展:可添加更多统计维度
- 数据导入:支持CSV文件数据导入
- 比例计算:清楚展示长短传比例分布
这个案例可以用于足球比赛数据分析、传球策略研究等场景,您可以根据实际需求调整距离分类标准和统计维度。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播