进攻三区传球成功率(Java实现)
“进攻三区传球成功率”是足球数据分析中的常见指标,通常指在前场进攻三区(Final Third)内成功传球次数 ÷ 该区域内总传球次数。

下面给你一个完整的 Java 案例实现。
需求说明
- 足球场按纵向划分为三个区域:防守三区、中场三区、进攻三区
- 只需要统计发生在进攻三区内的传球
- 传球分为成功/失败(
isSuccess) - 计算:
成功率 = 成功传球数 / 总传球数 × 100%
实体类设计
import java.util.List;
/**
* 传球记录
*/
public class PassRecord {
private String playerName; // 球员
private int startX; // 起点X坐标(0~100, 0=本方球门, 100=对方球门)
private int endX; // 终点X坐标
private boolean success; // 是否成功
public PassRecord(String playerName, int startX, int endX, boolean success) {
this.playerName = playerName;
this.startX = startX;
this.endX = endX;
this.success = success;
}
public String getPlayerName() { return playerName; }
public int getStartX() { return startX; }
public int getEndX() { return endX; }
public boolean isSuccess() { return success; }
/** 起点是否在进攻三区 (X > 66) */
public boolean isInFinalThird() {
return startX > 66;
}
}
说明:把球场纵向 0~100,进攻三区通常为 X > 66(即最后 1/3 区域),也可根据你们数据标准改成
> 70等。
统计服务类
import java.util.List;
public class PassStatsService {
/**
* 计算进攻三区传球成功率
* @param records 所有传球记录
* @return 成功率(0~100 的百分比),若没有传球则返回 0
*/
public double finalThirdPassSuccessRate(List<PassRecord> records) {
if (records == null || records.isEmpty()) {
return 0.0;
}
int total = 0;
int success = 0;
for (PassRecord r : records) {
if (r.isInFinalThird()) { // 只统计起点在进攻三区的传球
total++;
if (r.isSuccess()) {
success++;
}
}
}
if (total == 0) {
return 0.0;
}
return success * 100.0 / total;
}
}
如果你想保留两位小数,可以:
double rate = Math.round(success * 10000.0 / total) / 100.0;
测试主类
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<PassRecord> records = Arrays.asList(
// 进攻三区 (startX > 66)
new PassRecord("梅西", 80, 90, true),
new PassRecord("梅西", 75, 85, true),
new PassRecord("内马尔", 70, 78, false),
new PassRecord("姆巴佩", 68, 80, true),
new PassRecord("姆巴佩", 90, 95, false),
// 中场 / 后场 (不计入)
new PassRecord("内马尔", 50, 60, true),
new PassRecord("梅西", 30, 40, false),
new PassRecord("维拉蒂", 65, 70, true)
);
PassStatsService service = new PassStatsService();
double rate = service.finalThirdPassSuccessRate(records);
System.out.printf("进攻三区传球成功率: %.2f%%%n", rate);
}
}
运行结果
进攻三区传球成功率: 60.00%
计算过程:进攻三区共 5 次传球,成功 3 次 → 3 / 5 = 60%。
进阶扩展
| 场景 | 做法 |
|---|---|
| 按球员统计 | 用 Map<String, int[]> 按 playerName 分组,分别累加 total/success |
| 按球队统计 | 在 PassRecord 中加 teamId,分组统计 |
| 区分传球距离 | 加入坐标 (startY,endY),计算距离后分类统计 |
| 再细分三区 | 把进攻三区再拆为左中右三块,用 startY 判断 |
| 数据来源 | 可以从 CSV / JSON / 数据库读取,替换 List<PassRecord> 转成 Stream 即可 |
按球员统计示例片段:
Map<String, int[]> map = new HashMap<>();
for (PassRecord r : records) {
if (!r.isInFinalThird()) continue;
int[] arr = map.computeIfAbsent(r.getPlayerName(), k -> new int[2]);
arr[0]++; // total
if (r.isSuccess()) arr[1]++; // success
}
map.forEach((name, arr) ->
System.out.printf("%s: %.2f%% (%d/%d)%n",
name, arr[1] * 100.0 / arr[0], arr[1], arr[0]));
核心公式总结
$$ \text{进攻三区传球成功率} = \frac{\text{进攻三区内成功传球数}}{\text{进攻三区内总传球数}} \times 100\% $$
关键判定:以传球起点坐标是否落在进攻三区为准(X > 66,也可根据数据源采用 70 分位等标准)。
如果你有具体的数据字段(Opta/StatsBomb 的事件格式、或 CSV 表头),我可以帮你把解析和统计代码写得更贴合实际数据。