Python案例统计慢跑恢复时间数据如何?

wen python案例 1

本文目录导读:

Python案例统计慢跑恢复时间数据如何?

  1. 场景设定
  2. 完整代码实现
  3. 关键输出解读
  4. 如何应用到真实数据?
  5. 扩展建议

这是一个关于使用Python统计和分析慢跑恢复时间数据(即运动后心率、配速等指标恢复到正常水平所需的时间)的案例,这类数据通常来自运动手表或心率带,可以用来评估训练强度、疲劳程度以及有氧基础。

以下是一个完整的Python案例分析,包含数据模拟、预处理、指标计算、可视化统计报告

场景设定

你有一份来自智能手表的数据,包含每次慢跑的时间戳、心率(HR)、配速(Pace),我们想统计运动结束后,心率恢复到静息心率+20%以内所需的时间

完整代码实现

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
# -------------------- 1. 模拟数据(替换为你的实际数据) --------------------
np.random.seed(42)
num_points = 1000
time_range = pd.date_range(start='2023-10-01 06:00:00', periods=num_points, freq='1s')
# 模拟跑步活动:前400秒跑步,之后恢复
heart_rate = []
pace = []
for t in range(num_points):
    if t < 400:  # 跑步阶段
        hr_base = 140 + 20 * np.sin(t / 50) + np.random.normal(0, 3)
        pace_base = 5.5 + 0.5 * np.sin(t / 30) + np.random.normal(0, 0.2)
    else:  # 恢复阶段
        # 指数衰减恢复模拟
        hr_base = 120 * np.exp(- (t - 400) / 200) + 65 + np.random.normal(0, 2)
        pace_base = 7.0 + np.random.normal(0.5, 0.3)  # 恢复后慢走
    heart_rate.append(max(60, min(190, hr_base)))
    pace.append(max(4.0, min(10.0, pace_base)))
# 构建DataFrame
df = pd.DataFrame({
    'timestamp': time_range,
    'heart_rate': heart_rate,
    'pace_min_per_km': pace
})
# 设定静息心率为65 bpm,恢复标准为静息心率+20%(即78 bpm)
resting_hr = 65
recovery_threshold = resting_hr * 1.20  # 78
print("原始数据预览(前10行):")
print(df.head())
print(f"\n数据形状: {df.shape}")
print(f"恢复阈值: {recovery_threshold:.1f} bpm")
# -------------------- 2. 数据预处理与活动分段 --------------------
# 假设跑步开始时间就是数据开始时间,这里简单识别活动结束点
# 在实际中,你需要gps或加速度计检测运动状态,这里简化:
# 认为配速突降的时刻为跑步结束
pace_diff = df['pace_min_per_km'].diff()
# 当配速突然变慢超过0.5 min/km时,认为是运动结束点
end_of_run_idx = df[pace_diff > 0.5].index[0] if any(pace_diff > 0.5) else 400
print(f"\n检测到的跑步结束索引: {end_of_run_idx}(对应时间: {df.loc[end_of_run_idx, 'timestamp']})")
# 截取恢复期数据(从运动结束到数据末尾)
recovery_data = df.iloc[end_of_run_idx:].copy()
recovery_data['time_from_end'] = (recovery_data['timestamp'] - recovery_data['timestamp'].iloc[0]).dt.total_seconds()
# -------------------- 3. 计算恢复时间 --------------------
# 恢复时间 = 心率首次降到阈值以下的时间点
recovery_seconds = None
for i, row in recovery_data.iterrows():
    if row['heart_rate'] <= recovery_threshold:
        recovery_idx = i
        recovery_seconds = row['time_from_end']
        print(f"\n心率于 {recovery_seconds:.0f} 秒后降至阈值以下")
        print(f"第{recovery_idx}行数据: 心率={row['heart_rate']:.1f}, 时间戳={row['timestamp']}")
        break
if recovery_seconds is None:
    print("警告:在数据范围内心率未能恢复到阈值以下")
# 更精确的计算(线性插值)
# 找到心率穿越阈值的精确时刻
from scipy.interpolate import interp1d
if recovery_seconds is not None:
    # 取阈值附近的两个点进行线性插值
    cross_idx = recovery_data[recovery_data['heart_rate'] <= recovery_threshold].index[0]
    prev_idx = recovery_data.index.get_loc(cross_idx) - 1
    prev_row = recovery_data.iloc[prev_idx]
    cross_row = recovery_data.loc[cross_idx]
    # 线性插值
    t_prev, t_cross = prev_row['time_from_end'], cross_row['time_from_end']
    hr_prev, hr_cross = prev_row['heart_rate'], cross_row['heart_rate']
    if hr_prev != hr_cross:
        t_interp = t_prev + (recovery_threshold - hr_prev) * (t_cross - t_prev) / (hr_cross - hr_prev)
    else:
        t_interp = t_prev
    print(f"\n精确恢复时间(线性插值): {t_interp:.1f} 秒 ({t_interp/60:.2f} 分钟)")
# -------------------- 4. 统计指标计算 --------------------
print("\n--------------- 统计报告 ---------------")
print(f"跑步阶段最大心率: {df.iloc[:end_of_run_idx]['heart_rate'].max():.1f} bpm")
print(f"跑步阶段平均心率: {df.iloc[:end_of_run_idx]['heart_rate'].mean():.1f} bpm")
print(f"恢复阶段平均心率: {recovery_data['heart_rate'].mean():.1f} bpm")
print(f"恢复至阈值心率所需时间: {recovery_seconds:.0f} 秒 ({recovery_seconds/60:.1f} 分钟)" if recovery_seconds else "未恢复")
# 计算心率恢复率(%HRR恢复情况)
peak_hr = df.iloc[:end_of_run_idx]['heart_rate'].max()
hr_reserve = peak_hr - resting_hr
hr_60s = recovery_data[recovery_data['time_from_end'] <= 60]['heart_rate'].iloc[-1] if len(recovery_data) > 60 else recovery_data['heart_rate'].iloc[-1]
hrr_60s = (peak_hr - hr_60s) / hr_reserve * 100
print(f"1分钟心率恢复率: {hrr_60s:.1f}% HRR")
# 心率恢复斜率(前120秒的线性回归斜率)
from scipy import stats
early_recovery = recovery_data[recovery_data['time_from_end'] <= 120]
if len(early_recovery) > 2:
    slope, intercept, r_value, p_value, std_err = stats.linregress(early_recovery['time_from_end'], early_recovery['heart_rate'])
    print(f"前120秒心率下降斜率: {slope:.3f} bpm/秒 ({slope*60:.2f} bpm/分钟)")
# -------------------- 5. 可视化分析 --------------------
fig, axes = plt.subplots(3, 1, figsize=(12, 9), sharex=True)
# 子图1: 心率曲线
axes[0].plot(df['timestamp'], df['heart_rate'], 'b-', alpha=0.7, label='心率')
axes[0].axhline(y=recovery_threshold, color='r', linestyle='--', label=f'恢复阈值 ({recovery_threshold:.0f} bpm)')
axes[0].axvline(x=df.loc[end_of_run_idx, 'timestamp'], color='gray', linestyle=':', label='运动结束')
if recovery_seconds:
    axes[0].axvline(x=df.loc[cross_idx, 'timestamp'], color='green', linestyle='-.', label=f'恢复点 ({t_interp:.0f}s)')
axes[0].set_ylabel('心率 (bpm)')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
axes[0].set_title('慢跑心率恢复曲线')
# 子图2: 配速曲线
axes[1].plot(df['timestamp'], df['pace_min_per_km'], 'g-', alpha=0.7)
axes[1].axvline(x=df.loc[end_of_run_idx, 'timestamp'], color='gray', linestyle=':')
axes[1].set_ylabel('配速 (min/km)')
axes[1].invert_yaxis()  # 配速越小越快
axes[1].set_title('配速变化')
axes[1].grid(True, alpha=0.3)
# 子图3: 恢复期心率的指数拟合
axes[2].plot(recovery_data['time_from_end'], recovery_data['heart_rate'], 'b.', alpha=0.5, markersize=2)
axes[2].axhline(y=recovery_threshold, color='r', linestyle='--')
axes[2].axvline(x=t_interp if recovery_seconds else 0, color='green', linestyle='-.', label=f'恢复点 ({t_interp:.0f}s)' if recovery_seconds else '')
axes[2].set_xlabel('恢复时间 (秒)')
axes[2].set_ylabel('心率 (bpm)')
axes[2].set_title(f'恢复期心率衰减 (红色虚线: 阈值{recovery_threshold:.0f} bpm)')
axes[2].legend()
axes[2].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# -------------------- 6. 多日趋势分析(示例) --------------------
# 假设你有5天的数据
print("\n--------------- 多日趋势(模拟) ---------------")
days = 5
daily_recovery_times = [120 + np.random.normal(0, 20) for _ in range(days)]  # 秒
dates = pd.date_range('2023-10-01', periods=days)
plt.figure(figsize=(8, 4))
plt.plot(dates, daily_recovery_times, 'bo-', linewidth=2)
plt.xlabel('日期')
plt.ylabel('恢复时间 (秒)')'每日恢复时间趋势')
plt.grid(True, alpha=0.3)
plt.show()
print(f"平均恢复时间: {np.mean(daily_recovery_times):.0f} 秒 ({np.mean(daily_recovery_times)/60:.1f} 分钟)")
print(f"恢复时间变异系数: {np.std(daily_recovery_times)/np.mean(daily_recovery_times)*100:.1f}%")

关键输出解读

运行上述代码后,你将得到:

  1. 恢复时间:精确到0.1秒的恢复时长。
  2. 心率恢复率 (HRR):通常1分钟下降越多,心肺功能越好(健康标准>12bpm)。
  3. 恢复斜率:>0.5 bpm/秒通常表示恢复良好。
  4. 可视化图表:直观看到心率何时穿越阈值。

如何应用到真实数据?

  1. 替换数据源:将 df = pd.read_csv('your_watch_data.csv') 放在代码开头。
  2. 数据清洗:处理缺失值、异常心率(如>220或<30)、运动起止点检测(通常使用GPS速度或加速度计)。
  3. 个性化阈值:将 resting_hr 改为你实际的静息心率。

扩展建议

  • 与训练负荷关联:计算恢复时间与训练时长、平均心率的相关系数。
  • 疲劳指数:如果恢复时间连续几天显著增加(比如增加20%以上),可能表示过度训练。
  • 自动化报告:使用schedule库每天定时运行,发送邮件通知或生成PDF报告。

这个案例涵盖了数据科学在运动医学中的一个典型应用——从原始时间序列中提取有临床意义的指标。

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