Plotting global BMI data in R

infoart.ca
3 min readFeb 10, 2024

--

Photo by Towfiqu barbhuiya on Unsplash

With the increasing prevalence of obesity and its associated health risks, analyzing and visualizing BMI data on a global scale has become essential.

In this blog post, we will explore how to leverage R to plot and visualize global BMI data to gain insights into worldwide health trends.

Plot 1: country-level differences in BMI in 2015

Here are the steps:

First, let’s load the libraries:

library(rvest)
library(dplyr)
library(rio)

Then extract the data from Wikipedia on BMI, and do some cleaning work

df =  read_html("https://en.wikipedia.org/wiki/List_of_sovereign_states_by_body_mass_index")  %>%
html_nodes("table") %>%
.[[1]]%>%
html_table(fill=T) %>%
mutate(Country = gsub("[^A-Za-z[:space:]]", "", Country)) %>% rename_all(tolower) %>%
mutate_at(vars(2:4), as.numeric) %>%
inner_join(continent, by = "country")

And finally make the plot (reshaping is done to plot the data for both male and female)

df %>%
pivot_longer(cols = c(male, female), names_to = "gender", values_to = "percentage") %>%
filter(!is.na(percentage)) %>%
ggplot(aes(x = fct_reorder(country, percentage), y = percentage, fill = gender)) +
geom_bar(stat = "identity") +
labs(x = "", y = "Mean BMI (kg/m²)",caption='Data: WHO, 2015',
fill = "") +
scale_fill_manual(values = c("#85865F", "#CEB793"), labels = c("Female", "Male")) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, size = 7, hjust = 1), legend.position = 'bottom',
panel.grid = element_blank())

Plot 2: Mean BMI in the LICs (this time in lollipop flavour)


df %>%
filter(!is.na(both), incomeGrp=='Low income') %>%
ggplot(aes(x = fct_reorder(country, both), y = both)) +
geom_segment(aes(xend = fct_reorder(country, both), yend = 0), color = "#85865F") +
geom_point(size = 3, color = "#CEB793") +
labs(x = "", y = "Mean BMI (kg/m²) in the LICs", caption = 'Data: WHO, 2015',
fill = "") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, size = 7, hjust = 1),
legend.position = 'bottom',
panel.grid = element_blank())

Plot 3: Color coding the countries by continent

library(ggpubr)

df %>%
drop_na(both) %>%
ggbarplot(x = 'country', y = 'both',
fill = 'region',
color = 'white',
palette = c('#5F6F52', '#A9B388', '#234233', '#F9EBC7', '#B99470', '#C4661F', '#783D19'),
sort.val = 'asc',
sort.by.groups = TRUE,
x.text.angle = 90)+labs(x='', y='')+ theme(legend.title = element_blank(), legend.position = 'bottom')

Plot 4: Male-female difference in BMI among the countries

 
df %>% drop_na(male, female) %>%
mutate(diff = male - female) %>%
arrange(desc(diff)) %>%
ggplot(aes(x = reorder(country, diff), y = diff, fill = ifelse(diff >= 0, "Male > Female", "Male < Female"))) +
geom_col() +
scale_fill_manual(values = c("Male > Female" = "#85865F", "Male < Female" = "#CEB793")) +
labs(y = "", x = "Difference in BMI") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1), legend.title = element_blank(), panel.grid = element_blank(), panel.background = element_blank(), legend.position = 'bottom')

Plot 5: A global view

library(ggplot2)
library(dplyr)
library(viridis)
library(maps)
library(ggthemes)
library(ggmap)

ww %>%
left_join(df, by = 'region') %>%
ggplot(aes(long, lat, group = group, fill = both)) +
geom_polygon(color = "white") +
scale_fill_viridis_b(breaks = c(15, 20, 25, 30, 35),
na.value = "grey") +
labs(fill = "",
title = "Global distribution of BMI values",
na.value = "No data") +
theme_map() +
scale_alpha_manual(values = 1) +
guides(
fill = guide_colorsteps(order = 1),
alpha = guide_legend(order = 2, override.aes = list(fill = "grey")))

--

--

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

No responses yet