Visualizing COVID-19 Mobility with Shiny
Create an Interactive Shiny App for Urban Data
I made an interactive app to explore residents’ COVID-19 mobility for cities in Spain and the UK. It’s fairly simple as it is a learning example but you can add countries worldwide. The data is available by Google. It proves that Shiny is handy, fast, interactive and flexible in both R and Python. Take a look at the app here.
In the following, I explain how you can create a Shiny App for big data. It is also useful when you want to make data dashboards.
1. Simple Structure
The Shiny library simplifies the process of transforming analyses into interactive web applications, eliminating the need for expertise in HTML, CSS, or JavaScript. A Shiny app comprises a user interface (UI) and a server. The UI defines visual elements like scatter plots and dropdown menus, while the server implements the app’s logic, linking inputs to outputs. Next, we will delve into detailing the contents of the UI and server sections.
2. Set the Stage
First, load libraries and data:
library(shiny)
library(plotly)
library(DT)
data <- read.csv("data/Spain_UrbanMobility_Covid19.csv")
Also, specify types of data. When R knows about data type, it reacts better:
data$date <- as.Date(data$date)
data$region <- as.factor(data$region)
I defined some variables and set default variables:
colnames(data) <- c("country", "region", "sub_region", "date", "retail_recreation", "grocery_pharmacy", "parks", "transit_stations", "workplaces", "residential")
default_country <- "Spain"
default_region <- "Total"
3. User Interface
The app has a left sidebarPanel() for selecting countries, categories, regions, date ranges, and a download button. Shiny supports various control widgets such as dropdown menus and sliders, each with unique input IDs and labels.
On the right side, the mainPanel() is for interactive plots. To turn static plots into interactive ones, it uses plotlyOutput with DT::dataTableOutput(). Working with interactive tables is more fun and informative; it enhances user engagement and data exploration capabilities.
ui <- fluidPage(
titlePanel("COVID-19 Urban Mobility Data"),
sidebarLayout(
sidebarPanel(
selectInput("country", "Select Country:", choices = unique(data$country), selected = default_country),
selectInput("region",
"Select Region:",
choices = unique(data$region),
selected = default_region,
multiple = TRUE),
selectInput("category", "Select Category:", choices = c("retail_recreation", "grocery_pharmacy", "parks", "transit_stations", "workplaces", "residential")),
dateRangeInput("dates", "Select Date Range:", start = min(data$date), end = max(data$date)),
downloadButton("downloadData", "Download Data")
),
mainPanel(
plotlyOutput("dataPlot"),
dataTableOutput("dataTable")
)
)
)
3. Server Functions
The server function manages input and output parameters. The user selects or filters data like input$country, and the server starts processing. When the user changes buttons or droplists, the input variables are re-evaluated to ensure real-time updates in plots and tables.
With ggplot, R make plots with customized axes and colour categories. There are various types of plots for dynamic visualization of mobility trends; for example, ggplot2 is an improved and more advanced version of ggplot. Finally, I like to give users more space to export CSV files for further analysis.
# Define server logic
server <- function(input, output, session) {
# Update regions based on selected country
observeEvent(input$country, {
updateSelectInput(session, "region", choices = unique(data[data$country == input$country, "region"]), selected = default_region)
})
filteredData <- reactive({
subset(data, country == input$country & region %in% input$region &
date >= input$dates[1] & date <= input$dates[2])
})
output$dataPlot <- renderPlotly({
p <- ggplot(filteredData(), aes_string(x = "date", y = input$category, color = "region")) +
geom_point(alpha = 0.5) + theme(legend.position = "none") +
ylab("% change from baseline")
ggplotly(p)
})
output$dataTable <- DT::renderDataTable({
filteredData()
})
# Download Data
output$downloadData <- downloadHandler(
filename = "download_data.csv",
content = function(file) {
data <- filteredData()
write.csv(data, file, row.names = FALSE)
}
)
}
# Run the application
shinyApp(ui = ui, server = server)
Remember when the user changes countries, it automatically updates regions. It is about observeEvent.
observeEvent(input$country, {
updateSelectInput(session, "region", choices = unique(data[data$country == input$country, "region"]), selected = default_region)
})
4. Source Code in Interactive Dashboards 2024
I keep my code on Github so you can easily access it. Also, I made a folder for more Interactive Dashboards.
You can simply create your Shiny app and make it online. To share your app online, simply use the “Publish” feature in the RStudio window and follow the steps.
5. Dealing with Big Data in Shiny
To make a modest app, I only used Spain and the UK data but it is possible to have any other countries that you like. When handling large datasets in Shiny apps, consider optimizing data loading processes by using efficient data structures and implementing server-side processing techniques to enhance performance.
Here is a sample server-side optimization.
# Define the server logic
server <- function(input, output) {
# Render the large dataset table using server-side processing
output$large_table <- renderDataTable({
datatable(
large_data,
options = list(
server = TRUE, # Enable server-side processing
processing = TRUE,
searching = TRUE,
paging = TRUE,
lengthMenu = c(10, 25, 50, 100),
pageLength = 10
)
)
})
}
Finally …
Creating interactive Shiny apps for exploring COVID-19 mobility data offers valuable insights for public health and urban planning initiatives. By leveraging Shiny’s capabilities in visualizing complex datasets and engaging users interactively, we can drive informed decision-making processes amidst evolving mobility trends during the pandemic.
The interactive app is great for data-driven planning and decision making.
I am Hassan, an urban planner with a passion for data analysis. I invite you to follow me for more updates and insights into the intersection of #datascience, #python, #machinelearning, and #urbanplanning.
Let’s learn and grow together! 🌟