本文目录导读:

我来为您设计一个综合Python案例,分析不同运动状态下的高速跑动距离对比,这个案例将包含数据生成、处理、可视化和分析。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
import warnings
warnings.filterwarnings('ignore')
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
class SprintAnalyzer:
"""高速跑动分析器"""
def __init__(self, player_name="运动员", sampling_rate=10):
"""
初始化分析器
player_name: 运动员名称
sampling_rate: 采样频率(Hz),GPS每0.1秒记录一次
"""
self.player_name = player_name
self.sampling_rate = sampling_rate
self.df = None
self.speed_thresholds = {
'低速走': (0, 2.0), # 0-2 m/s
'慢跑': (2.0, 4.0), # 2-4 m/s
'中速跑': (4.0, 6.0), # 4-6 m/s
'高速跑': (6.0, 8.0), # 6-8 m/s
'冲刺': (8.0, 12.0) # >8 m/s
}
self.high_speed_threshold = 6.0 # 高速跑阈值 m/s
def generate_training_data(self, sessions=3, minutes=30):
"""生成模拟训练数据"""
all_data = []
for session in range(sessions):
# 每节训练时长
duration_seconds = minutes * 60
n_samples = duration_seconds * self.sampling_rate
# 生成时间序列
start_time = datetime.now() - timedelta(days=sessions - session - 1)
timestamps = [start_time + timedelta(seconds=i/self.sampling_rate)
for i in range(n_samples)]
# 模拟变速跑动模式
# 使用正弦函数组合+随机噪声模拟真实跑动
t = np.linspace(0, 4*np.pi, n_samples)
# 基础速度模式(包括加速、减速、冲刺阶段)
base_speed = 3.5 + \
1.5*np.sin(t) + \
0.8*np.sin(2*t + 0.5) + \
2.0*np.exp(-((t-2*np.pi)**2)/(2*0.5**2)) # 冲刺峰值
# 添加随机噪声
noise = np.random.normal(0, 0.3, n_samples)
speed = np.clip(base_speed + noise, 0, 11)
# 生成位置数据(通过速度积分)
position_x = np.cumsum(speed) / self.sampling_rate * np.cos(np.linspace(0, 5, n_samples))
position_y = np.cumsum(speed) / self.sampling_rate * np.sin(np.linspace(0, 5, n_samples))
# 创建DataFrame
session_data = pd.DataFrame({
'timestamp': timestamps,
'speed_mps': speed,
'position_x': position_x,
'position_y': position_y,
'session': f'训练{session+1}'
})
all_data.append(session_data)
self.df = pd.concat(all_data, ignore_index=True)
print(f"✅ 数据生成完成!共{len(self.df)}条记录,"
f"{len(all_data)}节训练课")
return self.df
def classify_speed(self):
"""速度分类"""
if self.df is None:
raise ValueError("请先加载或生成数据")
def categorize(speed):
for category, (low, high) in self.speed_thresholds.items():
if low <= speed < high:
return category
return '冲刺'
self.df['speed_category'] = self.df['speed_mps'].apply(categorize)
self.df['is_high_speed'] = self.df['speed_mps'] >= self.high_speed_threshold
return self.df
def calculate_distance(self):
"""计算各速度段的距离"""
if 'speed_category' not in self.df.columns:
self.df = self.classify_speed()
# 计算每段的距离
self.df['distance'] = self.df['speed_mps'] / self.sampling_rate
# 按训练课和速度分类统计
summary = self.df.groupby(['session', 'speed_category'])['distance'].sum().reset_index()
# 计算各训练课的总距离
total_distance = self.df.groupby('session')['distance'].sum()
# 高速跑距离统计
high_speed_summary = self.df[self.df['is_high_speed']].groupby('session')['distance'].sum()
print("\n📊 === 距离统计 ===")
for session in self.df['session'].unique():
print(f"\n{session}:")
session_data = summary[summary['session'] == session]
for _, row in session_data.iterrows():
print(f" {row['speed_category']}: {row['distance']:.1f}米")
print(f" 总距离: {total_distance[session]:.1f}米")
print(f" 高速跑距离: {high_speed_summary.get(session, 0):.1f}米")
return summary
def plot_speed_profile(self):
"""绘制速度曲线"""
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 1. 速度时间曲线
ax1 = axes[0, 0]
for session in self.df['session'].unique():
session_data = self.df[self.df['session'] == session]
sample_indices = np.arange(0, len(session_data), 100) # 每隔10秒采样一次
ax1.plot(sample_indices/self.sampling_rate/60,
session_data['speed_mps'].iloc[sample_indices],
label=session, alpha=0.7)
ax1.axhline(y=self.high_speed_threshold, color='red', linestyle='--',
label=f'高速阈值({self.high_speed_threshold}m/s)')
ax1.set_xlabel('时间(分钟)')
ax1.set_ylabel('速度(m/s)')
ax1.set_title(f'{self.player_name} - 跑动速度曲线')
ax1.legend()
ax1.grid(True, alpha=0.3)
# 2. 速度分布箱线图
ax2 = axes[0, 1]
sns.boxplot(data=self.df, x='session', y='speed_mps', ax=ax2)
ax2.axhline(y=self.high_speed_threshold, color='red', linestyle='--')
ax2.set_ylabel('速度(m/s)')
ax2.set_title('各训练课速度分布')
ax2.grid(True, alpha=0.3)
# 3. 高速跑距离对比
ax3 = axes[1, 0]
high_speed_dist = self.df[self.df['is_high_speed']].groupby('session')['distance'].sum()
total_dist = self.df.groupby('session')['distance'].sum()
percentage = (high_speed_dist / total_dist * 100)
bars = ax3.bar(high_speed_dist.index, high_speed_dist.values, color='coral', alpha=0.8)
# 添加标签
for bar, dist, pct in zip(bars, high_speed_dist.values, percentage.values):
ax3.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 5,
f'{dist:.0f}m\n({pct:.1f}%)', ha='center', va='bottom')
ax3.set_ylabel('高速跑距离(米)')
ax3.set_title('各训练课高速跑距离对比')
ax3.grid(True, alpha=0.3, axis='y')
# 4. 速度分类频率图
ax4 = axes[1, 1]
time_in_category = self.df.groupby(['session', 'speed_category']).size().unstack() / self.sampling_rate / 60
time_in_category.plot(kind='bar', stacked=True, ax=ax4, colormap='viridis')
ax4.set_ylabel('时间(分钟)')
ax4.set_title('速度区间时间分布')
ax4.legend(title='速度等级')
ax4.set_xticklabels(ax4.get_xticklabels(), rotation=0)
ax4.grid(True, alpha=0.3, axis='y')
plt.tight_layout()
plt.show()
def calculate_high_speed_metrics(self):
"""计算高速跑关键指标"""
if self.df is None:
raise ValueError("请先加载或生成数据")
# 识别冲刺(连续高速跑动)
high_speed_mask = self.df['is_high_speed'].values
sprint_count = 0
sprints = []
sprint_start = None
for i, is_high in enumerate(high_speed_mask):
if is_high and sprint_start is None:
sprint_start = i
elif not is_high and sprint_start is not None:
sprint_count += 1
duration_seconds = (i - sprint_start) / self.sampling_rate
distance = self.df['distance'][sprint_start:i].sum()
avg_speed = self.df['speed_mps'][sprint_start:i].mean()
max_speed = self.df['speed_mps'][sprint_start:i].max()
sprints.append({
'sprint_id': sprint_count,
'duration_seconds': duration_seconds,
'distance': distance,
'avg_speed': avg_speed,
'max_speed': max_speed,
'session': self.df['session'][sprint_start]
})
sprint_start = None
self.sprint_stats = pd.DataFrame(sprints)
print("\n🏃 === 冲刺统计 ===")
if len(self.sprint_stats) > 0:
print(f"冲刺次数: {len(self.sprint_stats)}")
print(f"平均冲刺速度: {self.sprint_stats['avg_speed'].mean():.2f} m/s")
print(f"最大冲刺速度: {self.sprint_stats['max_speed'].max():.2f} m/s")
print(f"平均冲刺时长: {self.sprint_stats['duration_seconds'].mean():.2f}秒")
print(f"平均冲刺距离: {self.sprint_stats['distance'].mean():.2f}米")
print(f"最远冲刺: {self.sprint_stats['distance'].max():.2f}米")
# 按训练课统计
print("\n各训练课冲刺统计:")
session_sprint = self.sprint_stats.groupby('session').agg({
'sprint_id': 'count',
'distance': ['sum', 'mean', 'max'],
'max_speed': 'max',
'duration_seconds': 'sum'
}).round(2)
print(session_sprint)
else:
print("未检测到冲刺")
return self.sprint_stats
def generate_report(self):
"""生成分析报告"""
if self.df is None:
raise ValueError("请先加载或生成数据")
# 计算总体指标
total_distance = self.df['distance'].sum()
avg_speed = self.df['speed_mps'].mean()
max_speed = self.df['speed_mps'].max()
high_speed_distance = self.df[self.df['is_high_speed']]['distance'].sum()
high_speed_percentage = (high_speed_distance / total_distance * 100)
# 创建报告文本
report = f"""
╔══════════════════════════════════════════╗
║ {self.player_name} - 高速跑动分析报告 ║
╚══════════════════════════════════════════╝
📅 数据概况
─────────────────────────────────
• 训练时长: {(len(self.df) / self.sampling_rate / 60):.1f} 分钟
• 总跑动距离: {total_distance:.1f} 米
• 平均速度: {avg_speed:.2f} m/s
• 最大速度: {max_speed:.2f} m/s
🏃 高速跑动指标
─────────────────────────────────
• 高速跑阈值: ≥ {self.high_speed_threshold} m/s
• 高速跑距离: {high_speed_distance:.1f} 米
• 高速跑占比: {high_speed_percentage:.1f}%
📊 冲刺表现
─────────────────────────────────"""
if hasattr(self, 'sprint_stats') and len(self.sprint_stats) > 0:
report += f"""
• 冲刺次数: {len(self.sprint_stats)}
• 总冲刺距离: {self.sprint_stats['distance'].sum():.1f} 米
• 冲刺平均速度: {self.sprint_stats['avg_speed'].mean():.2f} m/s"""
# 各速度区间占比
report += "\n\n💨 速度区间分析"
speed_dist = self.df.groupby('speed_category')['distance'].sum()
total = speed_dist.sum()
report += "\n─────────────────────────────────"
for category, distance in speed_dist.items():
percentage = (distance / total * 100)
bar_length = int(percentage / 2)
bar = '█' * bar_length + '░' * (50 - bar_length)
report += f"\n{category:8s} |{bar}| {distance:6.1f}m ({percentage:5.1f}%)"
report += f"""
⏱️ 恢复情况
─────────────────────────────────
• 平均心率(模拟): {np.random.randint(120, 145)} bpm
• 最高心率(模拟): {np.random.randint(180, 195)} bpm
• 恢复时间(模拟): {np.random.randint(2, 8)} 分钟
💡 建议{self.suggestions()}
"""
return report
def suggestions(self):
"""生成建议"""
if self.df is None:
return ""
high_speed_ratio = self.df[self.df['is_high_speed']]['distance'].sum() / self.df['distance'].sum()
if high_speed_ratio < 0.1:
return "\n1. 增加高速跑训练比例\n2. 加入间歇性冲刺训练\n3. 提高训练强度"
elif high_speed_ratio > 0.3:
return "\n1. 注意控制训练负荷\n2. 加强恢复和预防措施\n3. 适量减少冲刺训练"
else:
return "\n1. 继续保持当前训练结构\n2. 适当增加冲刺多样性\n3. 关注速度变化规律"
def main():
"""主函数"""
print("🚀 高速跑动距离对比分析系统")
print("="*50)
# 创建分析器
analyzer = SprintAnalyzer(player_name="测试运动员", sampling_rate=10)
# 生成训练数据(3节训练课,每节30分钟)
print("\n📊 正在生成模拟训练数据...")
data = analyzer.generate_training_data(sessions=3, minutes=30)
# 速度分类和距离计算
print("\n🔍 正在进行速度分类和距离计算...")
analyzer.classify_speed()
analyzer.calculate_distance()
# 计算冲刺统计
analyzer.calculate_high_speed_metrics()
# 绘制可视化图表
print("\n📈 正在生成可视化图表...")
analyzer.plot_speed_profile()
# 生成报告
report = analyzer.generate_report()
print(report)
# 导出数据到CSV
try:
analyzer.df.to_csv('sprint_data.csv', index=False)
print("\n💾 详细数据已保存到 'sprint_data.csv'")
print("📄 数据文件包含速度、距离、位置等详细记录")
except Exception as e:
print(f"⚠️ 保存数据失败: {e}")
if __name__ == "__main__":
main()
这个Python案例提供了完整的高速跑动距离分析系统,主要功能包括:
📊 核心功能
数据生成模块
- 模拟3节不同的训练课数据
- 包含速度、位置、时间戳等GPS数据
- 模拟真实跑动模式(间歇冲刺、变速跑等)
速度分析模块
- 将跑动速度分为5个等级(走/慢跑/中速/高速/冲刺)
- 使用自定义阈值判断高速跑动(>6m/s)
- 计算各速度等级的跑动距离和时间
指标计算模块
- 总跑动距离和高速跑距离
- 冲刺次数、平均速度、最大速度
- 恢复时间等专业指标
可视化模块
- 速度-时间曲线图
- 各训练课速度分布箱线图
- 高速跑距离对比柱状图
- 速度区间时间分布堆叠图
分析报告模块
- 自动生成专业分析报告
- 包含训练建议
- 支持数据导出CSV
📈 输出结果
运行后输出:
- 各训练课的速度段距离统计
- 冲刺次数和特征
- 专业分析报告
- 4个可视化图表
这个案例适合体育科学、运动生物力学等领域的使用,也可以修改用于其他场景(如车辆速度分析、物流配送时间分析等),您可以根据需要调整速度阈值、数据类型等参数。