iT邦幫忙

0

Day 19:睡眠與喝水量統計——計算平均值

  • 分享至 

  • xImage
  •  

一、前言

在前幾天的學習中,我已經完成健康紀錄的新增、查詢、修改與刪除,並且初步建立了個人健康儀表板,讓使用者可以查看每日的喝水量、睡眠時間與運動分鐘數。

然而,只有單筆紀錄還不足以觀察長期的生活習慣。例如,某一天喝了 2000 毫升的水,不代表每天都有達到相同的喝水量;某一天睡了 8 小時,也不代表平時的睡眠時間都很充足。

因此,今天的目標是學習使用 Python 的 Pandas 套件計算平均喝水量與平均睡眠時間,並將統計結果整合至 Streamlit 健康儀表板,讓使用者更容易了解自己的生活習慣。

二、學習目標

認識平均值的計算方式。

使用 Pandas 的 mean() 計算平均喝水量與平均睡眠時間。

學習處理空白、無效或非數字的資料。

將統計結果顯示在 Streamlit 網頁上。

了解平均值的限制,避免只根據單一統計數字判斷健康狀況。

三、認識平均值與 Pandas

平均值是一種常見的統計指標,可以協助我們了解一組資料的整體情況。

計算方式如下:

平均值 = 所有有效數值的總和 ÷ 有效數值的筆數

假設最近三筆睡眠紀錄分別為 6、7、8 小時:

[
\frac{6+7+8}{3}=7
]

因此,這三筆紀錄的平均睡眠時間為 7 小時。

在 Pandas 中,可以使用 mean() 計算平均值:

import pandas as pd

sleep_data = pd.Series([6, 7, 8])
average_sleep = sleep_data.mean()

print(average_sleep)

執行結果:

7.0

同樣的方式也能用來計算喝水量。

water_data = pd.Series([1500, 2000, 1800])
average_water = water_data.mean()

print(average_water)

執行結果:

1766.6666666666667

這代表三筆紀錄的平均喝水量約為 1767 毫升。

四、讀取健康紀錄並處理資料

目前系統將健康資料儲存在 health_records.csv,其中包含以下欄位:
https://ithelp.ithome.com.tw/upload/images/20261028/20178903tx8NlJIUHn.png

在進行統計前,需要先讀取資料,並確保喝水量與睡眠時間是可以計算的數字。

例如,資料可能因為輸入錯誤而出現空白或文字。如果直接將這些內容當成數字運算,就可能造成錯誤。因此,我們可以使用 pd.to_numeric() 搭配 errors="coerce",將無法轉換的內容設為缺失值 NaN。

import pandas as pd
from pathlib import Path

FILE_PATH = Path("health_records.csv")

if FILE_PATH.exists():
records = pd.read_csv(FILE_PATH)

records["water_ml"] = pd.to_numeric(
    records["water_ml"],
    errors="coerce"
)

records["sleep_hours"] = pd.to_numeric(
    records["sleep_hours"],
    errors="coerce"
)

print(records)

else:
print("目前尚無健康紀錄。")

這個步驟可以讓後續的統計更加穩定。不過,將文字轉換成缺失值並不代表資料一定合理;例如負數喝水量或負數睡眠時間,仍然需要額外的資料驗證。

五、實作:在健康儀表板顯示平均值

接下來,將平均喝水量與平均睡眠時間整合到 Streamlit 網頁。

請在專案資料夾中開啟 app.py,將原本的程式碼備份後,替換成以下完整版本。

from pathlib import Path

import pandas as pd
import streamlit as st

FILE_PATH = Path("health_records.csv")

st.set_page_config(
page_title="個人健康習慣追蹤系統",
page_icon="🌱",
layout="wide"
)

st.title("🌱 個人健康習慣追蹤系統")
st.subheader("睡眠與喝水量統計")

if not FILE_PATH.exists():
st.info("目前尚無健康紀錄,請先新增每日健康資料。")
st.stop()

try:
records = pd.read_csv(FILE_PATH)
except (OSError, pd.errors.ParserError, UnicodeDecodeError):
st.error("讀取健康紀錄失敗,請檢查 CSV 檔案。")
st.stop()

if records.empty:
st.info("目前沒有可供統計的健康紀錄。")
st.stop()

確認統計需要的欄位是否存在

required_columns = ["water_ml", "sleep_hours"]
missing_columns = [
column
for column in required_columns
if column not in records.columns
]

if missing_columns:
st.error(
"健康紀錄缺少必要欄位:" + ", ".join(missing_columns)
)
st.stop()

將統計欄位轉換成數字

records["water_ml"] = pd.to_numeric(
records["water_ml"],
errors="coerce"
)

records["sleep_hours"] = pd.to_numeric(
records["sleep_hours"],
errors="coerce"
)

排除缺失值與不合理的負數

valid_water = records.loc[
records["water_ml"].ge(0),
"water_ml"
].dropna()

valid_sleep = records.loc[
records["sleep_hours"].ge(0),
"sleep_hours"
].dropna()

計算平均值

average_water = (
valid_water.mean()
if not valid_water.empty
else None
)

average_sleep = (
valid_sleep.mean()
if not valid_sleep.empty
else None
)

顯示統計結果

col1, col2 = st.columns(2)

with col1:
st.metric(
"平均喝水量",
f"{average_water:,.0f} 毫升"
if average_water is not None
else "尚無有效資料"
)
st.caption(f"有效紀錄筆數:{len(valid_water)}")

with col2:
st.metric(
"平均睡眠時間",
f"{average_sleep:.1f} 小時"
if average_sleep is not None
else "尚無有效資料"
)
st.caption(f"有效紀錄筆數:{len(valid_sleep)}")

st.divider()

st.subheader("健康紀錄明細")
st.dataframe(records, use_container_width=True)

st.caption(
"統計結果以目前檔案中的有效紀錄計算;"
"同一天若有多筆紀錄,每筆都會納入平均值。"
)

程式碼重點說明

  1. 使用 pd.read_csv() 讀取資料

系統會從 CSV 檔案取得過去保存的健康紀錄,不需要每次開啟網站時重新輸入。

  1. 使用 pd.to_numeric() 整理數值

records["water_ml"] = pd.to_numeric(
records["water_ml"],
errors="coerce"
)

這段程式會將喝水量轉換成數字,無法轉換的內容則設為缺失值,避免文字影響計算。

  1. 使用 mean() 計算平均值

average_water = valid_water.mean()
average_sleep = valid_sleep.mean()

mean() 會計算有效數值的平均值。程式另外檢查資料是否為空,避免沒有有效紀錄時顯示錯誤。

  1. 使用 st.metric() 呈現統計結果

st.metric() 可以用來顯示重要數字,例如平均喝水量、平均睡眠時間等。透過儀表板,使用者不必自行計算,就能快速掌握目前紀錄的整體情況。

六、實際執行與測試

完成程式碼後,開啟終端機,進入專案資料夾,執行:

python -m streamlit run app.py

接著,依照以下測試案例確認功能是否正常。
https://ithelp.ithome.com.tw/upload/images/20261028/20178903Ek6zG72sDJ.png

測試時,建議先建立幾筆測試資料,確認平均值與手動計算的結果一致。若需要修改 CSV 進行測試,請先備份原始檔案,以免影響已保存的健康紀錄。

另外,本日程式只排除負數與無效資料,尚未設定喝水量或睡眠時間的合理上限;這些條件可以在後續的資料驗證與系統測試階段進一步完善。

七、今日成果與學習心得

今天完成了健康習慣追蹤系統的基礎統計功能,學習如何透過 Pandas 計算平均喝水量與平均睡眠時間,並利用 Streamlit 將結果呈現在網頁儀表板上。

透過這次實作,我了解到資料保存只是健康追蹤系統的第一步。當系統累積了一定數量的紀錄後,還需要透過統計方法,將原始數字轉換成更容易理解的資訊。

同時,我也認識到資料品質對統計結果的重要性。若紀錄中包含空白、文字或不合理的數值,就可能影響分析結果。因此,資料驗證與統計功能需要互相配合。

需要注意的是,平均值只能反映目前有效紀錄的整體情況,不能直接代表每一天的表現,也不能單獨用來判斷個人的健康狀態。若要進一步了解生活習慣的變化,還需要搭配日期、每週統計與圖表進行分析。

八、下一步學習方向

第二十天將進入「每週運動分析——統計運動時間與次數」。

下一階段將學習如何利用日期篩選健康紀錄,計算每週的運動總分鐘數與運動次數,並比較不同週的活動情況,讓個人健康習慣追蹤系統從單純的資料記錄,逐步發展成具備時間區間分析能力的工具。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言