commit 37a06c5f07b0cda1cf30e368b24af2585930dd2f Author: dylanbenzi Date: Tue Jun 3 17:46:30 2025 -0400 init commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d3ed4c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.yml diff --git a/dashboard.Rmd b/dashboard.Rmd new file mode 100644 index 0000000..ffe0bc9 --- /dev/null +++ b/dashboard.Rmd @@ -0,0 +1,895 @@ +--- +title: "Hurricane Normalization App" +runtime: shiny +output: + flexdashboard::flex_dashboard: + orientation: columns + vertical_layout: fill + theme: + version: 4 + bootswatch: litera +--- + +```{r setup, include=FALSE} +library(flexdashboard) +library(shiny) +library(leaflet) +library(DT) +library(dplyr) +library(DBI) +library(tidyr) +library(ggplot2) +library(plotly) +library(viridis) +library(lubridate) +library(scales) +library(readr) +library(stringr) +library(kableExtra) +library(bslib) +library(dygraphs) +library(tidyverse) +library(sf) +library(shinyBS) +library(xts) +library(tigris) + +linuxdir <- "/home/dylan/Personal/Projects/Hurricane Normalization/" +macdir <- "~/Desktop/Personal/Projects/Hurricane Normalization/" +#baseDir <- macdir +baseDir <- linuxdir + +config <- config::get(file = paste0(baseDir, "R/dataScripts/restructured/app/config.yml")) + + + +# LOCAL CON +#con <- dbConnect( +# RPostgres::Postgres(), +# user = "postgres", +# password = "oiuqBub8s9n65sgan09", +# host = "192.168.0.6", +# port = 5432, +# dbname = "hurricanedb" +#) + +# SUPABASE CON +con <- dbConnect( + RPostgres::Postgres(), + host = config$db_host, + port = config$db_port, + dbname = config$db_dbname, + user = config$db_user, + password = config$db_password +) + +selected_storm_name <- "KATRINA" +selected_storm_year <- 2005 +selected_storm_basin <- "AL" +selected_lf_type = "LF" +selected_lf_id = "2" + + + +bestTrackQry <- paste0("SELECT * FROM hurdat.best_track WHERE storm_basin = '", selected_storm_basin, + "' AND storm_name = '", selected_storm_name, + "' AND storm_year = ", selected_storm_year + ) + +qry <- "SELECT *, ST_X(ST_Transform(location::geometry, 4326)) as lon, ST_Y(ST_Transform(location::geometry, 4326)) as lat FROM hurdat.best_track WHERE storm_basin = 'AL' AND storm_name = 'KATRINA' AND storm_year = 2005" + +xlallLandfallsNormalized <- read.csv(paste0(baseDir, "R/dataScripts/restructured/normalization/all-landfalls-normalized.csv"), header = T) %>% + select(-X) + +katrinaTrack <- dbGetQuery(con, qry) +katrinaTrack <- katrinaTrack %>% + mutate( + date = make_datetime(datetime) + ) %>% + select( + Date = date, + Latitude = lat, + Longitude = lon, + Pressure = pressure, + Windspeed = windspeed, + RMW = rmw, + record_identifier + ) + +katrinaLandfalls <- katrinaTrack %>% + filter(record_identifier == 'L') %>% + select(-record_identifier) + + +normalized2024 <- read.csv(paste0(baseDir, "R/dataScripts/restructured/normalization/2024-normalized.csv"), header = T) %>% + select(-X, -hurdatId, -MMH23, -MMP23) %>% + filter(MMH24 > 0) %>% + mutate( + lf_date = trimws(lf_date) + ) + +normalized2024 <- normalized2024 %>% + mutate( + lf_date = mdy(lf_date) + ) %>% + rename( + Storm = storm_name, + Landfall = lf_date + ) + +pop <- read.csv(paste0(baseDir, "Data/population_with_projections.csv"), stringsAsFactors = F) %>% + pivot_longer( + cols = starts_with("X"), + names_to = "year", + values_to = "pop", + ) %>% + rename(population = pop) %>% + mutate( + year = parse_number(year), + FIPS = ifelse(nchar(FIPS) == 4, paste0("0", FIPS), FIPS), + state_fips = substr(FIPS, 1, 2), + county_fips = substr(FIPS, 3, 5) + ) %>% + select(!full_county_and_state:County & !county_state & !FIPS) + +housing <- read.csv(paste0(baseDir, "Data/housing_units.csv"), stringsAsFactors = F) %>% + pivot_longer( + cols = starts_with("X"), + names_to = "year", + values_to = "housing" + ) %>% + mutate( + year = parse_number(year), + FIPS = ifelse(nchar(FIPS) == 4, paste0("0", FIPS), FIPS), + state_fips = substr(FIPS, 1, 2), + county_fips = substr(FIPS, 3, 5) + ) %>% + rename(housing_units = housing) %>% + select(!County.Full:County & !County.State & !FIPS) + +metrics.pop_and_housing <- pop %>% + left_join(housing, by = c("state_fips", "county_fips", "year")) + +#counties <- counties(state = "LA", cb = T) + +weightedCounties <- read.csv(paste0(baseDir, "R/dataScripts/weighted-counties.csv"), header = T) %>% + mutate( + weight = (PERCENTAGE/100), + FIPS = ifelse(nchar(FIPS) == 4, paste0("0", FIPS), FIPS), + state_fips = substr(FIPS, 1, 2), + county_fips = substr(FIPS, 3, 5) + ) %>% + select( + state_fips, + county_fips, + hurdatId = HURDAT_Cod, + storm_name = Name_1, + lfId = LF_ID_Mull, + lf_date = LF_Date, + year = Year, + rmw = RMW, + lat = Lat, + lon = Long, + rmw_2x = RMW_x2, + area = AREA, + weight + ) + +katrinaAffectedCounties <- weightedCounties %>% + filter(hurdatId == "AL122005" & lfId == "LF2") %>% + mutate( + fips = paste0(state_fips, county_fips) + ) + +katrinaLfTwoCountyMetrics <- metrics.pop_and_housing %>% + filter(year >= 2005) %>% + pivot_longer( + cols = c("population", "housing_units"), + names_to = "metric", + values_to = "value" + ) %>% + pivot_wider( + names_from = year, + values_from = value, + ) %>% + mutate( + fips = paste0(state_fips, county_fips) + ) %>% + filter(fips %in% katrinaAffectedCounties$fips) %>% + select(fips, !state_fips & !county_fips) + +###### REACTIVE VALUES + +storm_selection <- reactiveValues( + storm_year = NULL, + storm_name = NULL, + storm_basin = NULL, + lf_id = NULL, + is_selected = FALSE +) + +growth_trends <- reactiveValues( + lf_id = NULL +) + +###### + +###### SUPABASE PORT + +hurdat.hurdat_storms <- dbGetQuery(con, "SELECT *, CONCAT(storm_basin, storm_number, storm_year) AS hurdatId FROM hurdat.hurdat_storms") + +#hurdat.best_track <- dbGetQuery(con, "SELECT *, ST_X(ST_Transform(location::geometry, 4326)) as lon, ST_Y(ST_Transform(location::geometry, 4326)) as lat FROM hurdat.best_track") + +econ.normalized_landfalls <- dbGetQuery(con, "SELECT * FROM econ.normalized_landfalls") + +econ.storm_base_loss <- reactive({ + req(storm_selection$is_selected) + + query <- paste0(" + SELECT DISTINCT ON (storm_basin, storm_year, storm_name, lf_type, lf_id) + storm_basin, + storm_year, + storm_name, + lf_type, + lf_id, + base_loss_source, + base_loss + FROM econ.storm_base_loss + WHERE base_loss IS NOT NULL + ORDER BY + storm_basin, storm_year, storm_name, lf_type, lf_id, + CASE + WHEN base_loss_source LIKE '%ncei%' THEN 1 + WHEN base_loss_source LIKE '%mwr%' THEN 2 + ELSE 3 + END + ") + + dbGetQuery(con, query) +}) + +gis.affected_area_landfalls <- tbl(con, I("gis.affected_area_landfalls")) +public.counties <- tbl(con, I("public.counties")) + + +#allLandfallsNormalized <- econ.normalized_landfalls %>% +# left_join(econ.storm_base_loss, by = c("storm_basin", "storm_year", "storm_name", "lf_type", "lf_id")) %>% +# mutate( +# mmh = gdp_deflator * rwhu * affected_housing, +# mmp = gdp_deflator * rwpc * affected_population +# ) +``` + +```{r} +###### REACTIVE SETUP + +#REACTIVES USE LAZY LOADING + +#hurdat.best_track <- dbGetQuery(con, "SELECT *, ST_X(ST_Transform(location::geometry, 4326)) as lon, ST_Y(ST_Transform(location::geometry, 4326)) as lat FROM hurdat.best_track") + + +selected.best_track <- reactive({ + req(storm_selection$is_selected) + + query <- paste0(" + SELECT *, + ST_X(ST_Transform(location::geometry, 4326)) as lon, + ST_Y(ST_Transform(location::geometry, 4326)) as lat + FROM hurdat.best_track + WHERE storm_basin = '", storm_selection$storm_basin, + "' AND storm_year = ", storm_selection$storm_year, + " AND storm_name = '", storm_selection$storm_name, + "'") + + result <- dbGetQuery(con, query) + + cat(paste0("DEBUG: selected.best_track returned ", nrow(result))) + + return(result) +}) + + +``` + + +Home +============================================= + +Col {data-width=500} +---------------------------------------------- + +### {} +```{r eval=FALSE, include=FALSE} +HTML( + ' +

Welcome to the Hurricane Cost Normalization Web App!

+ +

Our platform provides access to normalized hurricane dama data spanning from 1900 to 2024, allowing researchers, policymakers, insurance professional, and the public to better understand how hurricane costs have changed over time.

+ +
Our Data
+ +

The core datasets used in this app are based on research by Muller et al. (2025) and the expanded analysis by Mooney et al. (2025), published in the Bulletin of the American Meteorlogical Society and ****JOURNAL**** respectively. These studies update and refine hurricane damage normalization methodologies to provide a more accurate picture of how historical hurricanes would impact today\'s society.

+ + + +
Methodology Innovations
+ +

Our platform incoroprates several methodological innovations over previously used cost normalization formulas: + +

+ +
Questions?
+ +

CONTACT INFO?

+ ' +) + +``` + + +```{r} +HTML( + ' +

Welcome to the Hurricane Cost Normalization Web App!

+ +

Our platform provides access to normalized hurricane dama data spanning from 1900 to 2024, allowing researchers, policymakers, insurance professional, and the public to better understand how hurricane costs have changed over time.

+ +
Our Data
+ +

The core datasets used in this app are based on research by Muller et al. (2025) published in the Bulletin of the American Meteorlogical Society. This study updates and refines hurricane damage normalization methodologies to provide a more accurate picture of how historical hurricanes would impact today\'s society.

+ + + +
Methodology Innovations
+ +

Our platform incoroprates several methodological innovations over previously used cost normalization formulas: + +

+ +
Questions?
+ +

CONTACT INFO?

+ ' +) + +``` + +Col {data-width=500} +---------------------------------------------- + +### Storm Selector {data-height=500} +```{r} +h5("Select Storm Name and Year") + +dbStormYears <- dbGetQuery(con, "SELECT DISTINCT storm_year, storm_name FROM econ.storm_base_loss ORDER BY storm_year") + +fluidRow( + column(6, + selectInput("stormYear", "Select Year", choices = dbStormYears$storm_year) + ), + column(6, + selectInput("stormName", "Select Storm", choices = NULL) + ) +) + +fluidRow( + column(12, + actionButton("selectStorm", "Submit", class = "btn-primary")) +) + +#h5("Search") + +#textInput("stormSearch", "Search by hurricane name, year") + +observeEvent(input$stormYear, { + stormsByChosenYear <- dbStormYears[dbStormYears$storm_year == input$stormYear, ] + + updateSelectInput(session, "stormName", + choices = stormsByChosenYear$storm_name, + selected = NULL) +}) + +observeEvent(input$selectStorm, { + storm_selection$storm_year <- input$stormYear + storm_selection$storm_name <- input$stormName + storm_selection$storm_basin <- "AL" + storm_selection$is_selected <- TRUE + + showNotification("Storm selection updated!", type = "message") +}) + +``` + +### All Storms {data-height=500 .no-padding} +```{r} +output$allStorms <- renderDT({ + datatable( + normalized2024, + rownames = F, + options = list( + pageLength = 1000, + order = list(2, 'desc'), + searching = F, + paging = F, + info = F, + lengthChange = F, + server = T + ) + ) %>% + formatCurrency(c("MMH24", "MMP24"), "$", digits = 0) +}) + +DTOutput("allStorms") +``` + + + +Storm Overview {data-navmenu="Storm Details"} +==================================== + +Col {data-width=500} +------------------------------------ + +### Storm Details {data-height=200} +```{r} +HTML(' +
Katrina
+

Hurricane Katrina was a powerful, devestating and historic tropical cyclone that caused 1,392 fatalities and damages estimated at $125 billion in late August 2005.

+') +``` + +### Normalization Cost Index {data-height=800} +```{r} + +##BY LANDFALL### +##MULTIPLE LINES### + +dbNormalizedLandfalls <- reactive({ + req(storm_selection$is_selected) + + query <- paste0(" + SELECT *, CONCAT(lf_type, lf_id) as lfid FROM econ.normalized_landfalls + WHERE storm_basin = '", storm_selection$storm_basin, + "' AND storm_year = ", storm_selection$storm_year, + " AND storm_name = '", storm_selection$storm_name, + "'") + + result <- dbGetQuery(con, query) + + #cat(str(result)) + + showNotification(nrow(result)) + + return(result) +}) + +dbUniq <- reactive({ + req(dbNormalizedLandfalls(), nrow(dbNormalizedLandfalls()) > 0) + + dbNormalizedLandfalls() %>% + distinct(lfid) + + #re <- unique(res$lfid) + + #cat(str(res)) + #cat(str(re)) + + #cat("hi2") + + #cat(str(res)) + + #return(res) +}) + +lfNormalized <- reactive({ + req(storm_selection$lf_id) + + lf <- dbNormalizedLandfalls() %>% + filter(lfid == storm_selection$lf_id) %>% + mutate( + mmh = gdp_deflator * rwhu * affected_housing, + mmp = gdp_deflator * rwpc * affected_population, + years = as.Date(paste0(normalization_year, "-01-01")) + ) %>% + select( + years, mmh, mmp + ) + + lf_ts <- lf %>% + select(-years) %>% + xts(order.by = lf$years) + + cat(storm_selection$lf_id) + cat(str(lf_ts)) + + return(lf_ts) +}) + +fillCol( + flex = c(.2, .8), + fluidRow( + column(4, + selectInput("lfSelect", "Landfall Select", choices = NULL) + ), + column(4, + #checkboxInput("mmhSelect", "Display MMH", value = T) + ), + column(4, + #checkboxInput("mmpSelect", "Display MMP", value = T) + ) + ), + #dygraphOutput("katrinaCostIndex") + dygraphOutput("costIndex") +) + + +observe({ + req(dbUniq(), nrow(dbUniq()) > 0) + + #cat("hi") + #cat(nrow(dbUniq())) + #cat(str(dbUniq())) + + updateSelectInput( + session, + "lfSelect", + choices = dbUniq()$lfid, + selected = dbUniq()$lfid[1] + ) + + updateSelectInput( + session, + "growthTrendLfSelect", + choices = dbUniq()$lfid, + selected = dbUniq()$lfid[1] + ) + + storm_selection$lf_id = dbUniq()$lfid[1] +}) + +observeEvent(input$lfSelect, { + storm_selection$lf_id = input$lfSelect + + showNotification("Landfall updated", type = "message") +}) + +output$costIndex <- renderDygraph({ + req(lfNormalized()) + + dygraph(lfNormalized(), main = "Cost Index") %>% + dySeries("mmh", label = "MMH") %>% + dySeries("mmp", label = "MMP") %>% + dyRangeSelector(height = 30) +}) + +``` + +Col {data-width=500} +------------------------------------ + +### Fatalities {data-height=200} +```{r} +fluidRow( + column(6, + HTML(' +
Katrina recorded 1,392 fatalities
+

Surge: 387

+ ') + ), + column(6, + actionLink("fatalitiesLink", tagList(icon("arrow-right"), "Fatalities dashboard"), class = "btn btn-outline") + ) +) +``` + +### Landfalls {data-height=300 .no-padding} +```{r} +#selectLandfalls <- hurdat.best_track %>% +# filter( +# storm_name == storm_selection$storm_name & +# storm_year == storm_selection$storm_year & +# record_identifier == "L" +# ) + +landfallsdata <- reactive({ + req(storm_selection$is_selected) + + df <- selected.best_track() %>% + filter(record_identifier == "L") %>% + select( + Date = datetime, + Latitude = lat, + Longitude = lon, + Pressure = pressure, + Windspeed = windspeed, + RMW = rmw + ) +}) + +output$landfalls <- renderDT({ + datatable( + landfallsdata(), + rownames = F, + options = list( + order = list(0, 'asc'), + paging = F, + searching = F, + info = F, + lengthChange = F, + server = T + ) + ) %>% + formatDate(columns = "Date", method = "toUTCString") +}) + +DTOutput("landfalls") + +``` + +### Storm Track {data-height=500 .no-padding} +```{r} +output$trackMap <- renderLeaflet({ + leaflet() %>% + addProviderTiles("CartoDB.Positron", option = providerTileOptions(minZoom = 2, maxZoom = 18)) %>% + setView(lng = -80, lat = 32, zoom = 4) %>% + addCircleMarkers( + #data = katrinaTrack, + #lng = ~Longitude, + #lat = ~Latitude, + data = selected.best_track(), + lng = ~lon, + lat = ~lat, + radius = 5, + color = ~ifelse(record_identifier == "L", "red", "blue"), + fillColor = ~ifelse(record_identifier == "L", "red", "blue") + ) +}) + +leafletOutput("trackMap", height="100%") +``` + +Growth Trends {data-navmenu="Storm Details"} +================================ + +Column {data-width=550} +------------------------------- + +### {data-height=1000 .no-padding} + +```{r} +dbStormCounties <- reactive({ + req(storm_selection$is_selected) + + sel_storm_basin <- storm_selection$storm_basin + sel_storm_year <- storm_selection$storm_year + sel_storm_name <- storm_selection$storm_name + sel_lfid <- growth_trends$lf_id + + affectedCounties <- gis.affected_area_landfalls %>% + mutate( + fips = paste0(state_fips, county_fips), + lfid = paste0(lf_type, lf_id) + ) %>% + filter( + storm_basin == sel_storm_basin, + storm_year == sel_storm_year, + storm_name == sel_storm_name, + lfid == sel_lfid + ) %>% + left_join( + public.counties %>% + mutate(geom_wkt = sql("ST_AsText(ST_Transform(geom, 4326))")) %>% + rename(state_fips = statefp, county_fips = countyfp), + by = c("state_fips", "county_fips") + ) %>% + collect() + + affectedCounties_sf <- affectedCounties %>% + st_as_sf(wkt = "geom_wkt") + + cat(str(affectedCounties_sf)) + + return(affectedCounties_sf) +}) + +output$popMapPoly <- renderLeaflet({ + leaflet(dbStormCounties()) %>% + addProviderTiles("CartoDB.Positron", option = providerTileOptions(minZoom = 2, maxZoom = 18)) %>% + setView(lng = -89.8, lat = 29.6, zoom = 8) %>% + addPolygons( + fillColor = "red", + fillOpacity = 0.3, + color = "black", + weight = 2 + ) +}) + +output$housingMapPoly <- renderLeaflet({ + leaflet() %>% + addProviderTiles("CartoDB.Positron", option = providerTileOptions(minZoom = 2, maxZoom = 18)) %>% + setView(lng = -89.8, lat = 29.6, zoom = 8) %>% + addPolygons( + data = dbStormCounties(), + fillColor = "blue", + fillOpacity = 0.3, + color = "black", + weight = 2 + ) +}) + +fillCol( + flex = c(1, 1), + leafletOutput("popMapPoly"), + leafletOutput("housingMapPoly") +) + +``` + +Column {data-width=450} +---------------------------------- + +### Landfall Selection {data-height=150} +```{r} + + +fluidRow( + column(4, + selectInput("growthTrendLfSelect", "Landfall", choices = NULL) + ), + column(4, + + ), + column(4, + + ) +) + +observeEvent(input$growthTrendLfSelect, { + growth_trends$lf_id = input$growthTrendLfSelect + + showNotification("Landfall updated", type = "message") +}) +``` + +### Time Series {data-height=400 .no-padding} +```{r} + + +katrinaLfTwoLong <- katrinaLfTwoCountyMetrics %>% + pivot_longer( + cols = -c(fips, metric), + names_to = "year", + values_to = "value" + ) %>% + group_by( + metric, year + ) %>% + summarize( + aggregateValue = sum(value, na.rm = T), + .groups = "drop" + ) %>% + pivot_wider( + names_from = metric, + values_from = aggregateValue + ) + +normalizedKatrinaLfTwo <- xlallLandfallsNormalized %>% + filter(hurdatId == "AL122005" & lfId == "LF2") %>% + select(normalizationYear, affectedPop, affectedHousing) + +normalizedKatrinaLfTwoTs <- normalizedKatrinaLfTwo %>% + select(-normalizationYear) %>% + as.matrix() %>% + xts(order.by = as.Date(paste0(normalizedKatrinaLfTwo$normalizationYear, "-01-01"))) + +katrinaLfTwoLongTs <- katrinaLfTwoLong %>% + select(-year) %>% + as.matrix() %>% + xts(order.by = as.Date(paste0(katrinaLfTwoLong$year, "-01-01"))) + + +output$popHu <- renderDygraph({ + dygraph(normalizedKatrinaLfTwoTs, main = "Normalized LF2 Aggregate Growth") %>% + dySeries("affectedPop", label = "Population") %>% + dySeries("affectedHousing", label = "Housing Units") %>% + dyRangeSelector() +}) + + +dygraphOutput("popHu") +``` + +### County Data {data-height=450 .no-padding} +```{r} + + +output$katrinaCounties <- renderDT({ + datatable( + katrinaLfTwoCountyMetrics, + rownames = F, + #extensions = "RowGroup", + options = list( + pageLength = 1000, + #rowGroup = list(dataSrc = 1), + paging = F, + searching = F, + info = F, + lengthChange = F, + server = T + ) + ) +}) + +DTOutput("katrinaCounties") + +``` + + + +Fatalities {data-navmenu="Fatalities"} +=== + +Column {data-width=500} +--- + +### {data-height=500} + +### {data-height=500} + +Column {data-width=500} +--- + +### {data-height=500} +```{r} +``` + +### {data-height=500} +```{r} +``` + +Storm Comparison {data-navmenu="Compute"} +=== + +Sandbox {data-navmenu="Compute"} +=== + +Data {data-navmenu="Compute"} +=== + +Top 50 Storms +=== + +About +=== diff --git a/dashboard.Rmd.old b/dashboard.Rmd.old new file mode 100644 index 0000000..16a96e2 --- /dev/null +++ b/dashboard.Rmd.old @@ -0,0 +1,236 @@ +--- +title: "Hurricane Normalization App" +runtime: shiny +output: + flexdashboard::flex_dashboard: + orientation: rows + vertical_layout: fill + navbar: + - {title: "Home", icon: "fa-home", href: "#"} + - {title: "About", icon: "fa-info-circle"} + theme: + version: 4 + bootswatch: journal +--- + +```{r setup, include=FALSE} +library(flexdashboard) +library(shiny) +library(leaflet) +library(DT) +library(dplyr) +library(DBI) +library(tidyr) +library(ggplot2) +library(plotly) +library(viridis) +library(lubridate) +library(scales) +library(readr) +library(stringr) +library(kableExtra) +library(bslib) + +setwd("/home/dylan/Personal/Projects/Hurricane Normalization/") + +pop <- read.csv("Data/population_with_projections.csv", stringsAsFactors = F) %>% + pivot_longer( + cols = starts_with("X"), + names_to = "year", + values_to = "pop", + ) %>% + mutate( + year = parse_number(year) + ) + +housing <- read.csv("Data/housing_units.csv", stringsAsFactors = F) %>% + pivot_longer( + cols = starts_with("X"), + names_to = "year", + values_to = "housing" + ) %>% + mutate( + year = parse_number(year) + ) + +counties <- pop %>% + left_join(housing %>% select(FIPS, year, housing), by = c("FIPS", "year")) %>% + pivot_longer( + cols = c("pop", "housing"), + names_to = "metric", + values_to = "value" + ) + +pop <- pop %>% + mutate( + FIPS = ifelse(nchar(FIPS) == 4, paste0("0", FIPS), FIPS), + state_fips = substr(FIPS, 1, 2), + county_fips = substr(FIPS, 3, 5) + ) %>% + rename(population = pop) %>% + select(!full_county_and_state:County & !county_state & !FIPS) + +housing <- housing %>% + mutate( + FIPS = ifelse(nchar(FIPS) == 4, paste0("0", FIPS), FIPS), + state_fips = substr(FIPS, 1, 2), + county_fips = substr(FIPS, 3, 5) + ) %>% + rename(housing_units = housing) %>% + select(!County.Full:County & !County.State & !FIPS) + +metrics.pop_and_housing <- pop %>% + left_join(housing, by = c("state_fips", "county_fips", "year")) + +donna <- read.csv("R/dataScripts/restructured/hurdat2/gis_counties.csv") + +donna <- donna %>% + filter(HURDAT_C_1 == "AL051960") %>% + mutate( + FIPS = as.character(FIPS) + ) + +donna <- donna %>% + mutate( + FIPS = case_when( + str_length(donna$FIPS) == 4 ~ paste0("0", donna$FIPS), + TRUE ~ donna$FIPS + ), + state_fips = substr(FIPS, 1, 2), + county_fips = substr(FIPS, 3, 5) + ) %>% + rename(year = Year) + +donna <- donna %>% + left_join(metrics.pop_and_housing, by = c("state_fips", "county_fips", "year")) + +donna <- donna %>% + select(Storm_Name, STATE_NAME, County_Name, state_fips, county_fips, population, housing_units) + +donna <- donna %>% + mutate(Storm_Name = substr(Storm_Name, 1, 5)) + +donna <- donna %>% + mutate( + FIPS = paste0(state_fips, county_fips) + ) %>% + select( + -state_fips, + -county_fips + ) + +donna <- donna %>% + select( + County = County_Name, + Population = population, + Housing = housing_units + ) + + +# 1-3 FL +# 4-10 NC +# 11-13 CT +# 14-16 NY + +``` + + +Dashboard +============================================= + +Row {data-height=100} +---------------------------------------------- +### {data-width=103} +```{r} +h6("Hurricane") +h3("Galveston 1900") +``` + +### {data-width=25} + +```{r} +valueBox("#18", caption = "Rank by population") +``` + +### {data-width=25} + +```{r} +valueBox("$58.11b", caption = "Loss by population", icon = "fa-user") +``` + +### {data-width=25} + +```{r} +valueBox("#37", caption = "Rank by housing") +``` + +### {data-width=25} + +```{r} +valueBox("$10.63b", caption = "Loss by housing", icon = "fa-house") +``` + +Row {data-height=400} +---------------------------------------------- + +### {data-width=50} + +```{r} +donna %>% + kbl() %>% + kable_styling(font_size = 16) %>% + pack_rows("Florida", 1, 3, label_row_css = "color: #fff") %>% + pack_rows("North Carolina", 4, 10, label_row_css = "color: #fff") %>% + pack_rows("Connecticut", 11, 13, label_row_css = "color: #fff") %>% + pack_rows("New York", 14, 16, label_row_css = "color: #fff") %>% + row_spec(1:16, color = "white") +``` + + +### {data-width=50} + +```{r} +output$worldMap <- renderLeaflet({ + leaflet() %>% + addTiles() %>% + setView(lng = 0, lat = 20, zoom = 2) %>% + addScaleBar(position = "bottomleft") %>% + addLayersControl( + baseGroups = c("Default", "Satellite", "Terrain"), + options = layersControlOptions(collapsed = FALSE) + ) %>% + addProviderTiles(providers$Esri.WorldImagery, group = "Satellite") %>% + addProviderTiles(providers$Stamen.Terrain, group = "Terrain") %>% + hideGroup("Satellite") %>% + hideGroup("Terrain") +}) + +output$map <- renderLeaflet({ + leaflet() %>% + addProviderTiles("Stadia.AlidadeSmoothDark", option = providerTileOptions(minZoom = 2, maxZoom = 18)) %>% + setView(lng = 0, lat = 20, zoom = 2) +}) + +#leafletOutput("map", height="100%") + +leafletOutput("worldMap", height = "100%") +``` + +Row {data-height=400} +--- + +### {data-width=50} + +```{r} +lines <- metrics.pop_and_housing %>% + filter(state_fips == "01" & county_fips == "087" & year >= 1960) + +output$lineChart <- renderPlot({ + ggplot(lines, aes()) +}) +``` + +### {data-width=50} +```{r eval=FALSE, include=FALSE} + +``` \ No newline at end of file diff --git a/hurricane_app/server.R b/hurricane_app/server.R new file mode 100644 index 0000000..85e71a1 --- /dev/null +++ b/hurricane_app/server.R @@ -0,0 +1,28 @@ +# +# 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: +# +# https://shiny.posit.co/ +# + +library(shiny) + +# Define server logic required to draw a histogram +function(input, output, session) { + + output$distPlot <- renderPlot({ + + # generate bins based on input$bins from ui.R + x <- faithful[, 2] + bins <- seq(min(x), max(x), length.out = input$bins + 1) + + # draw the histogram with the specified number of bins + hist(x, breaks = bins, col = 'darkgray', border = 'white', + xlab = 'Waiting time to next eruption (in mins)', + main = 'Histogram of waiting times') + + }) + +} diff --git a/hurricane_app/ui.R b/hurricane_app/ui.R new file mode 100644 index 0000000..3aa541b --- /dev/null +++ b/hurricane_app/ui.R @@ -0,0 +1,33 @@ +# +# This is the user-interface definition of a Shiny web application. You can +# run the application by clicking 'Run App' above. +# +# Find out more about building applications with Shiny here: +# +# https://shiny.posit.co/ +# + +library(shiny) + +# Define UI for application that draws a histogram +fluidPage( + + # Application title + titlePanel("Old Faithful Geyser Data"), + + # Sidebar with a slider input for number of bins + sidebarLayout( + sidebarPanel( + sliderInput("bins", + "Number of bins:", + min = 1, + max = 50, + value = 30) + ), + + # Show a plot of the generated distribution + mainPanel( + plotOutput("distPlot") + ) + ) +)