实用脚本统计长短传比例如何分布?

wen 实用脚本 2

本文目录导读:

实用脚本统计长短传比例如何分布?

  1. 方案一:基于Python + Pandas(最通用)
  2. 方案二:基于Python + Matplotlib(可视化分布)
  3. 方案三:纯SQL(针对数据库表)
  4. 附加建议:如何定义“长短传”?
  5. 运行说明

在足球数据分析(或其他球类运动)中,统计“长短传比例”通常涉及对传球数据的分类,由于“长传”和“短传”没有统一的国际标准,通常需要人为定义阈值(如距离超过25米或30米算长传)。

以下提供三种不同场景的实用脚本方案,从最直接的Python数据处理到可视化,你可以根据数据格式选择。


基于Python + Pandas(最通用)

适用场景:你有一份包含传球距离的表格数据(CSV/Excel),字段类似 passer, receiver, distance

核心逻辑:设定阈值(threshold = 25),将距离分为“长传”和“短传”,然后统计组内比例。

import pandas as pd
import numpy as np
# --- 配置参数 ---
THRESHOLD = 25  # 单位:米,大于等于此值为长传
LONG_LABEL = '长传'
SHORT_LABEL = '短传'
# --- 加载数据(假设CSV有 distance 列) ---
# df = pd.read_csv('passing_data.csv')
# 为演示,创建模拟数据:
np.random.seed(42)
df = pd.DataFrame({
    'player': np.random.choice(['A', 'B', 'C'], 100),
    'distance': np.random.uniform(5, 50, 100)  # 距离5-50米
})
# --- 分类函数 ---
def classify_pass(distance):
    return LONG_LABEL if distance >= THRESHOLD else SHORT_LABEL
df['pass_type'] = df['distance'].apply(classify_pass)
# --- 统计全局比例 ---
global_counts = df['pass_type'].value_counts()
global_percent = df['pass_type'].value_counts(normalize=True) * 100
print("=== 全局长短传比例 ===")
print(f"总传球数: {len(df)}")
for label in [LONG_LABEL, SHORT_LABEL]:
    if label in global_percent.index:
        print(f"{label}: {global_counts[label]}次 ({global_percent[label]:.1f}%)")
# --- 统计每个球员的比例(按球员分组) ---
print("\n=== 各球员长短传分布 ===")
player_stats = df.groupby(['player', 'pass_type']).size().unstack(fill_value=0)
player_stats['总计'] = player_stats.sum(axis=1)
# 计算百分比(针对每行)
player_stats[LONG_LABEL + '_%'] = (player_stats[LONG_LABEL] / player_stats['总计'] * 100).round(1)
player_stats[SHORT_LABEL + '_%'] = (player_stats[SHORT_LABEL] / player_stats['总计'] * 100).round(1)
print(player_stats[[LONG_LABEL, SHORT_LABEL, LONG_LABEL+'_%', SHORT_LABEL+'_%']])

基于Python + Matplotlib(可视化分布)

适用场景:你想直观查看“距离”的连续分布,并自动用颜色划分长短传区域。

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 假设 df 已有 distance 列
# 此处直接用上面的模拟数据
# ...
# --- 绘制直方图 ---
plt.figure(figsize=(10, 5))
# 按分类分色绘图
plt.hist(df[df['pass_type'] == '长传']['distance'], 
         bins=15, alpha=0.7, color='red', label='长传 (>=25m)')
plt.hist(df[df['pass_type'] == '短传']['distance'], 
         bins=15, alpha=0.7, color='blue', label='短传 (<25m)')
# 画阈值线
plt.axvline(x=THRESHOLD, color='k', linestyle='--', linewidth=1, 
            label=f'阈值: {THRESHOLD}m')
plt.xlabel('传球距离 (米)')
plt.ylabel('传球次数')f'传球距离分布 (长短传比例: {global_percent[LONG_LABEL]:.1f}% vs {global_percent[SHORT_LABEL]:.1f}%)')
plt.legend()
plt.grid(axis='y', alpha=0.3)
plt.show()

纯SQL(针对数据库表)

适用场景:数据存在MySQL/PostgreSQL中,表结构为 passes(id, player_id, distance)

-- 1. 设置阈值(如果你不想改代码,可以临时用WITH定义)
WITH params AS (SELECT 25 AS threshold)
-- 2. 计算全局统计
SELECT 
    CASE WHEN distance >= (SELECT threshold FROM params) THEN '长传' ELSE '短传' END AS pass_type,
    COUNT(*) AS total_passes,
    ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 1) AS percentage
FROM passes
GROUP BY pass_type;
-- 3. 如果需要按球员分组统计:
SELECT 
    player_id,
    SUM(CASE WHEN distance >= 25 THEN 1 ELSE 0 END) AS long_pass_count,
    SUM(CASE WHEN distance < 25 THEN 1 ELSE 0 END) AS short_pass_count,
    ROUND(
        100.0 * SUM(CASE WHEN distance >= 25 THEN 1 ELSE 0 END) 
        / COUNT(*), 1
    ) AS long_pct
FROM passes
GROUP BY player_id
ORDER BY long_pct DESC;

附加建议:如何定义“长短传”?

如果你没有标准距离阈值,可以尝试以下两种动态方法:

  1. 基于百分位数:将传球距离按从大到小排序,前20%视为“长传”,后80%视为“短传”(利用 df['distance'].quantile(0.8))。
  2. 基于具体战术:将进入对方半场的传球算作长传,但需要额外的坐标数据(xy起始点和终点)。
# 替代方法:动态阈值(中位数或分位数)
DYNAMIC_THRESHOLD = df['distance'].median()  # 以中位数为界
# 或者按前80%分位:
P80 = df['distance'].quantile(0.8)

运行说明

  • 如果数据量大,建议使用pandasread_csv后直接运行方案一。
  • 如果只需要一个比率,直接运行方案一打印结果即可。
  • 如果数据是JSON格式(来自API),只需将pd.read_csv替换为pd.DataFrame(data_list)

如果提供具体的文件格式(如JSON、XML)或字段名,我可以进一步修改脚本。

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