Recipe Complexity Analysis

Exploring relationships in a large recipe dataset

VAISHNAVI REDDY TUDI (s4196984)

Last updated: 18 October, 2025

Introduction

Introduction Cont.

Problem Statement

Data

# Set your file path if it's saved elsewhere
data_path <- "1_Recipe_csv (1).csv"

# Read CSV (base R to avoid extra dependencies)
recipes <- read.csv(data_path, stringsAsFactors = FALSE)

# Basic checks
dim(recipes)
## [1] 62126     8
head(recipes)

Data Cont.

recipes$category    <- factor(recipes$category)
recipes$subcategory <- factor(recipes$subcategory)

sapply(recipes[, c("num_ingredients", "num_steps")], function(x) c(
  class = class(x),
  min   = min(x, na.rm = TRUE),
  mean  = mean(x, na.rm = TRUE),
  median= median(x, na.rm = TRUE),
  max   = max(x, na.rm = TRUE),
  n_na  = sum(is.na(x))
))
##        num_ingredients    num_steps         
## class  "integer"          "integer"         
## min    "1"                "1"               
## mean   "9.01744841129318" "4.66186459775295"
## median "9"                "4"               
## max    "35"               "25"              
## n_na   "0"                "0"

Descriptive Statistics and Visualisation

par(mfrow = c(1,2))
hist(recipes$num_ingredients, main = "Number of Ingredients", xlab = "Ingredients")
hist(recipes$num_steps,       main = "Number of Steps",       xlab = "Steps")

par(mfrow = c(1,1))

plot(num_steps ~ num_ingredients, data = recipes,
     main = "Steps vs Ingredients", xlab = "Num Ingredients", ylab = "Num Steps")
abline(lm(num_steps ~ num_ingredients, data = recipes), lwd = 2)

Descriptive Statistics Cont.

library(dplyr)

by_cat <- recipes %>%
  group_by(category) %>%
  summarise(
    n_recipes       = dplyr::n(),
    avg_ingredients = mean(num_ingredients, na.rm = TRUE),
    avg_steps       = mean(num_steps, na.rm = TRUE)
  ) %>%
  arrange(desc(n_recipes))

knitr::kable(head(by_cat, 15), caption = "Top 15 Categories by Count with Average Complexity")
Top 15 Categories by Count with Average Complexity
category n_recipes avg_ingredients avg_steps
Main Dishes 3387 10.421022 5.496605
Healthy Recipes 2237 7.724184 4.003129
Appetizers And Snacks 2084 7.903551 4.198656
Cakes 1954 9.615148 5.618219
Cookies 1849 8.843699 5.214711
Beef Recipes 1400 10.569286 5.130000
Breads 1352 9.116124 5.714497
Desserts 1288 7.242236 5.356367
Breakfast And Brunch 1223 8.147997 4.270646
Pork 1205 10.507054 5.139419
Mexican 1069 9.855940 4.405051
Christmas 1020 7.813726 5.514706
Vegetarian 968 9.703512 4.365703
Pies 954 7.848008 5.032495
Christmas Cookies 945 8.691005 5.200000

Visualisation: Top Categories

top10_cats <- by_cat %>% slice_max(n_recipes, n = 10) %>% pull(category)
top10_dat  <- recipes %>% filter(category %in% top10_cats)

bar_dat <- top10_dat %>%
  count(category) %>%
  arrange(desc(n))

barplot(height = bar_dat$n,
        names.arg = bar_dat$category,
        las = 2, cex.names = 0.8,
        main = "Top 10 Categories (Count of Recipes)",
        ylab = "Count")

Visualisation: Complexity by Category

top8_cats <- by_cat %>% slice_max(n_recipes, n = 8) %>% pull(category)
box_dat   <- recipes %>% filter(category %in% top8_cats)

# Base R boxplot to avoid extra dependencies
boxplot(num_steps ~ category, data = box_dat,
        las = 2, cex.axis = 0.8,
        main = "Recipe Steps by Category (Top 8 Categories)",
        xlab = "Category", ylab = "Number of Steps")

Hypothesis Testing

model1 <- lm(num_steps ~ num_ingredients, data = recipes)
summary(model1)
## 
## Call:
## lm(formula = num_steps ~ num_ingredients, data = recipes)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -5.0220 -1.5359 -0.2882  1.2164 20.7118 
## 
## Coefficients:
##                 Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     3.545060   0.023203  152.78   <2e-16 ***
## num_ingredients 0.123849   0.002368   52.29   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.261 on 62124 degrees of freedom
## Multiple R-squared:  0.04216,    Adjusted R-squared:  0.04215 
## F-statistic:  2735 on 1 and 62124 DF,  p-value: < 2.2e-16

Hypothesis Testing Cont.

recipes2 <- recipes
recipes2$category_limited <- ifelse(recipes2$category %in% top10_cats,
                                    as.character(recipes2$category), "Other")
recipes2$category_limited <- factor(recipes2$category_limited)

model2 <- lm(num_steps ~ num_ingredients + category_limited, data = recipes2)
summary(model2)
## 
## Call:
## lm(formula = num_steps ~ num_ingredients + category_limited, 
##     data = recipes2)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -5.0527 -1.5190 -0.2844  1.1991 20.8328 
## 
## Coefficients:
##                                      Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                           3.27169    0.05236  62.484  < 2e-16 ***
## num_ingredients                       0.11729    0.00237  49.478  < 2e-16 ***
## category_limitedBeef Recipes          0.61869    0.07739   7.995 1.32e-15 ***
## category_limitedBreads                1.37362    0.07800  17.611  < 2e-16 ***
## category_limitedBreakfast And Brunch  0.04332    0.08040   0.539  0.59003    
## category_limitedCakes                 1.21882    0.07040  17.312  < 2e-16 ***
## category_limitedCookies               0.90579    0.07134  12.696  < 2e-16 ***
## category_limitedDesserts              1.23527    0.07913  15.611  < 2e-16 ***
## category_limitedHealthy Recipes      -0.17449    0.06796  -2.568  0.01024 *  
## category_limitedMain Dishes           1.00269    0.06243  16.062  < 2e-16 ***
## category_limitedOther                 0.19176    0.05010   3.828  0.00013 ***
## category_limitedPork                  0.63541    0.08101   7.843 4.46e-15 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.232 on 62114 degrees of freedom
## Multiple R-squared:  0.06673,    Adjusted R-squared:  0.06657 
## F-statistic: 403.8 on 11 and 62114 DF,  p-value: < 2.2e-16

Mathematical Equations (Examples)

Conclusion (Take‑Home Message)

References