「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > データエンジニアリングによる健康状態の追跡 - 食事の最適化の章

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

2024 年 8 月 7 日に公開
ブラウズ:846

導入

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

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

目的

この章では、私の健康の旅を通して食事を研究し、(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.

を解きます。

私たちが従うテンプレートは、ブレンディング問題のケーススタディのテンプレートです。同様の目的に従いますが、この場合は、1 日を通じて食事をブレンドしたいと考えています。まず、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)

視力の弱い方は、そのままスクロールしてください。不気味な 2 行のコードに気づいた人のために説明しましょう。食料品の買い物中にこれを見ましたが、ガーデニアの高繊維小麦レーズンローフの栄養成分表には、実際には1スライスで9グラムの繊維が含まれているのではなく、2スライスで6グラムです。これは大変なことですが、データの入力ミスや成分の変更によりデータが古くなったために、値が間違っている可能性があることを知り、計り知れない苦痛を感じました。いずれにせよ、私はこの正義を正す必要があり、私は自分に値する以上の繊維の不足を支持するつもりはありません。次に進みます。

ケーススタディ データのテンプレートを使用して、値を直接入力します。タンパク質と食物繊維の最小値と、食べてもよい最大カロリーを表す変数を設定します。次に、魔法のテンプレート コードに作業を実行させ、結果を取得します。

# 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]) = 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))

結果

Image description

タンパク質 120 グラムと繊維質 40 グラムを摂取するには、鶏の胸肉 269 グラムと緑豆 526 グラムに 128 フィリピン ペソを費やす必要があります。これは...私が両方の材料をどれだけ愛しているかを考えると、まったく悪くないようです。十分な栄養を摂っているにもかかわらず、どのくらいお金を節約できるかを確認するために、おそらく 1 週間か 1 か月間、ぜひ試してみたいと思います。

データ エンジニアリングによる健康状態の追跡のこの章は以上です。この章で私が取り組んだデータを確認したい場合は、リポジトリにアクセスするか、このページのノートブックにアクセスしてください。何かあればコメントを残して、健康を維持してください。

リリースステートメント この記事は次の場所に転載されています: https://dev.to/wilyanse/tracking-health-with-data-engineering-chapter-1-meal-optimization-2cl7?1 権利侵害がある場合は、[email protected] までご連絡ください。それを削除するには
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3