首頁  >  文章  >  後端開發  >  透過數據工程追蹤健康狀況 - 膳食優化章節

透過數據工程追蹤健康狀況 - 膳食優化章節

PHPz
PHPz原創
2024-07-19 11:24:31745瀏覽

介紹

大家好!這將是我的第一篇文章,所以請對我嚴厲一點,批評我你認為我可以改進的地方,我下次一定會考慮的。

過去幾個月,我一直在深入健康,主要是鍛煉和注意飲食,現在我認為我已經掌握了它,我想看看我可以如何進一步優化萬一我可能錯過了一些事情。

目標

在本章中,我希望研究我在整個健康之旅中的膳食,並以下週的膳食計劃作為結論:(1) 達到我的最低蛋白質需求量,(2) 不超過我的卡路里限制, (3) 滿足我的最低纖維要求,(4) 最大限度地降低成本。

數據集

我們首先介紹資料集,也就是我們使用 Cronometer 追蹤的食物。 Cronometer 在我的旅程中一直與我並肩工作,現在,我將匯出我輸入的數據,以便根據我之前列出的目標進行自己的分析。

對我來說幸運的是,Cronometer 可以讓我在他們的網站上輕鬆地將資料匯出到 .csv 檔案。
Screenshot of the export options from Cronometer

在本章中,我們將只匯出「食物和食譜條目」資料集。

我們首先檢查從「食物和食譜條目」獲得的數據。該數據集非常全面,我相信這對未來的章節非常有用!在本章中,我們確實希望將其限制為食物的名稱、含量、蛋白質、卡路里和纖維。

# Importing and checking out the dataset
df = pd.read_csv("servings.csv")
df.head()

資料預處理

我們已經為我們設定了一些列,「食物名稱」、「含量」、「能量(千卡)」、「纖維(克)」和「蛋白質(克)」。完美的!現在,我們唯一缺少的是獲取給定數量的每種食物的成本,因為它沒有在數據集中進行追蹤。對我來說幸運的是,我是第一個輸入資料的人,這樣我就可以輸入我所知道的價格。但是,我不會輸入所有食品的價格。相反,我們向我們的好老朋友 ChatGPT 詢問他們的估計,並透過調整 .csv 檔案填寫我們確實知道的價格。我們將新資料集儲存在「cost.csv」中,該資料集是透過從原始資料集中獲取「食物名稱」和「數量」列而得出的。

# Group by 'Food Name' and collect unique 'Amount' for each group
grouped_df = df.groupby('Food Name')['Amount'].unique().reset_index()

# Expand the DataFrame so each unique 'Food Name' and 'Amount' is on a separate row
expanded_df = grouped_df.explode('Amount')

# Export the DataFrame to a CSV file
expanded_df.to_csv('grouped_food_names_amounts.csv')

# Read the added costs and save as a new DataFrame
df_cost = pd.read_csv("cost.csv").dropna()
df_cost.head()

有些食物被丟棄只是因為它們太奇怪了,不屬於低熱量、營養和/或便宜的數據範圍(或者只是因為我懶得再做一次食譜) )。然後,我們需要合併兩個資料幀,即原始資料集和帶有成本的資料集,以獲得所謂的「最終」資料集。由於原始資料集包含每種食物的條目,這意味著原始資料集具有相同食物的多個條目,尤其是我反覆吃的食物(即雞蛋、雞胸肉、米飯)。我們也希望用「0」填滿沒有值的列,因為這裡最有可能出現問題的來源是「能量」、「纖維」、「蛋白質」和「價格」列。

merged_df = pd.merge(df, df_cost, on=['Food Name', 'Amount'], how='inner')

specified_columns = ['Food Name', 'Amount', 'Energy (kcal)', 'Fiber (g)', 'Protein (g)', 'Price']
final_df = merged_df[specified_columns].drop_duplicates()
final_df.fillna(0, inplace=True)
final_df.head()

最佳化

完美!我們的資料集已經完成,現在我們開始第二部分,優化。回顧研究的目標,我們希望確定在給予最少量蛋白質和纖維以及最大熱量的情況下的最低成本。這裡的選擇是暴力破解每一個組合,但在業界,正確的術語是“線性編程”或“線性優化”,但不要引用我的話。這次,我們將使用 puLP,它是一個旨在實現這一目標的 Python 庫。除了遵循模板之外,我對使用它不太了解,所以請瀏覽他們的文檔,而不是閱讀我對其工作原理的不專業解釋。但對於那些確實想聽我對這個主題的隨意解釋的人來說,我們基本上是在求解 y = ax1 + bx2 + cx3 + ... + zxn。

我們將遵循的模板是混合問題案例研究的模板,我們遵循類似的目標,但在本例中,我們希望全天混合膳食。首先,我們需要將DataFrame 轉換為字典,具體來說,將“食物名稱”作為自變量列表,充當x 序列,然後將能量、纖維、蛋白質和價格作為字典,這樣“食物名稱”:每種食物的價值。請注意,從現在開始,「數量」將被放棄,並將與「食物名稱」連接起來,因為我們不會定量使用它。

# Concatenate Amount into Food Name
final_df['Food Name'] = final_df['Food Name'] + ' ' + final_df['Amount'].astype(str)
food_names = final_df['Food Name'].tolist()

# Create dictionaries for 'Energy', 'Fiber', 'Protein', and 'Price'
energy_dict = final_df.set_index('Food Name')['Energy (kcal)'].to_dict()
fiber_dict = final_df.set_index('Food Name')['Fiber (g)'].to_dict()
fiber_dict['Gardenia, High Fiber Wheat Raisin Loaf 1.00 Slice'] = 3
fiber_dict['Gardenia, High Fiber Wheat Raisin Loaf 2.00 Slice'] = 6
protein_dict = final_df.set_index('Food Name')['Protein (g)'].to_dict()
price_dict = final_df.set_index('Food Name')['Price'].to_dict()

# Display the results
print("Food Names Array:", food_names)
print("Energy Dictionary:", energy_dict)
print("Fiber Dictionary:", fiber_dict)
print("Protein Dictionary:", protein_dict)
print("Price Dictionary:", price_dict)

For those without keen eyesight, continue scrolling. For those who did notice the eerie 2 lines of code, let me explain. I saw this while I was grocery shopping but the nutrition facts on Gardenia's High Fiber Wheat Raisin loaf do not actually have 1 slice be 9 grams of Fiber, it has 2 slices for 6 grams. This is a big deal and has caused me immeasurable pain knowing that the values may be incorrect due to either a misinput of data or a change of ingredients which caused the data to be outdated. Either way, I needed this justice corrected and I will not stand for any less Fiber than I deserve. Moving on.

We go straight into plugging in our values using the template from the Case Study data. We set variables to stand for the minimum values we want out of Protein and Fiber, as well as the maximum Calories we are willing to eat. Then, we let the magical template code do its work and get the results.

# Set variables
min_protein = 120
min_fiber = 40
max_energy = 1500

# Just read the case study at https://coin-or.github.io/pulp/CaseStudies/a_blending_problem.html. They explain it way better than I ever could.
prob = LpProblem("Meal Optimization", LpMinimize)
food_vars = LpVariable.dicts("Food", food_names, 0)
prob += (
    lpSum([price_dict[i] * food_vars[i] for i in food_names]),
    "Total Cost of Food daily",
)
prob += (
    lpSum([energy_dict[i] * food_vars[i] for i in food_names]) <= max_energy,
    "EnergyRequirement",
)
prob += (
    lpSum([fiber_dict[i] * food_vars[i] for i in food_names]) >= min_fiber,
    "FiberRequirement",
)
prob += (
    lpSum([protein_dict[i] * food_vars[i] for i in food_names]) >= min_protein,
    "ProteinRequirement",
)
prob.writeLP("MealOptimization.lp")
prob.solve()
print("Status:", LpStatus[prob.status])
for v in prob.variables():
    if v.varValue > 0:
        print(v.name, "=", v.varValue)
print("Total Cost of Food per day = ", value(prob.objective))

Results

Image description

In order to get 120 grams of protein and 40 grams of fiber, I would need to spend 128 Philippine Pesos on 269 grams of chicken breast fillet, and 526 grams of mung beans. This... does not sound bad at all considering how much I love both ingredients. I will definitely try it out, maybe for a week or a month just to see how much money I would save despite having just enough nutrition.

That was it for this chapter of Tracking Health with Data Engineering, if you want to see the data I worked on in this chapter, visit the repository or visit the notebook for this page. Do leave a comment if you have any and try to stay healthy.

以上是透過數據工程追蹤健康狀況 - 膳食優化章節的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn