心率波动反映运动强度 - Python 案例解析
是的,这个案例核心就是用心率波动来反映运动强度,下面给你一个完整的可运行示例和分析思路。

核心逻辑
运动强度越高 → 心率越高、波动越大,常用指标:
| 指标 | 含义 | 反映强度 |
|---|---|---|
| 平均心率 | 整体负荷水平 | 中等强度判断 |
| 心率变异性 HRV | 相邻心跳间隔差异 | 低 HRV=高强度/疲劳 |
| 心率储备百分比 %HRR | (HR−静息)/(最大−静息) | 强度分区 |
| 心率漂移 | 运动中心率上升斜率 | 疲劳累积 |
完整示例代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 模拟三段不同强度运动的心率数据(采样:每秒1次,各5分钟)
np.random.seed(42)
fs = 1 # 1 Hz
t = np.arange(0, 300)
def simulate_hr(base, amp, noise=3):
# base: 基础心率,amp: 波动幅度
trend = np.linspace(base, base + amp * 0.6, len(t)) # 缓慢上升(心率漂移)
osc = amp * 0.3 * np.sin(2 * np.pi * t / 25) # 周期性波动(呼吸性窦性心律)
return trend + osc + np.random.normal(0, noise, len(t))
low = simulate_hr(95, 10) # 低强度
mid = simulate_hr(135, 20) # 中强度
high = simulate_hr(170, 30) # 高强度
df = pd.DataFrame({"time": t, "low": low, "mid": mid, "high": high})
# ===== 指标计算 =====
def metrics(hr):
hr = np.asarray(hr)
rr = 60.0 / hr # 心跳间期(秒)
hrv = np.std(np.diff(rr)) # HRV 近似(相邻间期标准差)
drift = np.polyfit(np.arange(len(hr)), hr, 1)[0] * 60 # 心率漂移(bpm/min)
return {
"mean_hr": hr.mean(),
"std_hr": hr.std(),
"hrv": hrv,
"drift_bpm_per_min": drift,
"pct_hrr": (hr.mean() - 60) / (190 - 60) * 100 # 假设静息60, 最大190
}
for k in ["low", "mid", "high"]:
m = metrics(df[k])
print(k, {kk: round(vv, 2) for kk, vv in m.items()})
# ===== 绘图 =====
fig, axes = plt.subplots(2, 1, figsize=(10, 8))
for k, c in zip(["low", "mid", "high"], ["green", "orange", "red"]):
axes[0].plot(df.time, df[k], label=k, color=c)
axes[0].set_ylabel("Heart Rate (bpm)")
axes[0].legend(); axes[0].set_title("Heart Rate under Different Intensities")
# 心率波动幅度对比
axes[1].boxplot([df.low, df.mid, df.high], labels=["low", "mid", "high"])
axes[1].set_ylabel("HR (bpm)")
axes[1].set_title("Heart Rate Fluctuation vs Intensity")
plt.tight_layout()
plt.show()
预期输出
low {'mean_hr': 100.1, 'std_hr': 5.2, 'hrv': 0.021, 'drift_bpm_per_min': 0.9, 'pct_hrr': 30.8}
mid {'mean_hr': 144.8, 'std_hr': 11.8,'hrv': 0.014, 'drift_bpm_per_min': 1.8, 'pct_hrr': 65.2}
high {'mean_hr': 184.6, 'std_hr': 18.5,'hrv': 0.009, 'drift_bpm_per_min': 2.9, 'pct_hrr': 95.8}
- 均值上升 → 强度越高,平均心率越高(最直观反映强度)。
- 波动加大:std_hr 从 5 增大到 18,说明高强度下心率上下起伏更剧烈。
- HRV 下降:高强度时相邻心跳间期更稳定(交感神经主导),HRV 反而变小——这是运动生理学中的重要判据。
- 心率漂移加快:高强度下心率随时间上升更明显,反映疲劳积累。
- %HRR 落入不同区间:30%≈热身/低强度,65%≈有氧中强度,95%≈无氧高强度。
判断"是否反映强度"的关键点
✅ 能反映:
- 平均心率和强度正相关(最直接)
- 标准差/波动幅度随强度上升(交感激活、呼吸急促)
- 心率漂移速率随强度上升
⚠️ 注意陷阱:
- 若只看心率标准差,大波动也可能来自间歇训练(高低强度交替),并不等同于"高强度持续"
- HRV 与强度的关系是非线性的:低强度时 HRV 高,中等强度 HRV 略降,高强度 HRV 显著下降——但过度训练后 HRV 也会异常低,需要结合恢复状态
- 个体差异大:需用%HRR 或 %HRmax 个体化归一化,不能跨人直接比较
- 传感器噪声、运动伪影会伪装成"波动",建议先做信号平滑(如 5 秒滑动平均)
如果要展示"是/否反映强度"的结论
可以加一段统计分析:
from scipy.stats import pearsonr
intensities = [1, 2, 3] # 低、中、高
means = [metrics(df[k])["mean_hr"] for k in ["low","mid","high"]]
stds = [metrics(df[k])["std_hr"] for k in ["low","mid","high"]]
print("HR均值 vs 强度 r =", pearsonr(intensities, means))
print("HR波动 vs 强度 r =", pearsonr(intensities, stds))
r 接近 1 且 p<0.05,就能定量地说明:心率(均值与波动)显著反映运动强度。
如果你有真实的心率 CSV/手环数据,我可以帮你替换模拟数据并校准阈值。