Disclaimer:
The examples and code snippets in this tutorial are adapted from the official Shiny tutorial by Posit (formerly RStudio). Full credit goes to the original authors โ this walkthrough simply restructures and supplements their content for a smoother, section-wise learning experience.
Packages required
# Load Required Libraries
library(shiny)
library(leaflet)
library(DT)
# Define the User Interface (UI)
ui <- fluidPage(
titlePanel("Upload and View CSV File"),
sidebarLayout(
sidebarPanel(
fileInput(inputId = "filedata",
label = "Upload data (CSV file)",
accept = c(".csv"))
),
mainPanel(
DTOutput("table")
)
)
)
# Define the Server Logic
server <- function(input, output) {
data <- reactive({
req(input$filedata) # Ensure file is uploaded
read.csv(input$filedata$datapath)
})
output$table <- renderDT({
datatable(data())
})
}
# Run the Shiny App
shinyApp(ui = ui, server = server)To demonstrate this section, a small dataset was created using a few latitude and longitude points around the Athens campus.
# Load Required Libraries
library(shiny)
library(leaflet)
library(DT)
# ---- Sample Data ----
default_data <- data.frame(
name = c("Point A", "Point B", "Point C"),
lat = c(28.5383, 34.0522, 40.7128),
lon = c(-81.3792, -118.2437, -74.0060)
)
# Step 2: Define the User Interface (UI)
# ---- UI ----
ui <- fluidPage(
titlePanel("Basic Leaflet Map in Shiny"),
sidebarLayout(
sidebarPanel(
fileInput("file", "Upload CSV with lat/lon", accept = ".csv"),
helpText("CSV should have columns: 'lat', 'lon', and optional 'name'"),
br(),
DTOutput("table") # <- Table goes here
),
mainPanel(
leafletOutput("map", height = 500)
)
)
)
# ---- Server ----
server <- function(input, output, session) {
# Load data: use uploaded file or default
data_reactive <- reactive({
if (is.null(input$file)) {
default_data
} else {
read.csv(input$file$datapath)
}
})
# Render map
output$map <- renderLeaflet({
df <- data_reactive()
req(df$lat, df$lon)
leaflet(df) %>%
addTiles() %>% # Add default OpenStreetMap tiles
addCircleMarkers(
lng = ~lon,
lat = ~lat,
label = ~name,
radius = 6,
color = "blue",
fillOpacity = 0.7
)
})
# Render scrollable table
output$table <- renderDT({
datatable(data_reactive(), options = list(scrollX = TRUE, pageLength = 5))
})
}
# ---- Run App ----
shinyApp(ui = ui, server = server)This section is inspired by Paula Moragaโs excellent book Geospatial Health Data: Modeling and Visualization with R-INLA and Shiny (2019), published by Chapman & Hall/CRC Biostatistics Series. An online version of the book, along with Shiny code examples, is available here.
The accompanying datasets can also be accessed via the authorโs GitHub repository.
# Load Required Libraries
library(shiny)
library(sf)
library(DT)
library(leaflet)
# Define the User Interface (UI)
ui <- fluidPage(
titlePanel("Upload and View Shapefile"),
sidebarLayout(
sidebarPanel(
fileInput(
inputId = "filemap",
label = "Upload shapefile (select all related files)",
multiple = TRUE,
accept = c('.shp','.dbf','.sbn','.sbx','.shx','.prj')
)
),
mainPanel(
leafletOutput("map", height = 400),
DTOutput("table")
)
)
)
# Define the Server Logic
server <- function(input, output) {
map <- reactive({
req(input$filemap)
shpdf <- input$filemap
tempdirname <- dirname(shpdf$datapath[1])
# Rename files to original names
for (i in 1:nrow(shpdf)) {
file.rename(shpdf$datapath[i],
file.path(tempdirname, shpdf$name[i]))
}
# Get the .shp file path
shp_file <- shpdf$name[grep("\\.shp$", shpdf$name)]
req(length(shp_file) == 1)
# Read shapefile using sf
sf::st_read(file.path(tempdirname, shp_file))
})
output$table <- renderDT({
req(map())
datatable(map())
})
output$map <- renderLeaflet({
req(map())
leaflet() %>%
addTiles() %>%
addPolygons(data = map(), weight = 1, color = "#444444", fillOpacity = 0.5)
})
}
# Run the App
shinyApp(ui = ui, server = server)This section too is inspired by Paula Moragaโs excellent book Geospatial Health Data: Modeling and Visualization with R-INLA and Shiny (2019), published by Chapman & Hall/CRC Biostatistics Series. An online version of the book, along with Shiny code examples, is available here. The dataset used in this section is the same as in Section 3.
#Load Required Libraries
library(shiny)
library(leaflet)
library(rgdal)
library(DT)
# Load the data
data <- read.csv("data/Ohio/dataohiocomplete.csv")
map <- readOGR(dsn = "data/Ohio/fe_2007_39_county",layer = "fe_2007_39_county")
# Define UI
ui <- fluidPage(
titlePanel("Advanced Map of Cases (1980)"),
leafletOutput("map", height = 600),
DTOutput("table")
)
# Define Server
server <- function(input, output) {
output$map <- renderLeaflet({
# Filter for year 1980
data1980 <- subset(data, year == 1980)
# Create new columns for clarity
data1980$cases <- data1980$y
data1980$county_name <- tolower(trimws(data1980$NAME))
map_names <- tolower(trimws(map@data$NAME))
# Match counties by name
ordercounties <- match(map_names, data1980$county_name)
matched <- !is.na(ordercounties)
if (sum(matched) == 0) {
showNotification("No matching counties found between data and shapefile", type = "error")
return(NULL)
}
map <- map[matched, ]
map@data <- data1980[ordercounties[matched], ]
# Create color palette
pal <- colorBin("YlOrRd", domain = map@data$cases, bins = 7)
# Labels for interactivity
labels <- lapply(
paste0(map@data$NAME, "<br>Cases: ", map@data$cases),
htmltools::HTML
)
# Render map
leaflet(map) %>%
addTiles() %>%
addPolygons(
fillColor = ~pal(map@data$cases),
fillOpacity = 0.7,
color = "white",
weight = 1,
label = labels,
highlight = highlightOptions(
weight = 2,
color = "#666",
fillOpacity = 0.9,
bringToFront = TRUE
)
) %>%
addLegend(
pal = pal,
values = map@data$cases,
title = "Cases (1980)",
opacity = 0.7
)
})
output$table <- renderDT({
dataagg <- aggregate(cbind(y, n) ~ NAME + year, data = data, sum)
dataagg$cases <- dataagg$y
dataagg$population <- dataagg$n
datatable(dataagg[, c("NAME", "year", "cases", "population")])
})
}
# Run the App
shinyApp(ui = ui, server = server)๐ Dive in โ and letโs learn from this awesome resource!