Automating Meal Planning (Progress Update)

Mon, Sep 14, 2020 3-minute read 494 words

Some quick update on my progress with building decision support system for meal planning in R.

Last year I shared some thoughts on building an automated system for planning my monthly meals. The work is still in progress, but in this post I describe the process and share some code in its current state.

Step 1: Library

I started with a library of recipes (currently 26 meals) which I keep in CSV format for easy editing. Eventually I will share the actual data file, in the meantime here is a quick preview of its layout and contents:

meal planning input data

For meals, I list prep time (in minutes), and taste score (1=hate it, 5= love it). For ingredients, I include cost (for now this column is populated with dummy data), measures (to make 3 meals), and binary flags for gluten and lactose intake of which I am trying to minimize.

Step 2: Selection

From my experiments in the past I learned that I can eat the same meal no more than 3 times in a row. After that, my chances of getting acid reflux increase, and taste gratification drops considerably. So I can get away with 4 different recipes a week (Monday-Saturday), each recipe eaten 3 times. On Sundays I tend to eat out or order take outs.

To select 16 recipes, system assigns a unique random number between 1 and 26 to each meal in the library. The RNG seed is tied to the current month so a new set is generated every month. I then retain the first 16 selections and distribute them across four weeks:

library(tidyverse)
library(lubridate)
rawrec<-read.csv("./DATAIN/recipes.csv",header=T,stringsAsFactors = F)
as_tibble(rawrec)
#RNG seed is updated every month
set.seed(month(today()))
#generating menu for 4 weeks
menu<-rawrec %>% distinct(meal) %>%  
    mutate(sel=sample(1:26,n(),replace=FALSE))%>% 
    filter(sel<=16) %>% 
    mutate(week=as.integer((sel-1)/4)+1)%>%
    select(week,meal) %>% 
    arrange(week)

Step 3: Output

The monthly menu is generated along with stats for each meal:

menu generated by meal planner

Additionally, a list of ingredients is produced that can be used for grocery shopping:

inredients generated by meal planner

Step 4: Diagnostics

A simple diagnosics snippet built into the code provides a quick stats summary for each week:

weeks<-menu %>% group_by(week) %>% 
    summarise(cost=sum(cost),
              prep=round(sum(prep)/60,digits=1),
              taste=mean(taste),
              gluten=sum(gluten),
              lactose=sum(lactose))

It revealed some issues with the very first monthly selection:

diagnostics generated by meal planner

As you can see, the second week’s menu has too many meals that contain gluten and lactose. Ideally, I would want to have no more than one such meal per week.

Also, the third week’s total cooking time is too high, and the fourth week’s average taste score is too low. I may need to set some constraints around these parameters too.

Next Steps

It looks like I need to adjust the selection process to ensure more uniform distribution of nutrition stats, cooking time and taste. I also need to account for the fact that months have more than 4 weeks.

Finally, I will need a mechanism for exporting and delivering the weekly menus and grocery lists. Most likely, I will use sendmailR package to deliver results by email. Stay tuned for more updates!