¡Hola a todos! Este será mi primer post así que sé duro conmigo, critícame en lo que creas que puedo mejorar y seguramente lo tendré en cuenta la próxima vez.
Durante los últimos meses, he estado profundamente preocupado por la salud, principalmente haciendo ejercicio y cuidando lo que como, y ahora que creo que lo tengo muy claro, quería ver cómo puedo optimizar aún más en el caso de que hay algunas cosas que quizás me haya perdido.
Para este capítulo, deseo estudiar mis comidas a lo largo de mi camino hacia la salud y concluir con un plan de alimentación para la próxima semana que (1) alcance mis requerimientos mínimos de proteínas, (2) no supere mi límite de calorías, (3) cumple con mis requisitos mínimos de fibra y (4) minimiza el costo.
Comenzamos presentando el conjunto de datos, los alimentos que hemos rastreado usando Cronometer. Cronometer ha estado trabajando conmigo lado a lado en mi viaje y ahora exportaré los datos que ingresé para analizarlos por mí mismo con los objetivos que he enumerado anteriormente.
Afortunadamente para mí, Cronometer me permite exportar datos a un archivo .csv con facilidad en su sitio web.
Para este capítulo, exportaremos solo el conjunto de datos 'Entradas de alimentos y recetas'.
Comenzamos examinando los datos que obtuvimos de 'Entradas de alimentos y recetas'. El conjunto de datos es muy completo, lo que estoy seguro será excelente para futuros capítulos. En este capítulo, queremos limitarlo al nombre del alimento, su cantidad, proteínas, calorías y fibra.
# Importing and checking out the dataset df = pd.read_csv("servings.csv") df.head()
Ya tenemos algunas columnas configuradas para nosotros, en 'Nombre del alimento', 'Cantidad', 'Energía (kcal)', 'Fibra (g)' y 'Proteína (g)'. ¡Perfecto! Ahora, lo único que nos falta es obtener el costo de cada alimento dada una cierta cantidad, ya que no se realiza un seguimiento en el conjunto de datos. Por suerte para mí, fui yo quien ingresó los datos en primer lugar para poder ingresar los precios que sí conozco. Sin embargo, no ingresaré los precios de todos los alimentos. En su lugar, le pedimos a nuestro buen amigo ChatGPT su estimación y completamos los precios que conocemos modificando el archivo .csv. Almacenamos el nuevo conjunto de datos en 'cost.csv' que obtuvimos tomando las columnas 'Nombre del alimento' y 'Cantidad' del conjunto de datos original.
# 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()
Algunos alimentos se eliminaron simplemente porque eran demasiado extrañamente específicos y no estarían en el alcance de los datos de ser bajos en calorías, nutritivos y/o baratos (o simplemente porque no podía molestarme en hacer la receta nuevamente). ). Luego necesitaríamos fusionar dos marcos de datos, el conjunto de datos original y el que tiene el costo, para obtener el supuesto conjunto de datos "final". Dado que el conjunto de datos original contiene las entradas de cada alimento, esto significa que el conjunto de datos original tiene varias entradas del mismo alimento, especialmente aquellos que como repetidamente (es decir, huevos, pechuga de pollo, arroz). También queremos llenar las columnas sin valores con '0', ya que la fuente más probable de problemas aquí serían las columnas 'Energía', 'Fibra', 'Proteína' y 'Precio'.
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()
¡Perfecto! Nuestro conjunto de datos está terminado y ahora comenzamos con la segunda parte, la optimización. Recordando los objetivos del estudio, queremos identificar el menor coste con una cantidad mínima de proteínas y fibra, y una cantidad máxima de calorías. La opción aquí es aplicar fuerza bruta en cada combinación, pero en la industria el término adecuado es "Programación lineal" u "Optimización lineal", pero no me cite sobre eso. Esta vez usaremos puLP, que es una biblioteca de Python cuyo objetivo es hacer exactamente eso. No sé mucho sobre su uso además de seguir la plantilla, así que explore su documentación en lugar de leer mi explicación poco profesional de cómo funciona. Pero para aquellos que quieran escuchar mi explicación informal del tema, básicamente estamos resolviendo y = ax1 bx2 cx3 ... zxn.
La plantilla que seguiremos es la plantilla para el estudio de caso del problema de Mezcla, donde seguimos objetivos similares pero en este caso, queremos mezclar nuestras comidas a lo largo del día. Para comenzar, necesitaríamos convertir el DataFrame en diccionarios, específicamente, el 'Nombre del alimento' como una lista de variables independientes que sirven como una serie de x, luego Energía, Fibra, Proteína y Precio como un diccionario tal que 'Nombre del alimento': valor de cada uno. Tenga en cuenta que la Cantidad se eliminará de ahora en adelante y, en su lugar, se concatenará con el 'Nombre del alimento', ya que no lo usaremos cuantitativamente.
# 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)
Para aquellos que no tienen buena vista, continúen desplazándose. Para aquellos que notaron las espeluznantes 2 líneas de código, permítanme explicarles. Vi esto mientras estaba comprando comestibles, pero la información nutricional del pan de trigo y pasas con alto contenido de fibra de Gardenia en realidad no tiene 1 rebanada por 9 gramos de fibra, tiene 2 rebanadas por 6 gramos. Esto es un gran problema y me ha causado un dolor inconmensurable al saber que los valores pueden ser incorrectos debido a una introducción incorrecta de los datos o a un cambio de ingredientes que provocó que los datos quedaran desactualizados. De cualquier manera, necesitaba que se corrigiera esta justicia y no toleraré menos Fibra de la que merezco. Hacia adelante.
Pasamos directamente a ingresar nuestros valores usando la plantilla de los datos del estudio de caso. Establecemos variables para representar los valores mínimos que queremos de proteína y fibra, así como las calorías máximas que estamos dispuestos a consumir. Luego, dejamos que el código de la plantilla mágica haga su trabajo y obtenga los resultados.
# 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))
Para obtener 120 gramos de proteína y 40 gramos de fibra, necesitaría gastar 128 pesos filipinos en 269 gramos de filete de pechuga de pollo y 526 gramos de frijoles mungo. Esto... no suena nada mal considerando lo mucho que amo ambos ingredientes. Definitivamente lo probaré, tal vez durante una semana o un mes, solo para ver cuánto dinero ahorraría a pesar de tener la nutrición suficiente.
Eso fue todo para este capítulo de Seguimiento del estado con ingeniería de datos. Si desea ver los datos en los que trabajé en este capítulo, visite el repositorio o visite el cuaderno de esta página. Deje un comentario si tiene alguno y trate de mantenerse saludable.
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3