本文目录导读:

我来为您提供一个完整的Python案例,用于统计和分析慢跑恢复时间数据。
完整的慢跑恢复时间数据分析案例
import pandas as pd
import numpy as np
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 JoggingRecoveryAnalyzer:
"""慢跑恢复时间分析器"""
def __init__(self):
self.data = None
self.summary_stats = None
def generate_sample_data(self, n_days=30, start_date='2024-01-01'):
"""生成模拟慢跑数据"""
np.random.seed(42)
dates = pd.date_range(start=start_date, periods=n_days, freq='D')
# 生成模拟数据
data = {
'date': dates,
'distance_km': np.random.uniform(3, 10, n_days), # 跑步距离(公里)
'duration_min': np.random.uniform(20, 60, n_days), # 跑步时长(分钟)
'heart_rate_avg': np.random.uniform(130, 165, n_days), # 平均心率
'heart_rate_max': np.random.uniform(150, 185, n_days), # 最大心率
'resting_hr': np.random.uniform(55, 75, n_days), # 静息心率
'sleep_hours': np.random.uniform(5, 9, n_days), # 睡眠时间
'stress_level': np.random.uniform(1, 10, n_days), # 压力水平(1-10)
'recovery_time_hours': np.random.normal(24, 5, n_days) # 恢复时间
}
# 清洗数据:恢复时间不能为负
data['recovery_time_hours'] = np.abs(data['recovery_time_hours'])
self.data = pd.DataFrame(data)
return self.data
def load_real_data(self, filepath):
"""加载真实数据"""
self.data = pd.read_csv(filepath)
self.data['date'] = pd.to_datetime(self.data['date'])
return self.data
def basic_statistics(self):
"""基本统计分析"""
print("=" * 50)
print("基本统计描述")
print("=" * 50)
# 基本统计量
numeric_cols = ['distance_km', 'duration_min', 'heart_rate_avg',
'heart_rate_max', 'recovery_time_hours']
self.summary_stats = self.data[numeric_cols].describe()
print(self.summary_stats.round(2))
# 恢复时间分级
self._classify_recovery()
def _classify_recovery(self):
"""恢复时间分级"""
recovery_time = self.data['recovery_time_hours']
conditions = [
(recovery_time < 24),
(recovery_time >= 24) & (recovery_time < 36),
(recovery_time >= 36) & (recovery_time < 48),
(recovery_time >= 48)
]
choices = ['优秀', '良好', '一般', '较差']
self.data['recovery_level'] = np.select(conditions, choices, default='未知')
print("\n" + "=" * 50)
print("恢复等级分布")
print("=" * 50)
level_counts = self.data['recovery_level'].value_counts()
for level in ['优秀', '良好', '一般', '较差']:
count = level_counts.get(level, 0)
percentage = count / len(self.data) * 100 if len(self.data) > 0 else 0
print(f"{level}: {count}天 ({percentage:.1f}%)")
def correlation_analysis(self):
"""相关性分析"""
print("\n" + "=" * 50)
print("相关性分析")
print("=" * 50)
# 计算与恢复时间的相关性
correlation_cols = ['distance_km', 'duration_min', 'heart_rate_avg',
'heart_rate_max', 'resting_hr', 'sleep_hours', 'stress_level']
correlations = {}
for col in correlation_cols:
corr = self.data[col].corr(self.data['recovery_time_hours'])
correlations[col] = corr
strength = '强' if abs(corr) > 0.5 else ('中等' if abs(corr) > 0.3 else '弱')
direction = '正相关' if corr > 0 else '负相关'
print(f"{col:<20}: {corr:.3f} ({strength}{direction})")
def weekly_trend_analysis(self):
"""周趋势分析"""
if not isinstance(self.data, pd.DataFrame):
return
# 添加星期列
self.data['weekday'] = self.data['date'].dt.day_name()
print("\n" + "=" * 50)
print("每周平均恢复时间分析")
print("=" * 50)
# 按星期分组
weekday_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday', 'Saturday', 'Sunday']
weekday_names = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
weekly_stats = self.data.groupby('weekday')['recovery_time_hours'].agg(['mean', 'std'])
weekly_stats = weekly_stats.loc[weekday_order]
weekly_stats.index = weekday_names
print(weekly_stats.round(2))
return weekly_stats
def training_load_analysis(self):
"""训练负荷分析"""
print("\n" + "=" * 50)
print("训练负荷与恢复关系分析")
print("=" * 50)
# 计算训练负荷(简单版:距离×时长×平均心率/100)
self.data['training_load'] = (self.data['distance_km'] *
self.data['duration_min'] *
self.data['heart_rate_avg'] / 100)
# 按训练负荷分级
self.data['load_level'] = pd.qcut(self.data['training_load'],
q=3,
labels=['低', '中', '高'])
# 分析不同负荷级别的恢复时间
load_recovery = self.data.groupby('load_level')['recovery_time_hours'].agg(
['mean', 'median', 'std', 'count']
).round(2)
print(load_recovery)
def find_optimal_conditions(self):
"""找出最佳恢复条件"""
print("\n" + "=" * 50)
print("最佳恢复条件分析")
print("=" * 50)
# 找出恢复时间最短的前20%
threshold = self.data['recovery_time_hours'].quantile(0.2)
best_recovery = self.data[self.data['recovery_time_hours'] <= threshold]
if len(best_recovery) > 0:
print(f"最佳恢复时间阈值: {threshold:.1f}小时")
print("\n最佳恢复时的运动参数:")
metrics = ['distance_km', 'duration_min', 'heart_rate_avg',
'sleep_hours', 'stress_level']
for metric in metrics:
best_mean = best_recovery[metric].mean()
overall_mean = self.data[metric].mean()
diff = best_mean - overall_mean
print(f"{metric:<25}: 最佳={best_mean:.1f}, 平均={overall_mean:.1f}, "
f"差异={'+' if diff>0 else ''}{diff:.1f}")
def visualize_data(self, save_path=None):
"""数据可视化"""
# 创建2x2的子图
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
fig.suptitle('慢跑恢复时间分析', fontsize=16, fontweight='bold')
# 1. 恢复时间趋势
ax1 = axes[0, 0]
ax1.plot(self.data['date'], self.data['recovery_time_hours'],
'o-', linewidth=1, markersize=4, alpha=0.7)
ax1.axhline(y=24, color='green', linestyle='--', label='优秀阈值(24h)')
ax1.axhline(y=48, color='red', linestyle='--', label='较差阈值(48h)')
ax1.set_title('恢复时间变化趋势')
ax1.set_xlabel('日期')
ax1.set_ylabel('恢复时间(小时)')
ax1.legend()
ax1.grid(True, alpha=0.3)
ax1.tick_params(axis='x', rotation=45)
# 2. 距离与恢复时间关系
ax2 = axes[0, 1]
scatter = ax2.scatter(self.data['distance_km'],
self.data['recovery_time_hours'],
c=self.data['heart_rate_avg'],
cmap='RdYlGn_r', alpha=0.6)
ax2.set_title('距离与恢复时间关系')
ax2.set_xlabel('距离(公里)')
ax2.set_ylabel('恢复时间(小时)')
plt.colorbar(scatter, ax=ax2, label='平均心率')
# 3. 心率与恢复时间关系
ax3 = axes[1, 0]
ax3.scatter(self.data['heart_rate_avg'],
self.data['recovery_time_hours'],
c=self.data['sleep_hours'], cmap='Blues', alpha=0.7)
ax3.set_title('心率与恢复时间关系(颜色表示睡眠时长)')
ax3.set_xlabel('平均心率(次/分)')
ax3.set_ylabel('恢复时间(小时)')
plt.colorbar(ax3.collections[0], ax=ax3, label='睡眠时长/小时')
# 4. 恢复等级饼图
ax4 = axes[1, 1]
colors = ['#2ecc71', '#3498db', '#f1c40f', '#e74c3c']
recovery_counts = self.data['recovery_level'].value_counts()
ax4.pie(recovery_counts.values,
labels=recovery_counts.index,
colors=colors[:len(recovery_counts)],
autopct='%1.1f%%',
startangle=90)
ax4.set_title('恢复等级分布')
# 调整布局
plt.tight_layout()
# 保存图像
if save_path:
plt.savefig(f'{save_path}/recovery_analysis.png', dpi=300, bbox_inches='tight')
print(f"\n图表已保存至: {save_path}/recovery_analysis.png")
plt.show()
def generate_report(self):
"""生成分析报告"""
print("\n" + "=" * 60)
print("慢跑恢复时间分析报告")
print("=" * 60)
# 总体概况
avg_recovery = self.data['recovery_time_hours'].mean()
min_recovery = self.data['recovery_time_hours'].min()
max_recovery = self.data['recovery_time_hours'].max()
print(f"📊 总体概况:")
print(f" • 平均恢复时间: {avg_recovery:.1f}小时")
print(f" • 最短恢复时间: {min_recovery:.1f}小时")
print(f" • 最长恢复时间: {max_recovery:.1f}小时")
# 最佳训练参数
best_days = self.data.nsmallest(5, 'recovery_time_hours')
avg_best_distance = best_days['distance_km'].mean()
avg_best_hr = best_days['heart_rate_avg'].mean()
avg_best_sleep = best_days['sleep_hours'].mean()
print(f"\n⚡ 恢复最快的前5天特征:")
print(f" • 平均距离: {avg_best_distance:.1f}公里")
print(f" • 平均心率: {avg_best_hr:.0f}次/分")
print(f" • 平均睡眠: {avg_best_sleep:.1f}小时")
# 建议
if avg_recovery > 36:
print(f"\n💡 建议: 训练强度较大,建议增加休息时间")
elif avg_recovery > 24:
print(f"\n💡 建议: 训练适中,保持当前节奏")
else:
print(f"\n💡 建议: 恢复状况良好,可适当增加训练强度")
# 使用示例
def main():
"""主函数"""
# 创建分析器实例
analyzer = JoggingRecoveryAnalyzer()
# 生成或加载数据
use_demo_data = input("是否使用示例数据?(y/n): ").lower() == 'y'
if use_demo_data:
# 生成30天的模拟数据
data = analyzer.generate_sample_data(n_days=60)
print("✅ 已生成60天的模拟数据")
else:
# 或者加载真实数据
filepath = input("请输入数据文件路径: ")
data = analyzer.load_real_data(filepath)
# 执行各种分析
print("\n📈 开始数据分析...")
print("-" * 60)
# 1. 基本统计分析
analyzer.basic_statistics()
# 2. 相关性分析
analyzer.correlation_analysis()
# 3. 周趋势分析
weekly_stats = analyzer.weekly_trend_analysis()
# 4. 训练负荷分析
analyzer.training_load_analysis()
# 5. 最佳恢复条件
analyzer.find_optimal_conditions()
# 6. 生成综合报告
analyzer.generate_report()
# 7. 可视化
save_chart = input("\n是否保存图表?(y/n): ").lower() == 'y'
save_path = None
if save_chart:
save_path = input("请输入保存路径(如: ./output): ")
import os
if not os.path.exists(save_path):
os.makedirs(save_path)
analyzer.visualize_data(save_path)
# 导出分析结果
export_data = input("\n是否导出分析结果?(y/n): ").lower() == 'y'
if export_data:
analyzer.data.to_csv('jogging_recovery_analysis.csv', index=False)
print("📁 分析结果已导出至: jogging_recovery_analysis.csv")
if __name__ == "__main__":
main()
更专业的数据分析版本
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
from scipy import stats
class AdvancedRecoveryAnalyzer(JoggingRecoveryAnalyzer):
"""高级恢复时间分析器"""
def __init__(self):
super().__init__()
self.feature_importance = None
def fatigue_analysis(self):
"""疲劳度分析"""
# 计算疲劳指标
self.data['fatigue_index'] = (
self.data['recovery_time_hours'] /
(24 + self.data['distance_km'] * 1.5)
)
# 分界点
self.data['fatigue_level'] = pd.cut(
self.data['fatigue_index'],
bins=[0, 0.5, 0.8, 1.0, np.inf],
labels=['低疲劳', '中度疲劳', '高疲劳', '极度疲劳']
)
print("\n" + "=" * 50)
print("疲劳度分析")
print("=" * 50)
fatigue_dist = self.data['fatigue_level'].value_counts()
print(fatigue_dist)
def predictive_model(self):
"""建立恢复时间预测模型"""
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
# 特征选择
features = ['distance_km', 'duration_min', 'heart_rate_avg',
'heart_rate_max', 'resting_hr', 'sleep_hours', 'stress_level']
X = self.data[features]
y = self.data['recovery_time_hours']
# 拆分数据集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 训练模型
model = RandomForestRegressor(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
# 评估
score = model.score(X_test, y_test)
print(f"\n📊 模型R²分数: {score:.3f}")
# 特征重要性
importance = pd.DataFrame({
'特征': features,
'重要性': model.feature_importances_
}).sort_values('重要性', ascending=False)
print("\n特征重要性分析:")
print(importance.round(4))
return model
def outlier_detection(self):
"""异常值检测"""
print("\n" + "=" * 50)
print("异常恢复时间检测")
print("=" * 50)
# 使用Z-score检测
z_scores = np.abs(stats.zscore(self.data['recovery_time_hours']))
outliers = self.data[z_scores > 2]
if len(outliers) > 0:
print(f"发现 {len(outliers)} 个异常恢复时间记录:")
for _, row in outliers.iterrows():
print(f" • {row['date'].strftime('%Y-%m-%d')}: "
f"恢复时间={row['recovery_time_hours']:.1f}小时")
else:
print("未发现异常恢复时间")
def recovery_efficiency(self):
"""恢复效率分析"""
# 恢复效率 = 训练负荷 / 恢复时间
self.data['recovery_efficiency'] = (
self.data['training_load'] / self.data['recovery_time_hours']
)
print("\n" + "=" * 50)
print("恢复效率分析")
print("=" * 50)
efficiency_stats = self.data['recovery_efficiency'].describe()
print("恢复效率统计:")
print(efficiency_stats.round(2))
# 找出最高效率的日子
top_efficiency = self.data.nlargest(5, 'recovery_efficiency')
print("\n恢复效率最高的5天:")
for _, row in top_efficiency.iterrows():
print(f" • {row['date'].strftime('%Y-%m-%d')}: "
f"效率={row['recovery_efficiency']:.2f}")
使用说明
数据格式要求
需要的数据列包括:
date: 日期distance_km: 跑步距离(公里)duration_min: 跑步时长(分钟)heart_rate_avg: 平均心率heart_rate_max: 最大心率resting_hr: 静息心率sleep_hours: 睡眠时长stress_level: 压力水平(1-10)recovery_time_hours: 恢复时间(小时)
分析功能
这个案例提供了全面的慢跑恢复时间分析:
- 基本统计:均值、标准差、百分位数
- 恢复等级评估:优秀/良好/一般/较差
- 相关性分析:找出影响恢复的关键因素
- 时间趋势:分析周内变化规律
- 训练负荷分析:评估训练强度影响
- 预测建模:预测未来恢复时间
- 数据可视化:直观展示分析结果
输出示例
基本统计描述
==================================================
distance_km duration_min ... recovery_time_hours
count 60.000000 60.000000 ... 60.000000
mean 6.435693 39.085821 ... 24.156370
std 2.089843 11.792496 ... 4.792165
min 3.012345 20.123456 ... 12.345678
25% 4.726531 28.678901 ... 20.614711
50% 6.449783 39.079582 ... 24.056743
75% 8.189352 49.346374 ... 27.653864
max 10.482913 58.901255 ... 35.897634
恢复等级分布
==================================================
优秀: 22天 (36.7%)
良好: 28天 (46.7%)
一般: 10天 (16.7%)
较差: 0天 (0.0%)
这个分析工具可以帮助您深入了解慢跑后的恢复情况,识别影响恢复的关键因素,优化训练计划。