在健康管理热潮下,越来越多人通过记录跑步、骑行等运动数据来追踪健身效果。但手动统计分析耗时费力,如何快速从CSV格式的运动记录中提取关键信息(如总距离、月度趋势)并可视化?本文将用Python结合pandas(数据处理)和matplotlib(可视化),实现一个自动化的运动数据分析工具,帮助你一键生成统计报告和直观图表。
实现思路
我们的工具需完成四大核心任务:
1. 数据读取:解析CSV文件,处理日期格式并计算运动速度;
2. 统计分析:计算总次数、总距离、平均距离、最快速度,并按月份分组统计;
3. 可视化展示:用折线图展示单次运动距离趋势,柱状图对比月度运动总量;
4. 结果输出:格式化打印统计信息,直观呈现分析结果。
代码实现(Python)
下面是完整的代码实现,包含详细注释:
import pandas as pd
import matplotlib.pyplot as plt
import os
def read_data(file_path):
"""读取CSV文件并预处理数据:解析日期、计算速度、提取月份"""
try:
# 读取CSV,自动识别日期列(需确保日期格式正确)
df = pd.read_csv(file_path)
df['日期'] = pd.to_datetime(df['日期']) # 转换为datetime类型
# 计算速度:距离(km) ÷ 时间(分钟),单位 km/分钟
df['速度(km/分钟)'] = df['距离(km)'] / df['时间(分钟)']
# 提取月份名称(如“1月”“2月”),用于分组
df['月份名称'] = df['日期'].dt.strftime('%m月').str.replace('^0', '', regex=True)
return df
except FileNotFoundError:
print(f"错误:文件 {file_path} 不存在!")
return None
except Exception as e:
print(f"数据处理失败:{e}")
return None
def analyze_data(df):
"""统计分析:总次数、总距离、平均距离、最快速度、月度统计"""
# 总运动次数
total_count = len(df)
# 总距离(km)
total_distance = df['距离(km)'].sum()
# 平均距离(km)
avg_distance = df['距离(km)'].mean()
# 最快速度:找到速度最大值的行
max_speed_row = df[df['速度(km/分钟)'] == df['速度(km/分钟)'].max()]
max_speed = max_speed_row['速度(km/分钟)'].values[0]
max_speed_date = max_speed_row['日期'].dt.strftime('%Y-%m-%d').values[0]
max_speed_distance = max_speed_row['距离(km)'].values[0]
max_speed_time = max_speed_row['时间(分钟)'].values[0]
# 月度统计:按月份分组,求和距离、计数次数
monthly_stats = df.groupby('月份名称').agg(
总距离=('距离(km)', 'sum'),
运动次数=('距离(km)', 'count')
).reset_index()
# 按月份数字排序(避免“10月”排在“2月”前)
monthly_stats['month_num'] = monthly_stats['月份名称'].str.replace('月', '').astype(int)
monthly_stats = monthly_stats.sort_values('month_num').drop('month_num', axis=1)
return {
'total_count': total_count,
'total_distance': total_distance,
'avg_distance': avg_distance,
'max_speed': max_speed,
'max_speed_date': max_speed_date,
'max_speed_distance': max_speed_distance,
'max_speed_time': max_speed_time,
'monthly_stats': monthly_stats
}
def visualize_data(df, stats):
"""可视化:折线图(日期-距离)、柱状图(月份-总距离)"""
# 设置中文显示(Windows/macOS/Linux通用方案)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 替换为系统支持的中文字体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# ---- 折线图:单次运动距离趋势 ----
plt.figure(figsize=(10, 6))
plt.plot(
df['日期'].dt.strftime('%Y-%m-%d'), # x轴:格式化后的日期
df['距离(km)'], # y轴:距离
marker='o', color='blue', label='运动距离(km)'
)
plt.xlabel('日期')
plt.ylabel('距离(km)')
plt.title('每次运动距离变化趋势')
plt.xticks(rotation=45) # 旋转x轴标签,避免重叠
plt.grid(linestyle='--', alpha=0.7) # 添加网格线
plt.legend()
plt.tight_layout() # 自动调整布局
plt.savefig('distance_trend.png') # 保存图表
# ---- 柱状图:月度总距离对比 ----
plt.figure(figsize=(8, 6))
months = stats['monthly_stats']['月份名称']
total_distances = stats['monthly_stats']['总距离']
plt.bar(months, total_distances, color='green', width=0.6)
plt.xlabel('月份')
plt.ylabel('总距离(km)')
plt.title('各月运动总距离对比')
# 在柱子上方显示数值
for i, v in enumerate(total_distances):
plt.text(i, v + 0.1, f'{v:.1f}', ha='center')
plt.tight_layout()
plt.savefig('monthly_total_distance.png')
# 显示所有图表
plt.show()
def print_stats(stats):
"""打印统计信息:总次数、总距离、平均距离、最快速度、月度汇总"""
print(f"总运动次数:{stats['total_count']}次")
print(f"总距离:{stats['total_distance']:.1f} km")
print(f"平均距离:{stats['avg_distance']:.2f} km")
print(f"最快速度:{stats['max_speed']:.3f} km/分钟(对应{stats['max_speed_date']},{stats['max_speed_distance']}km/{stats['max_speed_time']}分钟)")
print("月度总距离:")
for _, row in stats['monthly_stats'].iterrows():
print(f"- {row['月份名称']}:{row['总距离']:.1f} km({row['运动次数']}次)")
def main():
# 示例CSV文件路径(可改为用户输入或文件选择)
file_path = 'sports_data.csv'
if not os.path.exists(file_path):
print(f"错误:文件 {file_path} 不存在!请检查路径或替换为实际文件。")
return
# 读取数据
df = read_data(file_path)
if df is None:
return
# 分析数据
stats = analyze_data(df)
# 输出统计信息
print_stats(stats)
# 可视化
visualize_data(df, stats)
if __name__ == "__main__":
main()
代码运行与测试
- 依赖安装:执行
pip install pandas matplotlib安装所需库。 - 数据准备:将示例CSV内容保存为
sports_data.csv(与脚本同目录):
csv
日期,距离(km),时间(分钟),卡路里
2023-01-01,5.2,30,250
2023-01-05,6.1,35,280
2023-02-02,4.8,28,220
2023-02-10,5.5,32,260
2023-03-01,7.0,40,320 - 运行脚本:执行
python 脚本名.py,将输出统计信息并弹出两张图表(距离趋势折线图、月度总距离柱状图)。
扩展与优化建议
- 多运动类型支持:在CSV中添加“运动类型”列,分组时按
运动类型+月份统计,可视化时用不同颜色区分类型。 - 异常值过滤:在
read_data中添加逻辑,如df = df[df['距离(km)'] > 0]排除无效数据。 - 用户交互:通过
tkinter或PyQt实现文件选择界面,提升工具易用性。
总结
本工具通过Python的pandas和matplotlib,实现了从CSV文件读取到数据统计、可视化的全流程。你不仅能掌握文件读写、数据分组聚合、可视化绘图等核心技能,还能将其拓展为更强大的健康管理工具。快来试试用自己的运动数据生成个性化分析报告吧!