«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Отслеживание здоровья с помощью обработки данных — глава «Оптимизация питания»

Отслеживание здоровья с помощью обработки данных — глава «Оптимизация питания»

Опубликовано 7 августа 2024 г.
Просматривать:839

Введение

Всем привет! Это будет мой первый пост, так что будьте со мной суровы, критикуйте меня там, где, по вашему мнению, я могу улучшиться, и я обязательно приму это во внимание в следующий раз.

Последние несколько месяцев я серьезно занимался здоровьем, в основном занимаясь спортом и наблюдая за тем, что я ем, и теперь, когда я думаю, что получил твердое представление об этом, я хотел посмотреть, как я могу дополнительно оптимизировать на случай, если я что-то пропустил.

Цели

В этой главе я хотел бы изучить свое питание на протяжении всего пути к здоровью и завершить составлением плана питания на следующую неделю, который (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)

Для тех, у кого нет острого зрения, продолжайте прокручивать. Для тех, кто заметил эти жуткие две строки кода, позвольте мне объяснить. Я видел это, когда ходил в магазин за продуктами, но пищевая ценность буханки пшеничного изюма с высоким содержанием клетчатки Gardenia на самом деле не содержит 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 граммов клетчатки, мне нужно потратить 128 филиппинских песо на 269 граммов филе куриной грудки и 526 граммов маша. Это... звучит совсем неплохо, учитывая, как сильно я люблю оба ингредиента. Я обязательно попробую это, может быть, неделю или месяц, просто чтобы посмотреть, сколько денег я сэкономлю, несмотря на достаточное количество питания.

Это была глава «Отслеживание работоспособности с помощью обработки данных». Если вы хотите увидеть данные, над которыми я работал в этой главе, посетите репозиторий или зайдите в блокнот на этой странице. Оставьте комментарий, если он у вас есть, и постарайтесь оставаться здоровым.

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/wilyanse/tracking-health-with-data-engineering-chapter-1-meal-optimization-2cl7?1. В случае нарушения прав обращайтесь по адресу [email protected]. удалить его
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3