大家好!这将是我的第一篇文章,所以请对我严厉一点,批评我你认为我可以改进的地方,我下次一定会考虑的。
过去几个月,我一直在深入健康,主要是锻炼和注意饮食,现在我认为我已经掌握了它,我想看看我可以如何进一步优化万一我可能错过了一些事情。
在本章中,我希望研究我在整个健康之旅中的膳食,并以下周的膳食计划作为结论:(1) 达到我的最低蛋白质需求量,(2) 不超过我的卡路里限制, (3) 满足我的最低纤维要求,(4) 最大限度地降低成本。
我们首先介绍数据集,即我们使用 Cronometer 跟踪的食物。 Cronometer 在我的旅程中一直与我并肩工作,现在,我将导出我输入的数据,以便根据我之前列出的目标进行自己的分析。
对我来说幸运的是,Cronometer 可以让我在他们的网站上轻松地将数据导出到 .csv 文件。
在本章中,我们将仅导出“食物和食谱条目”数据集。
我们首先检查从“食物和食谱条目”获得的数据。该数据集非常全面,我相信这对未来的章节非常有用!在本章中,我们确实希望将其限制为食物的名称、含量、蛋白质、卡路里和纤维。
# 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))
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中文网其他相关文章!