Nutrient Content of Foods by Food Types: A Visual Journey with FAO Data

infoart.ca
4 min readDec 9, 2023

--

Photo by Lee Myungseong on Unsplash

As an amateur nutritionist, I always feel the urge to keep a visual of the nutrient content of foods at the back of my head. This is crucial for making informed dietary choices and maintaining a healthy lifestyle.

In this blog post, we will explore the Food Composition Tables, which provide detailed information about the nutrient content of various foods. Specifically, we will focus on the retail weight per 100 grams of each food item.

To bring this data to life, we will leverage the power of the ggplot2 library in R to create visually appealing and informative plots. Our goal is to compare the caloric (kcal), protein and fat content of different food items across various food groups.

Data source: https://www.fao.org/3/X9892E/X9892e05.htm

Here is what the data looks like after hours of mining:

> df
# A tibble: 311 × 5
item kcal protein fat group
<chr> <int> <dbl> <dbl> <chr>
1 wheat 334 12.2 2.3 cereal
2 flour of wheat 364 10.9 1.1 cereal
3 bran of wheat 213 12.1 3.1 cereal
4 macaroni 367 11 1.1 cereal
5 germ of wheat 382 29.1 10.7 cereal
6 bread 249 8.2 1.2 cereal
7 bulgur wholemeal 345 12.3 2 cereal
8 pastry 369 7.4 17 cereal
9 wheat starch 362 0.5 0.3 cereal
10 wheat gluten 380 95 0 cereal
# ℹ 301 more rows
# ℹ Use `print(n = ...)` to see more rows

Plot 1: Kcal of Items by Group

library(ggplot2)

ggplot(df, aes(x = reorder(item, -kcal), y = kcal, fill = group)) +
geom_bar(stat = "identity", width = 0.7) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(title = "Kcal of Items by Group", x = "Item", y = "Kcal") +
facet_wrap(~group, scales = "free", ncol =2)

The chart is obviously a content-heavy one. Not the best of the looks so lets try flipping the coordinates:

ggplot(df, aes(x = reorder(item, -kcal), y = kcal, fill = group)) +
geom_bar(stat = "identity", width = 0.7) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(title = "Kcal of Items by Group", x = "Item", y = "Kcal") +
facet_wrap(~group, scales = "free", ncol =2)+ coord_flip()

Still not an easy one to read, some of the food groups have far more members than the chart can accommodate without overlapping the labels. So let’s stick with the first one.

Plot 2: Protein content of Items by Group

ggplot(df, aes(x = reorder(item, -protein), y = protein, fill = group)) +
geom_bar(stat = "identity", width = 0.7) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
facet_wrap(~group, scales = "free", ncol =2)

Plot 3: fat content of items by Group

ggplot(nn, aes(x = reorder(item, -fat), y = fat, fill = group)) +
geom_bar(stat = "identity", width = 0.7) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
facet_wrap(~group, scales = "free", ncol =2)

Plot 4: Comparison of calory, protein and fat content by groups

df %>%
gather(nutrient, value, -item, -group) %>%
ggplot(aes(x = reorder(item, -value), y = value, fill = nutrient)) +
geom_bar(stat = "identity", position = "dodge", width = 0.7) +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(title = "Nutrient Comparison by Item and Group", x = "Item", y = "Value") +
facet_wrap(~group, scales = "free")

World of calories!

Plot 4: Cereals with above and below-average fat content.

  df %>%  
filter(group == 'cereal') %>%
ggplot(aes(
x = reorder(item, -protein),
y = ifelse(protein >= mean(protein), protein, -protein),
fill = ifelse(protein >= mean(protein), "≥mean", "<mean")
)) +
geom_col(width = 0.7) + labs(x='', y='/100 grams') +
coord_flip() +
scale_fill_manual(values = c("<mean" = "#F0BD70", "≥mean" = "#43938A"), name = "Legend Title")+
theme(panel.grid = element_blank(),
panel.background = element_blank(),
plot.background = element_rect(fill = "white"), legend.title = element_blank(), legend.position = 'bottom') + geom_text(
aes(label = ifelse(protein >= mean(protein), round(protein, digits = 1), "")),
position = position_stack(vjust = 0.9),
color = "black"
) +
geom_text(
aes(label = ifelse(protein < mean(protein), round(protein, digits = 1), "")),
position = position_stack(vjust = -0.4),
color = "black"
) + lims(y=c(-20,100))+
theme(axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.ticks.y = element_blank())

Plot 5: Fish and fish products with above and below-average fat content.

Eat happily, friends, and stay nutritious!

--

--

infoart.ca
infoart.ca

Written by infoart.ca

Center for Social Capital & Environmental Research | Posts by Bishwajit Ghose, BI consultant and lecturer at the University of Ottawa

Responses (1)