Nutrient Content of Foods by Food Types: A Visual Journey with FAO Data
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!