Hey everyone. I found no way to make slidify to work on Rpubs or Github (doesn’t help that there is no course on slidify…) so I gave up and here’s the pitch in a format that works : an HTML presentation !
Here’s a quick slide presentation on how I built my visual BMI calculator app which can be found here :
We’ll go through the following steps :
The GGPLOT background
The UI code
The server code
Here’s the code for the ggplot background. I create a data frame for my BMI 16.5 to BMI 40 lines, then plot them.
After that, I plot the colored intervals with the geom_ribbon functions.
Finally, I add the text with geom_text and I manually set the positions and the slight angle
BMI <- data.frame(height = c(130:220), weight = c(40:130))
BMI <- BMI %>% mutate(bmi16.5 = 16.5 * (height*0.01)**2,
bmi18.5 = 18.5 * (height*0.01)**2,
bmi25 = 25 * (height*0.01)**2,
bmi30 = 30 * (height*0.01)**2,
bmi35 = 35 * (height*0.01)**2,
bmi40 = 40 * (height*0.01)**2,
)
g <- ggplot(data = data.frame(height = c(130 : 220), weight = c(40 : 130)),
aes(x = height, y = weight))
g <- g + geom_line(data = BMI, aes(x = height, y = bmi16.5), size = 1.2) +
geom_line(data = BMI, aes(x = height, y = bmi18.5), size = 1.2) +
geom_line(data = BMI, aes(x = height, y = bmi25), size = 1.2) +
geom_line(data = BMI, aes(x = height, y = bmi30), size = 1.2) +
geom_line(data = BMI, aes(x = height, y = bmi35), size = 1.2) +
geom_line(data = BMI, aes(x = height, y = bmi40), size = 1.2)
g <- g + geom_ribbon(aes(ymin = 0, ymax = BMI$bmi16.5), fill = "lightblue", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi16.5, ymax = BMI$bmi18.5), fill = "blue", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi18.5, ymax = BMI$bmi25), fill = "white", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi25, ymax = BMI$bmi30), fill = "yellow", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi30, ymax = BMI$bmi35), fill = "orange", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi35, ymax = BMI$bmi40), fill = "orange4", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi40, ymax = Inf), fill = "salmon", alpha = 0.5)
g <- g + geom_text(x = 175, y = 30, label = "Severely Underweight", angle = 11) +
geom_text(x = 175, y = 54, label = "Underweight", angle = 11) +
geom_text(x = 175, y = 66, label = "Normal", angle = 11) +
geom_text(x = 175, y = 84, label = "Overweight", angle = 11) +
geom_text(x = 175, y = 99, label = "Highly Overweight", angle = 11) +
geom_text(x = 175, y = 115, label = "Obese", angle = 11) +
geom_text(x = 175, y = 160, label = "Severely Obese", angle = 11)
This code will require to load both the dplyr and ggplot2 packages. We have to remember to include the package load in the server code
The UI code is pretty straight forward :
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("Visual BMI Calculator"),
# Sidebar config
sidebarLayout(
sidebarPanel(
h2("Please enter your data here :"),
numericInput("heightvar",
"What is your height (in cm) ?",
min = 130,
max = 220,
value = 180),
numericInput("weightvar",
"How much do you weigh (in kg) ?",
min = 0,
max = 200,
value = 80),
h2(""),
h1("Unit Conversion"),
br("If you know your measurements in non metric units,
insert them here for conversion : "),
br("Please insert below your height in feet and inches \n"),
br("-"),
numericInput("heightft",
"feet :",
min = 0,
max = 10,
value = 0),
numericInput("heightin",
"inches :",
min = 0,
max = 11,
value = 0),
br("Please insert below your weight in lbs"),
br("-"),
numericInput("weightlbs",
"How much do you weigh (in lbs) ?",
min = 0,
max = 800,
value = 0),
h1(""),
br("Your measurements in metric are :"),
em("height in cm : "),
textOutput("htincm"),
em("Weight in kg : "),
textOutput("wtinkg")
),
# Main Panel with text and plot outputs
mainPanel(
h3("Your BMI is :"),
textOutput("bmivalue"),
textOutput("bmiccl"),
plotOutput("bmiplot")
)
)
))
The server code manipulates the inputs a lot, so we mainly use reactive expressions
#
# This is the server logic of a Shiny web application. You can run the
# application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
library(shiny)
shinyServer(function(input, output) {
# Extract main values. Set to 0 if input is empty
heightvar <- reactive({
if (is.na(input$heightvar)){0}
else {as.numeric(input$heightvar)}
})
weightvar <- reactive({
if (is.na(input$weightvar)){0}
else {as.numeric(input$weightvar)}
})
# Calculate BMI value
bmival <- reactive({
round(weightvar() / ((0.01*heightvar())**2),2)
})
# Create "bmivalue" output
output$bmivalue = renderText(bmival())
# Create "bmiccl" output that depends on the user's BMI
output$bmiccl = renderText(
if (bmival() < 16.5) {print("You are severly underweight")}
else if (bmival() < 18.5) {print("You are underweight")}
else if (bmival() < 25) {print("Your weight is normal")}
else if (bmival() < 30) {print("You are overweight")}
else if (bmival() < 35) {print("You are highly overweight")}
else if (bmival() < 40) {print("You are obese")}
else {print("You are severly obese")}
)
# UNIT CONVERSION PANEL
# Extract values and set to 0 if input is empty
wtlbs <- reactive({
if (is.na(input$weightlbs)){0}
else {input$weightlbs}
})
htft <- reactive({
if (is.na(input$heightft)){0}
else {input$heightft}
})
htin <- reactive({
if (is.na(input$heightin)){0}
else {input$heightin}
})
# Create output : converted measurements, NULL if empty or = 0
# NULL output = results don't appear = cleaner UI
output$wtinkg = reactive({
if (wtlbs() == 0){NULL}
else {round(wtlbs() * 0.453592, 1)}
})
output$htincm = reactive({
if (htft() + htin() == 0){NULL}
else {round((htft() * 12 + htin()) * 2.54, 1)}
})
# Create plot output
output$bmiplot <- renderPlot({
# GGPLOT BACKGROUND :
library(dplyr)
library(ggplot2)
BMI <- data.frame(height = c(130:220), weight = c(40:130))
BMI <- BMI %>% mutate(bmi16.5 = 16.5 * (height*0.01)**2,
bmi18.5 = 18.5 * (height*0.01)**2,
bmi25 = 25 * (height*0.01)**2,
bmi30 = 30 * (height*0.01)**2,
bmi35 = 35 * (height*0.01)**2,
bmi40 = 40 * (height*0.01)**2,
)
g <- ggplot(data = data.frame(height = c(130 : 220), weight = c(40 : 130)),
aes(x = height, y = weight))
g <- g + geom_line(data = BMI, aes(x = height, y = bmi16.5), size = 1.2) +
geom_line(data = BMI, aes(x = height, y = bmi18.5), size = 1.2) +
geom_line(data = BMI, aes(x = height, y = bmi25), size = 1.2) +
geom_line(data = BMI, aes(x = height, y = bmi30), size = 1.2) +
geom_line(data = BMI, aes(x = height, y = bmi35), size = 1.2) +
geom_line(data = BMI, aes(x = height, y = bmi40), size = 1.2)
g <- g + geom_ribbon(aes(ymin = 0, ymax = BMI$bmi16.5), fill = "lightblue", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi16.5, ymax = BMI$bmi18.5), fill = "blue", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi18.5, ymax = BMI$bmi25), fill = "white", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi25, ymax = BMI$bmi30), fill = "yellow", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi30, ymax = BMI$bmi35), fill = "orange", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi35, ymax = BMI$bmi40), fill = "orange4", alpha = 0.5) +
geom_ribbon(aes(ymin = BMI$bmi40, ymax = Inf), fill = "salmon", alpha = 0.5)
g <- g + geom_text(x = 175, y = 30, label = "Severely Underweight", angle = 11) +
geom_text(x = 175, y = 54, label = "Underweight", angle = 11) +
geom_text(x = 175, y = 66, label = "Normal", angle = 11) +
geom_text(x = 175, y = 84, label = "Overweight", angle = 11) +
geom_text(x = 175, y = 99, label = "Highly Overweight", angle = 11) +
geom_text(x = 175, y = 115, label = "Obese", angle = 11) +
geom_text(x = 175, y = 160, label = "Severely Obese", angle = 11)
# Add user input to GGPLOT background and print the final GGPLOT :
g <- g + geom_point(x = heightvar(), y = weightvar(), colour = "red", size = 5, shape = 4, stroke = 2)
g
})
})