| | | 0% | |== | 3% | |=== | 4% | |=== | 5% | |==== | 5% | |===== | 6% | |===== | 8% | |====== | 8% | |====== | 9% | |======= | 10% | |======= | 11% | |======== | 12% | |========= | 13% | |========== | 14% | |=========== | 15% | |=========== | 16% | |============ | 17% | |============= | 18% | |============== | 20% | |=============== | 22% | |================ | 24% | |================= | 24% | |================== | 26% | |=================== | 27% | |===================== | 29% | |====================== | 31% | |======================= | 33% | |========================= | 36% | |=========================== | 38% | |============================ | 41% | |============================== | 43% | |================================ | 46% | |================================== | 48% | |=================================== | 51% | |===================================== | 53% | |======================================= | 56% | |========================================= | 58% | |========================================== | 61% | |============================================ | 63% | |============================================== | 66% | |================================================ | 68% | |================================================= | 71% | |=================================================== | 73% | |===================================================== | 76% | |======================================================= | 78% | |======================================================== | 81% | |========================================================== | 83% | |============================================================ | 86% | |============================================================== | 88% | |=============================================================== | 91% | |================================================================= | 93% | |=================================================================== | 95% | |===================================================================== | 98% | |======================================================================| 100%
This dashboard is designed as a clean two-page overview of Iowa’s 2024 impaired waters data. Start with the KPIs above, then review the map and comparison charts to see where records are concentrated, which impairment types are most common, and how priority tiers and listing cycles are distributed.
Use this page to compare patterns across time and status. A higher bar or point indicates more listed records in that category. Focus on the categories with the strongest concentration because they indicate the areas where impaired waters are most frequently being documented in this dataset.
The dashboard suggests that a relatively small set of impairment categories accounts for many records, while waterbody type and priority tier provide a useful second layer for comparison. The cycle and status views help the viewer decide whether the dataset reflects persistent issues, emerging issues, or both.
Iowa Department of Natural Resources. (2024). Iowa impaired waters list (303d) dataset. https://www.iowadnr.gov/
Iannone, R., Allaire, J., & Borges, B. (2023). flexdashboard: R markdown format for flexible dashboards. https://rmarkdown.rstudio.com/flexdashboard/
Wickham, H. (2016). ggplot2: Elegant graphics for data analysis. Springer.
Sievert, C. (2020). Interactive web-based data visualization with R, plotly, and shiny. CRC Press.
Tufte, E. R. (2001). The visual display of quantitative information. Graphics Press.
The Epidemiologist R Handbook. (n.d.). Dashboards with R Markdown. https://www.epirhandbook.com/en/new_pages/flexdashboard.html
Moraga, P. (n.d.). Building a dashboard to visualize spatial data with flexdashboard. In Geospatial Health Data: Modeling and Visualization with R-INLA and Shiny. https://www.paulamoraga.com/book-geospatial/sec-flexdashboard.html
---
title: "Lab 1 - Dashboards and Dashboarding Theory"
author: "Lipi Vikram Thakker"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
theme:
version: 5
bootswatch: flatly
source_code: embed
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE)
library(flexdashboard)
library(tidyverse)
library(plotly)
library(leaflet)
library(sf)
library(DT)
library(scales)
library(htmltools)
```
```{r data}
# Update these file paths only if needed
imp <- read_csv("iowa_2024ImpairedFinal.csv", show_col_types = FALSE)
library(tidycensus)
ia_tract_pop_geo <- get_decennial(
geography = "tract",
state = "IA",
variables = "P1_001N",
year = 2020,
geometry = TRUE
)
ia_tract_pop_geo <- ia_tract_pop_geo %>%
select(GEOID, tract_name = NAME, population = value)
ia_tract_pop_geo <- st_transform(ia_tract_pop_geo, 4326)
imp <- imp %>%
mutate(
cycleListed = suppressWarnings(as.numeric(cycleListed)),
type = as.factor(type),
tmdlPriority = factor(tmdlPriority,
levels = c("Tier I", "Tier II", "Tier III", "Tier IV")),
impairmentStatus = as.factor(impairmentStatus)
)
# KPI values
total_records <- nrow(imp)
total_segments <- n_distinct(imp$SegID)
total_waterbodies <- n_distinct(imp$name)
new_impairments <- sum(imp$impairmentStatus == "New", na.rm = TRUE)
# Summaries
top_impairments <- imp %>%
count(impairment, sort = TRUE) %>%
filter(!is.na(impairment)) %>%
slice_head(n = 10)
type_summary <- imp %>%
count(type, sort = TRUE) %>%
filter(!is.na(type))
priority_summary <- imp %>%
count(tmdlPriority, sort = FALSE) %>%
filter(!is.na(tmdlPriority))
cycle_summary <- imp %>%
count(cycleListed, sort = TRUE) %>%
filter(!is.na(cycleListed))
status_summary <- imp %>%
count(impairmentStatus, sort = TRUE) %>%
filter(!is.na(impairmentStatus))
```
Overview
=====================================
Row {data-height=120}
-------------------------------------
### Records
```{r}
valueBox(
value = comma(total_records),
caption = "Total impairment records",
icon = "fa-database",
color = "primary"
)
```
### Segments
```{r}
valueBox(
value = comma(total_segments),
caption = "Unique water segments",
icon = "fa-water",
color = "info"
)
```
### Waterbodies
```{r}
valueBox(
value = comma(total_waterbodies),
caption = "Distinct waterbody names",
icon = "fa-map",
color = "success"
)
```
### New Listings
```{r}
valueBox(
value = comma(new_impairments),
caption = "Records with New status",
icon = "fa-circle-exclamation",
color = "warning"
)
```
Row {data-height=110}
-------------------------------------
### How to read this dashboard
This dashboard is designed as a clean two-page overview of Iowa's 2024 impaired waters data. Start with the KPIs above, then review the map and comparison charts to see where records are concentrated, which impairment types are most common, and how priority tiers and listing cycles are distributed.
Row
-------------------------------------
### Iowa map / geography context
```{r}
### Iowa map / geography context
mypal <- colorBin(
palette = "YlOrRd",
domain = ia_tract_pop_geo$population,
bins = 5,
na.color = "white"
)
leaflet(ia_tract_pop_geo) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addPolygons(
fillColor = ~mypal(population),
color = "#8C8C8C",
weight = 0.2,
fillOpacity = 0.9,
smoothFactor = 0.2,
popup = ~paste0(
"<b>", tract_name, "</b><br>",
"Population: ", scales::comma(population)
)
) %>%
addLegend(
pal = mypal,
values = ~population,
title = "Tract population",
position = "bottomright"
) %>%
fitBounds(
lng1 = -96.7, lat1 = 40.3,
lng2 = -90.1, lat2 = 43.6
)
```
### Top 10 reported impairments
```{r}
library(stringr)
library(scales)
p1 <- ggplot(top_impairments,
aes(
x = reorder(str_wrap(impairment, width = 50), n),
y = n,
text = paste0("Impairment: ", impairment, "<br>Count: ", comma(n))
)
) +
geom_col(fill = "#2C7FB8", width = 0.75) +
coord_flip() +
labs(
title = "Most common impairment categories",
x = NULL,
y = "Records"
) +
scale_y_continuous(labels = comma) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank(),
axis.text.y = element_text(size = 5)
)
ggplotly(p1, tooltip = "text") %>%
layout(margin = list(l = 140, r = 20, t = 60, b = 50))
```
Row
-------------------------------------
### Waterbody type distribution
```{r}
p2 <- ggplot(type_summary,
aes(x = reorder(type, n), y = n,
text = paste0("Type: ", type, "<br>Count: ", comma(n)))) +
geom_col(fill = "#18A999", width = 0.7) +
labs(
title = "Impairments by waterbody type",
x = NULL,
y = "Count"
) +
scale_y_continuous(labels = comma) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank(),
axis.text.x = element_text(angle = 20, hjust = 1)
)
ggplotly(p2, tooltip = "text") %>%
layout(margin = list(l = 50, r = 20, t = 60, b = 80))
```
### TMDL priority tiers
```{r}
p3 <- ggplot(priority_summary,
aes(x = tmdlPriority, y = n,
text = paste0("Priority: ", tmdlPriority, "<br>Count: ", comma(n)))) +
geom_col(fill = "#F4A261", width = 0.68) +
labs(
title = "TMDL priority distribution",
x = NULL,
y = "Count"
) +
scale_y_continuous(labels = comma) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank()
)
ggplotly(p3, tooltip = "text") %>%
layout(margin = list(l = 50, r = 20, t = 60, b = 60))
```
Patterns
=====================================
Row {data-height=110}
-------------------------------------
### Interpretive guidance
Use this page to compare patterns across time and status. A higher bar or point indicates more listed records in that category. Focus on the categories with the strongest concentration because they indicate the areas where impaired waters are most frequently being documented in this dataset.
Row
-------------------------------------
### Listing cycle trend
```{r}
p4 <- ggplot(cycle_summary,
aes(x = cycleListed,
y = n,
group = 1,
text = paste0("Cycle: ", cycleListed, "<br>Count: ", comma(n)))) +
geom_line(linewidth = 1, color = "#33658A") +
geom_point(size = 2.4, color = "#33658A") +
labs(
title = "Impairments by listing cycle",
x = "Cycle listed",
y = "Count"
) +
scale_y_continuous(labels = comma) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank()
)
ggplotly(p4, tooltip = "text") %>%
layout(margin = list(l = 55, r = 20, t = 60, b = 60))
```
### Impairment status comparison
```{r}
p5 <- ggplot(status_summary,
aes(x = reorder(impairmentStatus, n), y = n,
text = paste0("Status: ", impairmentStatus, "<br>Count: ", comma(n)))) +
geom_col(fill = "#BC5090", width = 0.65) +
labs(
title = "New vs continuing impairment status",
x = NULL,
y = "Count"
) +
scale_y_continuous(labels = comma) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank()
)
ggplotly(p5, tooltip = "text") %>%
layout(margin = list(l = 55, r = 20, t = 60, b = 60))
```
Row
-------------------------------------
### Detailed data table
```{r}
datatable(
imp,
class = "compact stripe hover",
options = list(
pageLength = 8,
scrollX = TRUE,
autoWidth = TRUE,
dom = "tip"
),
rownames = FALSE
)
```
### Key takeaways
The dashboard suggests that a relatively small set of impairment categories accounts for many records, while waterbody type and priority tier provide a useful second layer for comparison. The cycle and status views help the viewer decide whether the dataset reflects persistent issues, emerging issues, or both.
References
=====================================
### Sources
- Iowa Department of Natural Resources. (2024). *Iowa impaired waters list (303d) dataset*. https://www.iowadnr.gov/
- Iannone, R., Allaire, J., & Borges, B. (2023). *flexdashboard: R markdown format for flexible dashboards*. https://rmarkdown.rstudio.com/flexdashboard/
- Wickham, H. (2016). *ggplot2: Elegant graphics for data analysis*. Springer.
- Sievert, C. (2020). *Interactive web-based data visualization with R, plotly, and shiny*. CRC Press.
- Tufte, E. R. (2001). *The visual display of quantitative information*. Graphics Press.
- The Epidemiologist R Handbook. (n.d.). *Dashboards with R Markdown*. https://www.epirhandbook.com/en/new_pages/flexdashboard.html
- Moraga, P. (n.d.). *Building a dashboard to visualize spatial data with flexdashboard*. In *Geospatial Health Data: Modeling and Visualization with R-INLA and Shiny*. https://www.paulamoraga.com/book-geospatial/sec-flexdashboard.html