好的,我们来一起设计一个功能完整、界面友好的智能体重管理助手。
这个助手将不仅是一个记录工具,更是一个能提供个性化反馈和指导的“健康伙伴”。我们将使用 Python 语言和 Streamlit 框架来构建,因为它能快速创建漂亮的交互式Web应用,非常适合数据展示和工具类应用。
---
项目名称:智衡 - 智能体重管理助手
核心功能模块
我们将从四个核心维度来设计:
1. 数据追踪:记录体重、体脂率、腰围等关键指标。
2. 智能分析:根据历史数据计算趋势、BMI,并生成可视化图表。
3. 个性化目标:设定目标体重,计算每日热量缺口建议。
4. 健康洞察:基于数据提供简单的、鼓励性的建议和里程碑提醒。
---
技术栈
语言: Python 3.8+
Web框架: Streamlit
数据处理: Pandas
图表绘制: Plotly (交互式图表)
数据存储: 本地CSV文件(便于演示和轻量级使用)
---
代码实现
我们将代码拆分成几个逻辑清晰的部分,方便理解和维护。
1. 环境准备与依赖安装
首先,确保你安装了必要的库。
```bash
pip install streamlit pandas plotly
```
2. 主程序代码 (`app.py`)
```python
import streamlit as st
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
from datetime import datetime, timedelta
import os
import numpy as np
-------------------------------
页面配置与全局设置
-------------------------------
st.set_page_config(
page_title="智衡 - 智能体重管理",
page_icon="⚖️",
layout="wide",
initial_sidebar_state="expanded"
)
数据文件路径
DATA_FILE = "weight_data.csv"
-------------------------------
数据管理模块
-------------------------------
def load_data():
"""加载数据,如果文件不存在则返回空DataFrame"""
if os.path.exists(DATA_FILE):
df = pd.read_csv(DATA_FILE)
确保日期格式正确
df['date'] = pd.to_datetime(df['date']).dt.date
return df
else:
创建示例数据,便于演示
return create_sample_data()
def create_sample_data():
"""生成过去60天的模拟数据,方便首次体验"""
dates = [(datetime.now() - timedelta(days=i)).date() for i in range(60, -1, -1)]
weights = np.linspace(82, 78.5, len(dates)) + np.random.normal(0, 0.3, len(dates))
body_fats = np.linspace(28, 25.5, len(dates)) + np.random.normal(0, 0.5, len(dates))
waist = np.linspace(95, 90, len(dates)) + np.random.normal(0, 0.8, len(dates))
df = pd.DataFrame({
'date': dates,
'weight': weights.round(1),
'body_fat': body_fats.round(1),
'waist': waist.round(1)
})
df.to_csv(DATA_FILE, index=False)
return df
def save_data(df):
"""保存数据到CSV文件"""
df.to_csv(DATA_FILE, index=False)
def add_record(date, weight, body_fat, waist):
"""添加一条新记录"""
df = load_data()
检查日期是否已存在,如果存在则更新
if date in df['date'].astype(str).values:
st.warning("该日期已有记录,将更新原有数据。")
df.loc[df['date'].astype(str) == date, ['weight', 'body_fat', 'waist']] = [weight, body_fat, waist]
else:
new_row = pd.DataFrame({'date': [date], 'weight': [weight], 'body_fat': [body_fat], 'waist': [waist]})
df = pd.concat([df, new_row], ignore_index=True)
按日期排序
df = df.sort_values('date').reset_index(drop=True)
save_data(df)
return df
-------------------------------
计算与分析模块
-------------------------------
def calculate_bmi(weight_kg, height_cm):
"""计算BMI指数"""
height_m = height_cm 100
bmi = weight_kg (height_m 2)
return bmi
def get_bmi_category(bmi):
"""根据BMI值返回分类和健康建议"""
if bmi < 18.5:
return "偏瘦", "建议增加营养摄入,适当增肌。"
elif bmi < 24:
return "正常", "保持当前生活方式,注意均衡饮食。"
elif bmi < 28:
return "超重", "建议控制饮食,增加有氧运动。"
else:
return "肥胖", "建议制定科学减重计划,咨询专业人士。"
def calculate_trend(df, window=7):
"""计算移动平均趋势"""
df['weight_ma'] = df['weight'].rolling(window=window).mean()
df['body_fat_ma'] = df['body_fat'].rolling(window=window).mean()
return df
def get_weekly_change(df):
"""计算最近一周的体重变化"""
if len(df) >= 7:
recent = df.tail(7)
return recent.iloc[-1]['weight'] - recent.iloc[0]['weight']
return 0
-------------------------------
可视化模块
-------------------------------
def create_weight_chart(df):
"""创建体重趋势图"""
fig = go.Figure()
原始数据点
fig.add_trace(go.Scatter(
x=df['date'], y=df['weight'],
mode='markers',
name='每日体重',
marker=dict(size=6, color='lightblue')
))
移动平均线
if 'weight_ma' in df.columns:
fig.add_trace(go.Scatter(
x=df['date'], y=df['weight_ma'],
mode='lines',
name='7日均线',
line=dict(color='royalblue', width=3)
))
目标体重线(如果有设定)
if 'target_weight' in st.session_state:
fig.add_hline(y=st.session_state.target_weight,
line_dash="dash",
line_color="green",
annotation_text=f"目标 {st.session_state.target_weight}kg")
fig.update_layout(
title="