Starting a new R Shiny app
In RStudio, go to File > New File > Shiny Web App
. Name your application, save it in your desired directory, and just for this tutorial, save it as a single file (app.R).
You now have a sample R Shiny app to customize and make your own! Notice that the basic anatomy of an R Shiny app is represented here with the ui, server, and runApp function. Notice also that there are some additional inputs and outputs like a sliding input and histogram plot output. In our app, we’ll make inputs and outputs similar to these.
Load the packages into the very top of the shiny app.
# If you don't have one of these packages,
# install the package by typing install.packages("package") into the Console.
library(shiny)
library(ggplot2)
library(dplyr)
library(leaflet)
library(lubridate)
library(RColorBrewer)
library(plotly)
library(DT)
library(shinythemes)
Load the data into the shiny app.
Copy over the NASA fireballs dataset into the same directory as your Shiny app.
Load the NASA fireballs dataset below the loaded packages and above the ui and server components so that the data can be used in both.
load("nasa_fireball.rda")
Best Practice: Have your data saved as a .rda file, since it takes up less space in R and ultimately makes your shiny app faster.
Data Manipulation and UI/Server Customization
# load("nasa_fireball.rda") # commented here to show placement
nasa_fireball$year <- as.numeric(year(nasa_fireball$date)) # add a new column to nasa_fireball with the year of each observation (with lubridate)
pal <- colorFactor("Oranges", nasa_fireball$year) # color palette funct. for leaflet; allows map to show diff. shades of orange for each year
# "Oranges" is a palette in the "RColorBrewer" package
# Define UI
ui <- fluidPage(
# Sidebar layout with a input and output definitions
sidebarLayout(
# Inputs
sidebarPanel(
## Scatterplot
# Select variable for y-axis
selectInput(inputId = "y", # input Id to match with output that depends on this input widget
label = "Y-axis:", # label above this input widget in the sidebar
choices = c("energy", "impact_e", "alt", "vel"), # choices available for users to pick from
selected = "alt"), # selected = default selection; Watch for commas!
# Select variable for x-axis
selectInput(inputId = "x",
label = "X-axis:",
choices = c("energy", "impact_e", "alt", "vel"),
selected = "vel"), # Watch for commas!
# Select variable for color
selectInput(inputId = "z",
label = "Color by:",
choices = c("lat_dir","lon_dir"),
selected = "lat_dir")
),
# Outputs
mainPanel( # add outputs to the ui defining where they should be
leafletOutput(outputId = "leaflet_map"), # display the leaflet_map object
plotOutput(outputId = "scatterplot") # display the scatterplot object
)
)
)
# Define server logic
server <- function(input, output) {
# Create the leaflet_map object the leafletOutput function is expecting
output$leaflet_map <- renderLeaflet({ # uses nasa_fireball data
leaflet(data = nasa_fireball, options = leafletOptions(worldCopyJump = T)) %>% # worldCopyJump = T ensures no jumps when moving around the world
fitBounds(lng1 = -124.7844079, # coordinate bounds for continental US; centers the map on the continental US
lat1 = 49.3457868,
lng2 = -66.9513812,
lat2 = 24.7433195) %>%
addTiles() %>% # customize style of map
addCircleMarkers(lng = ~lon, # add circle markers for each fireball, plotting them at longitude and latitude coordinates
lat = ~lat,
popup = paste("Year:", nasa_fireball$year, "<br>", # display year, lat, lon, energy when circle marker is clicked
"Latitude:", nasa_fireball$lat, "<br>",
"Longitude:", nasa_fireball$lon, "<br>",
"Energy:", nasa_fireball$energy),
radius = ~sqrt(energy), # size of each circle marker is the square root of its energy level
color = ~pal(year)) # color of each circle is dependent on the pal function defined at the top (with RColorBrewer)
})
# Create the scatterplot object the plotOutput function is expecting
output$scatterplot <- renderPlot({ # uses nasa_fireball data
ggplot(data = nasa_fireball, aes_string(x = input$x, y = input$y, # x, y, and color layers of the plot depend on user input
color = input$z)) +
geom_point() # add points based on inputs x, y, and color to the plot
})
}
Best practice: Always make sure your object that you want to show in your Shiny app is in both your ui and server objects.
If it’s not in both, it won’t be displayed.
Question for the Audience!
Which of the following is not true about server functions?
Input values should be referred to as input$*
Objects to be displayed should be saved to output$*
Reactive outputs should be built with render*()
functions
Server functions should include a call to runApp()
Extend the UI Further
Let’s extend the UI further to add some additional ease for the user and interactivity with the scatterplot (ggplot).
Integrate plotly
to make the ggplot interactive
In the ui mainPanel, replace the function plotOutput
with plotlyOutput
. Also, in the server, replace renderPlot()
with renderPlotly()
.
In the same place in the server, assign the ggplot to the variable orig_ggplot
and plotly-ify this ggplot by typing ggplotly(orig_ggplot)
. Your server output$scatterplot
should look like this:
# Create the scatterplot object the plotlyOutput function is expecting
output$scatterplot <- renderPlotly({
orig_ggplot <- ggplot(data = nasa_fireball_reactive(), aes_string(x = input$x, y = input$y,
color = input$z)) + geom_point()
ggplotly(orig_ggplot)
})