ホームページ  >  記事  >  バックエンド開発  >  データエンジニアリングによる健康状態の追跡 - 食事の最適化の章

データエンジニアリングによる健康状態の追跡 - 食事の最適化の章

PHPz
PHPzオリジナル
2024-07-19 11:24:31738ブラウズ

導入

みなさん、こんにちは!これが私の最初の投稿になりますので、厳しく指摘し、改善できると思われる点を批判してください。次回は必ず考慮します。

ここ数か月間、私は主に運動をしたり、食事に気を配ったりして、健康に深く興味を持ってきました。今ではそれをしっかりと理解していると思うので、どのようにしてさらに最適化できるかを知りたいと思いました。見逃しているものもあるかもしれません。

目的

この章では、私の健康の旅全体を通して食事を研究し、(1) 最低タンパク質必要量を満たし、(2) カロリー制限を超えず、 (3) ファイバーの最小要件を満たし、(4) コストを最小限に抑えます。

データセット

まず、Cronometer を使用して追跡した食品であるデータセットを紹介します。 Cronometer は私の旅に協力してきました。これからは、以前にリストした目的に沿って自分で分析するために、入力したデータをエクスポートします。

幸いなことに、Cronometer を使用すると、Web サイトでデータを .csv ファイルに簡単にエクスポートできます。
Screenshot of the export options from Cronometer

この章では、「Food & Recipe Entries」データセットのみをエクスポートします。

「料理とレシピのエントリ」から取得したデータを調べることから始めます。データセットは非常に包括的で、将来の章で役立つと確信しています。この章では、食品の名前、その量、タンパク質、カロリー、繊維に限定したいと思います。

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

データの前処理

「食品名」、「量」、「エネルギー (kcal)」、「食物繊維 (g)」、「タンパク質 (g)」の列がすでに設定されています。完璧!ここで、私たちに欠けている唯一のことは、データセット内で追跡されていなかったため、特定の量を与えられた場合の各食品のコストを取得することです。幸いなことに、最初にデータを入力したのは私だったので、知っている価格を入力できます。ただし、すべての食品の価格を入力するわけではありません。代わりに、古き良き友人である 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()

一部の食品は、単に奇妙に特殊すぎて、低カロリー、栄養価が高い、および/または安価であるというデータの範囲に含まれないという理由だけで除外されました(または単にレシピを再度作るのが面倒だったという理由だけ) )。次に、想定される「最終」データセットを取得するために、元のデータセットとコストが設定されたデータセットの 2 つのデータ フレームをマージする必要があります。元のデータセットには各食品のエントリが含まれているため、元のデータセットには同じ食品、特に繰り返し食べる食品 (つまり、卵、鶏の胸肉、米) の複数のエントリがあることを意味します。また、ここで最も問題の原因となる可能性が高いのは「エネルギー」、「繊維」、「タンパク質」、「価格」列であるため、値のない列には「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()

最適化

完璧です!データセットが完成したので、次は 2 番目の部分である最適化を始めます。研究の目的を思い出して、タンパク質と繊維の最小量とカロリーの最大量を考慮した場合の最小コストを特定したいと思います。ここでのオプションは、すべての組み合わせを総当たりで実行することですが、業界では適切な用語は「線形計画法」または「線形最適化」ですが、それに関して私の言葉を引用しないでください。今回は、まさにそれを目的とした Python ライブラリである puLP を使用します。私はテンプレートに従う以外にその使用方法についてあまり知りません。そのため、それがどのように機能するかについての私の専門外の説明を読む代わりに、ドキュメントを参照してください。ただし、このトピックについての私のカジュアルな説明を聞きたい人のために、基本的に 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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。