用脚本统计长短传比例分布
下面给你一个完整可用的Python脚本,用于统计长短传比例分布,覆盖常见场景(如足球/篮球传球数据、日志、网络包等),你可以按需替换数据源。

核心思路
- 定义阈值:短传/长传的分界(例如足球常用 25 码或 30 米;可按业务自定)
- 读取数据:CSV / JSON / DataFrame
- 分类统计:短传数、长传数、比例
- 分布分析:按球员/球队/时间段分组,输出比例分布(直方图 + 分位数)
- 可视化 & 导出
完整脚本(以传球数据为例)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# ========== 1. 配置 ==========
SHORT_PASS_THRESHOLD = 25.0 # 短传距离阈值(米/码,按你的单位)
DATA_PATH = "passes.csv" # 列: player, team, distance, timestamp
# ========== 2. 读取数据 ==========
df = pd.read_csv(DATA_PATH)
# 示例列: player, team, distance
# 若无数据可先用模拟数据测试
# df = pd.DataFrame({
# "player": np.random.choice(["A","B","C"], 1000),
# "team": np.random.choice(["T1","T2"], 1000),
# "distance": np.random.gamma(2, 10, 1000)
# })
# ========== 3. 分类 ==========
df["pass_type"] = np.where(df["distance"] <= SHORT_PASS_THRESHOLD, "short", "long")
# ========== 4. 整体比例 ==========
total = len(df)
short_n = (df["pass_type"] == "short").sum()
long_n = (df["pass_type"] == "long").sum()
print(f"总传球: {total}")
print(f"短传: {short_n} ({short_n/total:.2%})")
print(f"长传: {long_n} ({long_n/total:.2%})")
print(f"长短比: {short_n/max(long_n,1):.2f} : 1")
# ========== 5. 按球员分组统计比例 ==========
by_player = (
df.groupby("player")["pass_type"]
.value_counts(normalize=True)
.unstack(fill_value=0)
.rename(columns={"short": "short_ratio", "long": "long_ratio"})
)
by_player["total"] = df.groupby("player").size()
by_player["short_long_ratio"] = by_player["short_ratio"] / by_player["long_ratio"].replace(0, np.nan)
print("\n按球员长短传比例:")
print(by_player.sort_values("short_ratio", ascending=False).round(3))
# ========== 6. 比例分布(分位数) ==========
ratios = by_player["short_ratio"].dropna()
print("\n短传比例分布:")
print(ratios.describe(percentiles=[.1,.25,.5,.75,.9]).round(3))
# ========== 7. 直方图 ==========
plt.figure(figsize=(8,5))
plt.hist(ratios, bins=10, edgecolor="black")
plt.xlabel("Short Pass Ratio")
plt.ylabel("Number of Players")"Distribution of Short Pass Ratio per Player")
plt.tight_layout()
plt.savefig("short_ratio_distribution.png", dpi=150)
# ========== 8. 导出 ==========
by_player.to_csv("short_long_ratio_by_player.csv")
print("\n已导出: short_long_ratio_by_player.csv / short_ratio_distribution.png")
关键设计要点
| 要点 | 说明 |
|---|---|
| 阈值可配置 | SHORT_PASS_THRESHOLD 按业务定;可用中位数/四分位动态划分 |
| 分组维度 | 球员 / 球队 / 时段 / 比赛阶段(可按需 groupby) |
| 比例而非计数 | value_counts(normalize=True) 避免样本量偏倚 |
| 分布而非均值 | 用直方图 + 分位数看偏态,避免均值误导 |
| 零除保护 | max(long_n,1)、replace(0,np.nan) |
进阶:按时间段看比例变化
df["timestamp"] = pd.to_datetime(df["timestamp"])
df["bin"] = df["timestamp"].dt.floor("5min") # 5分钟窗口
trend = (
df.groupby("bin")["pass_type"]
.value_counts(normalize=True)
.unstack(fill_value=0)
)
trend.plot(figsize=(10,4), title="Short/Long Pass Ratio over Time")
plt.ylabel("Ratio")
plt.tight_layout()
plt.savefig("ratio_trend.png", dpi=150)
其他场景的适配
- 网络包:
distance→ 包大小(字节),阈值如 500B 分短/长包 - 文本/消息:
distance→ 字符数 - 销售/订单:
amount按金额阈值分小额/大额
只需替换 distance 列和阈值即可,其余统计逻辑通用。
可选增强
- 动态阈值:
TH = df["distance"].median(),避免主观设定 - 置信区间:用 bootstrap 估计比例 CI
- 卡方检验:比较不同球员/球队比例是否显著差异(
scipy.stats.chi2_contingency) - 异常检测:比例偏离群体均值 2σ 以上的球员标记
需要我针对具体数据类型(足球事件流 / 网络pcap / 聊天日志)给出定制版本吗?