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

wen python案例 2

Python 案例:统计长短传比例及分布

下面给你一个完整的案例,统计"短传"和"长传"的比例,并分析其分布。

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

场景说明

以足球传球数据为例:

  • 短传:传球距离 < 25 米
  • 长传:传球距离 ≥ 25 米

完整代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
sns.set_style("whitegrid")
# ============ 1. 构造模拟数据 ============
np.random.seed(42)
n = 500
# 模拟传球距离(米),短传多、长传少
distances = np.concatenate([
    np.random.normal(loc=12, scale=5, size=int(n*0.7)),   # 短传
    np.random.normal(loc=35, scale=8, size=int(n*0.3))    # 长传
])
distances = np.clip(distances, 1, 70)  # 限制范围
df = pd.DataFrame({
    'player': np.random.choice(['A','B','C','D'], size=len(distances)),
    'distance': distances
})
# ============ 2. 打标签:短传 / 长传 ============
THRESHOLD = 25
df['pass_type'] = np.where(df['distance'] < THRESHOLD, '短传', '长传')
# ============ 3. 总体比例统计 ============
total_counts = df['pass_type'].value_counts()
total_ratio = df['pass_type'].value_counts(normalize=True) * 100
print("=== 总体比例 ===")
print(pd.DataFrame({'次数': total_counts, '占比(%)': total_ratio.round(2)}))
# ============ 4. 按球员分组的比例 ============
group_stat = df.groupby(['player','pass_type']).size().unstack(fill_value=0)
group_ratio = group_stat.div(group_stat.sum(axis=1), axis=0) * 100
print("\n=== 各球员长短传比例(%) ===")
print(group_ratio.round(2))
# ============ 5. 可视化 ============
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# (1) 饼图:总体比例
axes[0,0].pie(total_counts, labels=total_counts.index,
              autopct='%1.1f%%', startangle=90,
              colors=['#4C9BE8','#F2994A'])
axes[0,0].set_title('整体长短传比例')
# (2) 直方图:距离分布(阈值线)
axes[0,1].hist(df['distance'], bins=30, color='#4C9BE8', edgecolor='white')
axes[0,1].axvline(THRESHOLD, color='red', linestyle='--', label=f'阈值={THRESHOLD}m')
axes[0,1].set_title('传球距离分布')
axes[0,1].set_xlabel('距离(米)')
axes[0,1].set_ylabel('次数')
axes[0,1].legend()
# (3) 堆叠柱状图:各球员长短传比例
group_ratio.plot(kind='bar', stacked=True, ax=axes[1,0],
                 color=['#4C9BE8','#F2994A'])
axes[1,0].set_title('各球员长短传比例')
axes[1,0].set_ylabel('比例(%)')
axes[1,0].set_xlabel('球员')
axes[1,0].legend(title='类型')
axes[1,0].tick_params(axis='x', rotation=0)
# (4) 箱线图:各球员传球距离分布
sns.boxplot(data=df, x='player', y='distance', ax=axes[1,1],
            palette='Set2')
axes[1,1].axhline(THRESHOLD, color='red', linestyle='--')
axes[1,1].set_title('各球员传球距离箱线图')
plt.tight_layout()
plt.show()

输出示例

=== 总体比例 ===
        次数   占比(%)
短传      347   69.40
长传      153   30.60
=== 各球员长短传比例(%) ===
pass_type    短传    长传
player                  
A           68.33  31.67
B           70.54  29.46
C           69.84  30.16
D           68.55  31.45

关键点解析

步骤 说明
阈值判定 np.where(distance < 25) 一句话打标签
比例计算 value_counts(normalize=True) 直接得比例
分组分析 groupby().size().unstack() + 归一化
分布可视化 饼图看比例、直方图看距离分布、箱线图看个体差异

进阶:如果你想按"时间/比赛"维度看比例分布

# 假设有 match_id 字段,统计每场的长短传比例,再看这些比例的分布
match_ratio = (df.groupby(['match_id','pass_type']).size()
                 .unstack(fill_value=0)
                 .pipe(lambda x: x.div(x.sum(axis=1), axis=0))) * 100
# 长传比例在比赛间的分布
plt.figure(figsize=(8,4))
sns.histplot(match_ratio['长传'], bins=20, kde=True, color='#F2994A')'各场比赛长传比例的分布')
plt.xlabel('长传占比(%)')
plt.show()

这样你不仅能看整体比例,还能看分布情况(是否所有比赛都偏短传、是否存在极端场次等)。

如果你有真实数据(Opta、StatsBomb、或自己采集的传球记录),把 distance 换成真实传球距离字段即可直接运行,需要我根据你的数据结构再改一版吗?

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

友情链接攻略窝 · 礼包窝 · 配置窝 · 换算窝 · 算法窝 · 查文窝 · 手册窝 · 问答窝 · 全文搜 · 手册库
相关站点礼包窝 · 查文窝