diff --git a/01_Data_raw/HAB/HAB_FWC.csv b/01_Data_raw/Algae/HAB/HAB_FWC.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/HAB/HAB_FWC.csv rename to 01_Data_raw/Algae/HAB/HAB_FWC.csv diff --git a/01_Data_raw/HAB/HAB_FWC.xlsx b/01_Data_raw/Algae/HAB/HAB_FWC.xlsx old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/HAB/HAB_FWC.xlsx rename to 01_Data_raw/Algae/HAB/HAB_FWC.xlsx diff --git a/01_Data_raw/Biodiversity/PLACEHOLDER.txt b/01_Data_raw/Biodiversity/PLACEHOLDER.txt new file mode 100644 index 0000000..87e47d2 --- /dev/null +++ b/01_Data_raw/Biodiversity/PLACEHOLDER.txt @@ -0,0 +1,2 @@ +REMOVE THIS FILE AFTER ADDING DATA TO THIS FOLDER. +This is jsut so the folders are saved to Git. \ No newline at end of file diff --git a/01_Data_raw/Hydrology/PLACEHOLDER.txt b/01_Data_raw/Hydrology/PLACEHOLDER.txt new file mode 100644 index 0000000..87e47d2 --- /dev/null +++ b/01_Data_raw/Hydrology/PLACEHOLDER.txt @@ -0,0 +1,2 @@ +REMOVE THIS FILE AFTER ADDING DATA TO THIS FOLDER. +This is jsut so the folders are saved to Git. \ No newline at end of file diff --git a/01_Data_raw/Shellfish/PLACEHOLDER.txt b/01_Data_raw/Shellfish/PLACEHOLDER.txt new file mode 100644 index 0000000..87e47d2 --- /dev/null +++ b/01_Data_raw/Shellfish/PLACEHOLDER.txt @@ -0,0 +1,2 @@ +REMOVE THIS FILE AFTER ADDING DATA TO THIS FOLDER. +This is jsut so the folders are saved to Git. \ No newline at end of file diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2002.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2002.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2002.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2002.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2003.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2003.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2003.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2003.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2004.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2004.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2004.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2004.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2005.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2005.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2005.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2005.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2006.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2006.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2006.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2006.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2007.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2007.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2007.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2007.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2008.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2008.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2008.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2008.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2009.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2009.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2009.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2009.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2010.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2010.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2010.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2010.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2011.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2011.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2011.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2011.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2012.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2012.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2012.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2012.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2013.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2013.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2013.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2013.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2014.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2014.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2014.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2014.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2015.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2015.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2015.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2015.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2016.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2016.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2016.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2016.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2017.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2017.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2017.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2017.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2018.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2018.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2018.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2018.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2019.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2019.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/gtmnut2019.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/gtmnut2019.csv diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/nutrient_readme.txt b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/nutrient_readme.txt old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/nutrient_readme.txt rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/nutrient_readme.txt diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/readme.rtf b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/readme.rtf old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/readme.rtf rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/readme.rtf diff --git a/01_Data_raw/GTMNERR_SWMP_Nutrient_Data/sampling_stations.csv b/01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/sampling_stations.csv old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/GTMNERR_SWMP_Nutrient_Data/sampling_stations.csv rename to 01_Data_raw/Water_Quality/GTMNERR_SWMP_Nutrient_Data/sampling_stations.csv diff --git a/01_Data_raw/Guana_WQ/Guana_masterdata.xlsx b/01_Data_raw/Water_Quality/Guana_WQ/Guana_masterdata.xlsx similarity index 100% rename from 01_Data_raw/Guana_WQ/Guana_masterdata.xlsx rename to 01_Data_raw/Water_Quality/Guana_WQ/Guana_masterdata.xlsx diff --git a/01_Data_raw/Guana_WQ/guana_data_dictionary.csv b/01_Data_raw/Water_Quality/Guana_WQ/guana_data_dictionary.csv similarity index 100% rename from 01_Data_raw/Guana_WQ/guana_data_dictionary.csv rename to 01_Data_raw/Water_Quality/Guana_WQ/guana_data_dictionary.csv diff --git a/01_Data_raw/Guana_WQ/guana_data_dictionary_updateGK.csv b/01_Data_raw/Water_Quality/Guana_WQ/guana_data_dictionary_updateGK.csv similarity index 86% rename from 01_Data_raw/Guana_WQ/guana_data_dictionary_updateGK.csv rename to 01_Data_raw/Water_Quality/Guana_WQ/guana_data_dictionary_updateGK.csv index 92d4b8e..42aad1f 100644 --- a/01_Data_raw/Guana_WQ/guana_data_dictionary_updateGK.csv +++ b/01_Data_raw/Water_Quality/Guana_WQ/guana_data_dictionary_updateGK.csv @@ -1,9 +1,10 @@ -site,alternate_name,site_friendly,station_code,site_acronym,lat,long,start_date,end,wbid,location +site,alternate_name,site_friendly,StationCode,site_acronym,Latitude,Longitude,start_date,end,wbid,location MICKLERS,N,Micklers,GTMMKNUT,MK,30.16073611,-81.36027778,,N,Lake,water_control DEPGL1,N,Guana Lake 1,GTMGL1NUT,GL1,30.1504,-81.3604,,N,Lake,open_water DEPGL2,N,Guana Lake 2,GTMGL2NUT,GL2,30.1161,-81.3511,,N,Lake,open_water LAKE MIDDLE,DEPGL3,Lake Middle,GTMLMNUT,LM,30.08302,-81.34286,,N,Lake,open_water LAKE MIDDLE,N,Lake Middle,GTMOLNUT,LM,30.08302,-81.34286,,Y,Lake,open_water +LAKE MIDDLE,N,Lake Middle,GTMOLNUT_dup,LM,30.08302,-81.34286,,Y,Lake,open_water DEPGL4,N,Guana Lake 4,GTMGL4NUT,GL4,30.0451,-81.3351,,N,Lake,open_water LAKE SOUTH,N,Lake South,GTMDNNUT,LS,30.023763,-81.327928,,Y,Lake,water_control LAKE SOUTH,N,Lake South,GTMLSNUT,LS,30.023763,-81.327928,,N,Lake,water_control diff --git a/01_Data_raw/Guana_WQ/metadata_2017-2023_Q1m_prov.docx b/01_Data_raw/Water_Quality/Guana_WQ/metadata_2017-2023_Q1m_prov.docx similarity index 100% rename from 01_Data_raw/Guana_WQ/metadata_2017-2023_Q1m_prov.docx rename to 01_Data_raw/Water_Quality/Guana_WQ/metadata_2017-2023_Q1m_prov.docx diff --git a/01_Data_raw/Water_Quality/Guana_WQ/~$Guana_masterdata.xlsx b/01_Data_raw/Water_Quality/Guana_WQ/~$Guana_masterdata.xlsx new file mode 100644 index 0000000..5a93205 Binary files /dev/null and b/01_Data_raw/Water_Quality/Guana_WQ/~$Guana_masterdata.xlsx differ diff --git a/01_Data_raw/Guana_WQ/~$tadata_2017-2023_Q1m_prov.docx b/01_Data_raw/Water_Quality/Guana_WQ/~$tadata_2017-2023_Q1m_prov.docx similarity index 100% rename from 01_Data_raw/Guana_WQ/~$tadata_2017-2023_Q1m_prov.docx rename to 01_Data_raw/Water_Quality/Guana_WQ/~$tadata_2017-2023_Q1m_prov.docx diff --git a/01_Data_raw/WIN/Site_locations.csv b/01_Data_raw/Water_Quality/WIN/Site_locations.csv similarity index 100% rename from 01_Data_raw/WIN/Site_locations.csv rename to 01_Data_raw/Water_Quality/WIN/Site_locations.csv diff --git a/01_Data_raw/WIN/WINData_5016.xlsx b/01_Data_raw/Water_Quality/WIN/WINData_5016.xlsx old mode 100755 new mode 100644 similarity index 100% rename from 01_Data_raw/WIN/WINData_5016.xlsx rename to 01_Data_raw/Water_Quality/WIN/WINData_5016.xlsx diff --git a/01_Data_raw/WIN/WIN_Warehouse_Glossary.pdf b/01_Data_raw/Water_Quality/WIN/WIN_Warehouse_Glossary.pdf similarity index 100% rename from 01_Data_raw/WIN/WIN_Warehouse_Glossary.pdf rename to 01_Data_raw/Water_Quality/WIN/WIN_Warehouse_Glossary.pdf diff --git a/01_Data_raw/WIN/WIN_data_merged_20240501.csv b/01_Data_raw/Water_Quality/WIN/WIN_data_merged_20240501.csv similarity index 100% rename from 01_Data_raw/WIN/WIN_data_merged_20240501.csv rename to 01_Data_raw/Water_Quality/WIN/WIN_data_merged_20240501.csv diff --git a/01_Data_raw/WIN/filtered_WIN_data_GTMNERR.csv b/01_Data_raw/Water_Quality/WIN/filtered_WIN_data_GTMNERR.csv similarity index 100% rename from 01_Data_raw/WIN/filtered_WIN_data_GTMNERR.csv rename to 01_Data_raw/Water_Quality/WIN/filtered_WIN_data_GTMNERR.csv diff --git a/01_Data_raw/WIN/filtered_WIN_data_counties.csv b/01_Data_raw/Water_Quality/WIN/filtered_WIN_data_counties.csv similarity index 100% rename from 01_Data_raw/WIN/filtered_WIN_data_counties.csv rename to 01_Data_raw/Water_Quality/WIN/filtered_WIN_data_counties.csv diff --git a/01_Data_raw/Weather/PLACEHOLDER.txt b/01_Data_raw/Weather/PLACEHOLDER.txt new file mode 100644 index 0000000..87e47d2 --- /dev/null +++ b/01_Data_raw/Weather/PLACEHOLDER.txt @@ -0,0 +1,2 @@ +REMOVE THIS FILE AFTER ADDING DATA TO THIS FOLDER. +This is jsut so the folders are saved to Git. \ No newline at end of file diff --git a/02_Cleaning_scripts/HAB_FWC.R b/02_Cleaning_scripts/HAB_FWC.R index 499e011..32f9f08 100644 --- a/02_Cleaning_scripts/HAB_FWC.R +++ b/02_Cleaning_scripts/HAB_FWC.R @@ -11,13 +11,7 @@ library(tidyverse) -HAB <- read_csv("01_Data_raw/HAB/HAB_FWC.csv") - -# Save it as an .Rdata file so it can be read into the Shiny app -save(HAB, file = "03_Data_for_app/HAB.RData") - -saveRDS(HAB, "03_Data_for_app/HAB.Rds") - +HAB <- read_csv("01_Data_raw/Water_Quality/HAB/HAB_FWC.csv") # Create long format so it can be used in the Shiny app @@ -28,7 +22,8 @@ HAB <- HAB %>% names_to = "vars", values_to = "vals") HAB$Date <- dmy(HAB$`Sample Date`) -save(HAB, file = "03_Data_for_app/HAB.RData") +# Save it as an .Rds file so it can be read into the Shiny app +saveRDS(HAB, "03_Data_for_app/HAB.Rds") # Check all unique categories unique(HAB$Description) diff --git a/02_Cleaning_scripts/WIN_data_clean.R b/02_Cleaning_scripts/WIN_data_clean.R index 5f61138..6b0c28e 100644 --- a/02_Cleaning_scripts/WIN_data_clean.R +++ b/02_Cleaning_scripts/WIN_data_clean.R @@ -9,7 +9,24 @@ library(tidyverse) GTMNERR <- st_read("03_Data_for_app/shapefiles_new/counties_GTMNERR.shp") # CRS: NAD83 / UTM zone 17N # WIN Data -gps_data <- read.csv("./01_Data_raw/WIN/WIN_data_merged_20240501.csv") + +# Already select which variables we want straightaway. Saves resources. Pick +# things that have "Org" in the name because those are the units/names/etc +# submitted by the sampling organization - which should be the GTM for this (?) +gps_data <- read_csv("./01_Data_raw/Water_Quality/WIN/WIN_data_merged_20240501.csv", + col_select = c(`Monitoring Location ID`, `Activity Type`, + `Activity Start Date Time`, `Activity Depth`, + `DEP Result ID`, `Org Analyte Name`, `Org Result Value`, + `Org Result Unit`, `Org MDL`, `RowID`, `LocationID`, + `Station ID`, `Station Name`, `Station Type`, `County`, + `Location_1`, `Location_2`)) + +lookup_names <- read_csv("03_Data_for_app/WQ_lookup_names.csv") + +# Change column names so we can later merge this with other WQ data +recode_vec <- setNames(lookup_names$original_name, lookup_names$dashboard_name) +gps_data <- gps_data %>% + rename(any_of(recode_vec)) #### GTMNERR boundary and aquatic preserves #### @@ -41,7 +58,7 @@ bound_box <- st_bbox(st_sfc(pt1, pt3, pt4, pt2, crs = st_crs(GTMNERR))) # Filter GPS coordinates # Convert to sf object -gps_sf <- st_as_sf(gps_data, coords = c("Location_2", "Location_1"), crs = 4326) +gps_sf <- st_as_sf(gps_data, coords = c("Longitude", "Latitude"), crs = 4326) # Crop GPS points within the bounding box gps_cropped <- st_crop(gps_sf, bound_box) @@ -65,16 +82,16 @@ coordinates <- st_coordinates(gps_cropped) WIN_df <- cbind(WIN_df, coordinates) # Rename the coordinates columns if necessary -colnames(WIN_df)[(ncol(WIN_df)-1):ncol(WIN_df)] <- c("longitude", "latitude") +colnames(WIN_df)[(ncol(WIN_df)-1):ncol(WIN_df)] <- c("Longitude", "Latitude") #### Keep only columns with varying information #### # Function to remove columns with the same value in the whole column -remove_constant_columns <- function(df) { - df <- df[, sapply(df, function(col) length(unique(col)) > 1)] - return(df) -} - -WIN_df <- remove_constant_columns(WIN_df) +# remove_constant_columns <- function(df) { +# df <- df[, sapply(df, function(col) length(unique(col)) > 1)] +# return(df) +# } +# +# WIN_df <- remove_constant_columns(WIN_df) #### Reformat data to visualize easily #### # turn WIN_df into long format with the following columns @@ -83,23 +100,15 @@ WIN_df <- remove_constant_columns(WIN_df) # Convert all columns to character before pivoting and retain the original row identifier WIN_df <- WIN_df %>% - select(-all_of(c("Station.ID", - "Station.Name", - "Org.Analyte.Name", - "DEP.Result.Value.Number", - "DEP.MDL", - "DEP.PQL", - "Org.Detection.Unit", - "Org.Result.Unit", - "Activity.End.Date.Time"))) %>% + # Add a column to record the data source/provider + mutate(data_source = "WIN") %>% # or change this to DEP? mutate(across(everything(), as.character)) %>% mutate_all(~ na_if(., "")) %>% pivot_longer( cols = -c(RowID), # Exclude the Row_ID column from pivoting names_to = "variable", values_to = "value" - ) %>% - mutate(value = na_if(value, "")) + ) # filter(!is.na(value) & value != "") # use this if space is an issue #### Save data #### @@ -107,5 +116,6 @@ WIN_df <- WIN_df %>% # write.csv(WIN_df, # "03_Data_for_app/Filtered_WIN_data_merged_20240501.csv", # row.names = FALSE) -# Save the filtered data to a .RData file -save(WIN_df, file = "03_Data_for_app/WIN.RData") +# Save the filtered data to a .RDs file + +saveRDS(WIN_df, "03_Data_for_app/WIN.Rds") diff --git a/02_Cleaning_scripts/WQ_GTMNERR.R b/02_Cleaning_scripts/WQ_GTMNERR.R index 34ffe2d..3fb2b44 100644 --- a/02_Cleaning_scripts/WQ_GTMNERR.R +++ b/02_Cleaning_scripts/WQ_GTMNERR.R @@ -13,7 +13,7 @@ library(tidyverse) library(readxl) ### 1. Read in data ----------------------------------------------------------- -WQ <- read_excel("01_Data_raw/Guana_WQ/Guana_masterdata.xlsx", +WQ <- read_excel("01_Data_raw/Water_Quality/Guana_WQ/Guana_masterdata.xlsx", sheet = 1, # There is only one sheet, but just to be safe guess_max = 13000) # This is not ideal + cols 14 and 16 have a # mix of logical and numbers. Lord. @@ -24,10 +24,17 @@ WQ <- read_excel("01_Data_raw/Guana_WQ/Guana_masterdata.xlsx", #col_types = c("SampleDate" = "date", "#RQ" = "text")) # If not specified you get # warnings (as it expects logical; text only starts after row 1445) -WQ_meta <- read_csv("01_Data_raw/Guana_WQ/guana_data_dictionary_updateGK.csv") +WQ_meta <- read_csv("01_Data_raw/Water_Quality/Guana_WQ/guana_data_dictionary_updateGK.csv") # Some stations have two codes due to a name change (see Word doc with metadata) # Don't remove +lookup_names <- read_csv("03_Data_for_app/WQ_lookup_names.csv") + +# Change column names so we can later merge this with other WQ data +recode_vec <- setNames(lookup_names$original_name, lookup_names$dashboard_name) +WQ <- WQ %>% + rename(any_of(recode_vec)) + ### 2. Check categorical values ------------------------------------------------ # Check station names, componentLong and componentShort (spelling etc) unique(WQ$StationCode) @@ -60,38 +67,61 @@ unique(WQ$Remark) # inconsistent... But there are some capital letters that # Change station code column name so it is the same as the column in the data names(WQ_meta)[names(WQ_meta) == "station_code"] <- "StationCode" +WQ$StationCode <- str_trim(WQ$StationCode) + WQ <- WQ %>% - left_join(WQ_meta) %>% - select(-Lat, -Long) + left_join(WQ_meta, by = c("StationCode")) %>% # not all stations in the original have lat/lon + mutate(Latitude = coalesce(Latitude.y, Latitude.x), + Longitude = coalesce(Longitude.y, Longitude.x)) %>% + select(-c(Latitude.x, Latitude.y, Longitude.x, Longitude.y)) # Stations missing from metadata: GL1.5, GL2.5 and GL3.5 -> added manually and # emailed Nikki -which(is.na(WQ$lat)) -which(is.na(WQ$long)) +# Check +which(is.na(WQ$Latitude)) +which(is.na(WQ$Longitude)) + +# There is GTMMOLNUT and GTMMOLNUT_dup...? I think we can leave it in for now;I give +# them the same site, site acronym and site friendly name... +# And GTMLMNUT is the same? But DEP code? Fix this... + +# WQ[which(is.na(WQ$Latitude)),] # duplicates?? +# WQ <- WQ[-which(is.na(WQ$Latitude)),] + +# Some station codes appear to have changed over time. Make sure only one code is +# reflected (otherwise we have issues with the dashboard) +# GTMDNNUT -> GTMLSNUT (Lake South) +# GTMDSNUT -> GTMRNNUT (River North) +# GTMOLNUT and GTMOLNUT_dup -> GTMLMNUT + +replacement <- data.frame(StationCode = c("GTMDNNUT", "GTMDSNUT", "GTMOLNUT", "GTMOLNUT_dup"), + StationCode_repl = c("GTMLSNUT", "GTMRNNUT", "GTMLMNUT", "GTMLMNUT")) -WQ[which(is.na(WQ$lat)),] # duplicates?? Remove for now; emailed Nikki -WQ <- WQ[-which(is.na(WQ$lat)),] +WQ <- WQ %>% + left_join(replacement, by = "StationCode") %>% + mutate(StationCode = coalesce(StationCode_repl, StationCode)) %>% + select(-StationCode_repl) # Create a separate dataframe with only station info, not the data (makes map # too heavy) WQ_locations <- WQ %>% mutate(Year = year(SampleDate)) %>% - select(site_friendly, Year, site_acronym, lat, long, wbid, location) %>% - group_by(site_friendly, site_acronym, lat, long, wbid, location) %>% - summarize(maxYear = max(Year), minYear = min(Year)) + select(site_friendly, Year, site_acronym, Latitude, Longitude, wbid, location) %>% + group_by(site_friendly, site_acronym, Latitude, Longitude, wbid, location) %>% + summarize(maxYear = max(Year), minYear = min(Year)) %>% + mutate(type = "Water quality", + dataset = "Guana Water Quality Monitoring (GTMNERR)") WQ_data_available <- WQ %>% mutate(Year = year(SampleDate)) %>% select(StationCode, Year, SampleType, ComponentShort, ComponentLong, site_friendly, - site_acronym, lat, long, wbid, location) %>% + site_acronym, Latitude, Longitude, wbid, location) %>% distinct() ### 4. Save data --------------------------------------------------------------- -# Save it as an .Rdata (and .Rds?) file so it can be read into the Shiny app -save(WQ, file = "03_Data_for_app/WQ.RData") +# Save it as an .Rds file so it can be read into the Shiny app saveRDS(WQ, "03_Data_for_app/WQ.Rds") -save(WQ_locations, file = "03_Data_for_app/WQ_locations.RData") saveRDS(WQ_locations, "03_Data_for_app/WQ_locations.Rds") diff --git a/02_Cleaning_scripts/WQ_WIN_merge.R b/02_Cleaning_scripts/WQ_WIN_merge.R new file mode 100644 index 0000000..38b9f27 --- /dev/null +++ b/02_Cleaning_scripts/WQ_WIN_merge.R @@ -0,0 +1,125 @@ +######################################################################## +########## NERRS Science Transfer project - GTMNERR ############# +######################################################################## + +# Geraldine Klarenberg, PhD +# gklarenberg@ufl.edu +# 12 August 2024 + +# Load packages +library(tidyverse) + +# Merge WIN and WQ data into one + +WIN <- readRDS("03_Data_for_app/WIN.Rds") +WQ_GTMNERR <- readRDS("03_Data_for_app/WQ.Rds") + +# Make WQ_GTMNERR long format as well, just like WIN +# Having a column for the dates is advisable though, as it is a separate data +# type. Update that later, not right now. + +#### We need to update the variable list so the names are the same! + +# First make sure that every row has a UNID and also add a column for the data +# source / provider +WQ_GTMNERR <- WQ_GTMNERR %>% + mutate(data_source = "GTMNERR") %>% + arrange(UNID, StationCode, SampleDate, ComponentShort) + +for (i in 1:nrow(WQ_GTMNERR)){ + if (is.na(WQ_GTMNERR$UNID[i])){ + WQ_GTMNERR$UNID[i] <- WQ_GTMNERR$UNID[i-1] + 1 + } +} +# Check there are no duplicates +sum(duplicated(WQ_GTMNERR$UNID)) + +# Add a geometry column, to later use for clicking markers (we might change this) +WQ_GTMNERR <- st_as_sf(WQ_GTMNERR, coords = c("Longitude", "Latitude"), + crs = 4326, remove = FALSE) +# Turn back into dataframe with geometry as a column +WQ_GTMNERR <- as.data.frame(WQ_GTMNERR) + +WQ_GTMNERR_long <- WQ_GTMNERR %>% + mutate(across(everything(), as.character)) %>% + mutate_all(~ na_if(., "")) %>% + pivot_longer(cols = -UNID, + names_to = "variable", + values_to = "value") + +# How to deal with UNID when merging? Start counting anew (or add however far the +# one dataset is?) + +min(as.numeric(WQ_GTMNERR_long$UNID)) # 1 +max(as.numeric(WQ_GTMNERR_long$UNID)) # 17098 + +min(as.numeric(WIN$RowID)) # 55135 +max(as.numeric(WIN$RowID)) # 3677602 +# Appears there will be no overlap. Merge. + +WQ_GTMNERR_long <- WQ_GTMNERR_long %>% + rename(RowID = UNID) + +WQ_all <- WIN %>% + full_join(WQ_GTMNERR_long) + +unique(WQ_all$variable) +unique(WQ_all$value) + +# Read in the WQ vars lookup table and replace variables with the names we need +lookup_WQ_vars <- read_csv("03_Data_for_app/WQ_lookup_variables.csv") + +# # I am sure there is a nicer/quicker/tidyverse way of doing this, but whatevs for now +# for (i in 1:nrow(WQ_all)){ +# if (is.na(WQ_all$value[i])){ +# next +# } +# for (j in 1:nrow(lookup_WQ_vars)){ +# if (WQ_all$value[i] == lookup_WQ_vars$value[j]){ +# WQ_all$value[i] <- lookup_WQ_vars$new[j] +# } +# } +# } + +# Quicker way +WQ_all <- WQ_all %>% + left_join(lookup_WQ_vars, by = "value") %>% + mutate(value = coalesce(new, value)) %>% + select(-new) + +# Filter for only the things that we need: + +# In ComponentLong: + +# Air temperature +# Ammonium (filtered) +# Chlorophyll +# Chlorophyll a (corrected) +# Chlorophyll a (uncorrected) +# Fecal coliform +# Dissolved oxygen +# Organic carbon +# pH +# Salinity +# Specific conductance +# Total nitrogen (TKN + nitrate + nitrite) +# Phosphorus (total) +# Total dissolved solids +# Turbidity +# Water temperature + +# I did this as follows now but I am NOT happy about it and we should update it. +# Because this only removes the variables names but keeps everything else +# associated with that station (which might make things unnecesarily slow) +# Maybe we can do it by rowID? +selected_values <- c("Air temperature", "Ammonium (filtered)", "Chlorophyll", "Chlorophyll a (corrected)", + "Chlorophyll a (uncorrected)", "Fecal coliform", "Dissolved oxygen", "Organic carbon", + "pH", "Salinity", "Specific conductance", "Total nitrogen (TKN + nitrate + nitrite)", + "Phosphorus (total)", "Total dissolved solids", "Turbidity", "Water temperature") + +WQ_all <- WQ_all %>% + filter((variable == "ComponentLong" & value %in% selected_values) | variable != "ComponentLong") + + +# Save data +saveRDS(WQ_all, "03_Data_for_app/WQ_all.Rds") diff --git a/02_Cleaning_scripts/shapefile_cleanup.R b/02_Cleaning_scripts/shapefile_cleanup.R index f2f7991..cf99b63 100644 --- a/02_Cleaning_scripts/shapefile_cleanup.R +++ b/02_Cleaning_scripts/shapefile_cleanup.R @@ -55,7 +55,7 @@ pt4 <- st_point(c(xmax, ymax)) # Put together as sf object and get bounding box bound_box <- st_bbox(st_sfc(pt1, pt3, pt4, pt2, crs = st_crs(GTMNERR))) -##### Counties ##### +#### Counties ##### counties <- st_read("01_Data_raw/shapefiles/countyshore_areas_sep15/countyshore_areas_sep15.shp") # CRS: Albers Conical Equal Area counties <- st_transform(counties, crs = st_crs(GTMNERR)) @@ -79,7 +79,7 @@ st_write(counties_select, "03_Data_for_app/shapefiles_new/counties_GTMNERR.shp", append = FALSE) # Ignore warnings when writing data: checked saved shapefile and it is correct -##### Salt marshes ##### +#### Salt marshes ##### salt_marsh <- st_read("01_Data_raw/shapefiles/salt_marsh_2020/salt_marsh_2020.shp") # CRS: NAD83(HARN) / Florida GDL Albers -> for visualization this is not a problem, # for consistency I am still changing the CRS @@ -95,7 +95,7 @@ ggplot()+ st_write(salt_marsh, "03_Data_for_app/shapefiles_new/salt_marsh_GTMNERR.shp", append = FALSE) -##### Hydrology (several shapefiles) ##### +#### Hydrology (several shapefiles) ##### hydro_6 <- st_read("01_Data_raw/shapefiles/nhdwbd_huc6_dec17/nhdwbd_huc6_dec17.shp") # CRS: Albers Conical Equal Area hydro_6 <- st_transform(hydro_6, crs = st_crs(GTMNERR)) @@ -159,8 +159,7 @@ ggplot()+ # Look up differences between HUCs to add to metadata st_write(hydro_10_select, "03_Data_for_app/shapefiles_new/nhdwbd_huc10_dec17_GTMNERR.shp", append = FALSE) st_write(hydro_12_select, "03_Data_for_app/shapefiles_new/nhdwbd_huc12_dec17_GTMNERR.shp", append = FALSE) -#### CHECK WARNINGS of some values not being written (too long) ##### - +#### Checked warnings of some values not being written (too long): looks fine #### Water bodies #### waterbodies <- st_read("01_Data_raw/shapefiles/nhd24waterbody_dec17/nhd24waterbody_dec17.shp") diff --git a/03_Data_for_app/HAB.RData b/03_Data_for_app/HAB.RData deleted file mode 100644 index 432ac87..0000000 Binary files a/03_Data_for_app/HAB.RData and /dev/null differ diff --git a/03_Data_for_app/HAB.Rds b/03_Data_for_app/HAB.Rds index 385f844..d60719f 100644 Binary files a/03_Data_for_app/HAB.Rds and b/03_Data_for_app/HAB.Rds differ diff --git a/03_Data_for_app/WIN.RData b/03_Data_for_app/WIN.RData deleted file mode 100644 index 3eb8e96..0000000 Binary files a/03_Data_for_app/WIN.RData and /dev/null differ diff --git a/03_Data_for_app/WIN.Rds b/03_Data_for_app/WIN.Rds new file mode 100644 index 0000000..638d644 Binary files /dev/null and b/03_Data_for_app/WIN.Rds differ diff --git a/03_Data_for_app/WQ.RData b/03_Data_for_app/WQ.RData deleted file mode 100644 index 2fa7196..0000000 Binary files a/03_Data_for_app/WQ.RData and /dev/null differ diff --git a/03_Data_for_app/WQ.Rds b/03_Data_for_app/WQ.Rds index 2ac843a..b1f48dc 100644 Binary files a/03_Data_for_app/WQ.Rds and b/03_Data_for_app/WQ.Rds differ diff --git a/03_Data_for_app/WQ_all.Rds b/03_Data_for_app/WQ_all.Rds new file mode 100644 index 0000000..ec45b88 Binary files /dev/null and b/03_Data_for_app/WQ_all.Rds differ diff --git a/03_Data_for_app/WQ_locations.RData b/03_Data_for_app/WQ_locations.RData deleted file mode 100644 index c2b902d..0000000 Binary files a/03_Data_for_app/WQ_locations.RData and /dev/null differ diff --git a/03_Data_for_app/WQ_locations.Rds b/03_Data_for_app/WQ_locations.Rds index 93e0406..522cf04 100644 Binary files a/03_Data_for_app/WQ_locations.Rds and b/03_Data_for_app/WQ_locations.Rds differ diff --git a/03_Data_for_app/WQ_lookup_names.csv b/03_Data_for_app/WQ_lookup_names.csv new file mode 100644 index 0000000..5e8241f --- /dev/null +++ b/03_Data_for_app/WQ_lookup_names.csv @@ -0,0 +1,111 @@ +data_source,original_name,dashboard_name +WIN,Organization ID,OrganizationID +WIN,Monitoring Location ID,MonitoringLocationID +WIN,HUC12 Name,HUC12Name +WIN,Project ID,ProjectID +WIN,Activity ID,ActivityID +WIN,Activity Type,SampleType +WIN,Activity Start Date Time,SampleDate +WIN,Activity End Date Time,ActivityEndDateTime +WIN,Activity Time Zone,ActivityTimeZone +WIN,Media,Media +WIN,Matrix,Matrix +WIN,Sample Collection Type,SampleCollectionType +WIN,Sampling Agency Name,SamplingAgencyName +WIN,SampleCollectionEquipmentName,SampleCollectionEquipmentName +WIN,Activity Depth,ActivityDepth +WIN,Activity Depth Unit,ActivityDepthUnit +WIN,Relative Depth,RelativeDepth +WIN,Activity Top Depth,ActivityTopDepth +WIN,Activity Bottom Depth,ActivityBottomDepth +WIN,Activity Depth Top Bottom Unit,ActivityDepthTopBottomUnit +WIN,Total Depth,TotalDepth +WIN,Total Depth Unit,TotalDepthUnit +WIN,Activity Representative Ind,ActivityRepresentativeInd +WIN,Activity Comments,ActivityComments +WIN,Sampler Name,SamplerName +WIN,Field Blank Batch ID,FieldBlankBatchID +WIN,Equipment Blank Batch ID,EquipmentBlankBatchID +WIN,Trip Blank Batch ID,TripBlankBatchID +WIN,Master Activity ID,MasterActivityID +WIN,Activity Loaded Date,ActivityLoadedDate +WIN,Activity Updated Date,ActivityUpdatedDate +WIN,DEP Result ID,DEPResultID +WIN,Org Result ID,OrgResultID +WIN,DEP Analyte Group,DEPAnalyteGroup +WIN,DEP Analyte Name,DEP Analyte Name +WIN,ADaPT Analyte ID,ADaPTAnalyteID +WIN,Org Analyte Name,ComponentLong +WIN,Org Result Value,Result +WIN,Org Result Unit,Unit +WIN,Org MDL,OrgMDL +WIN,Org PQL,OrgPQL +WIN,Org Detection Unit,OrgDetectionUnit +WIN,DEP Result Value Number,DEP Result Value Number +WIN,DEP Result Value Text,DEPResultValueText +WIN,DEP Result Unit,DEP Result Unit +WIN,DEP MDL,DEPMDL +WIN,DEP PQL,DEPPQL +WIN,Value Qualifier,ValueQualifier +WIN,Sample Fraction,SampleFraction +WIN,Prep Method,PrepMethod +WIN,Preparation Date Time,PreparationDateTime +WIN,Preparation Time Zone,PreparationTimeZone +WIN,Analysis Method,AnalysisMethod +WIN,Analysis Date Time,AnalysisDateTime +WIN,Analysis Time Zone,AnalysisTimeZone +WIN,Lab ID,LabID +WIN,Lab Name,LabName +WIN,Lab Accreditation Authority,LabAccreditationAuthority +WIN,Result Comments,ResultComments +WIN,Lab Sample ID,LabSampleID +WIN,Method Batch ID,MethodBatchID +WIN,Analytical Batch ID,AnalyticalBatchID +WIN,Dilution,Dilution +WIN,Percent Moisture,PercentMoisture +WIN,Percent Recovery,PercentRecovery +WIN,Relative Percent Difference,RelativePercentDifference +WIN,Error,Error +WIN,Target Species,TargetSpecies +WIN,Finfish Size,FinfishSize +WIN,Finfish Unit,FinfishUnit +WIN,Result Value Type,ResultValueType +WIN,Statistical Base,StatisticalBase +WIN,Audit Censored Decisions,AuditCensoredDecisions +WIN,Result Loaded Date,ResultLoadedDate +WIN,Result Updated Date,ResultUpdatedDate +WIN,RowID,RowID +WIN,LocationID,LocationID +WIN,ProgramID,ProgramID +WIN,Station ID,StationCode +WIN,Station Name,site_friendly +WIN,Station Type,wbid +WIN,County,County +WIN,Start Date,StartDate +WIN,End Date,EndDate +WIN,Location_1,Latitude +WIN,Location_2,Longitude +GTMNERR,UNID,UNID +GTMNERR,StationCode,StationCode +GTMNERR,SampleDate,SampleDate +GTMNERR,SampleType,SampleType +GTMNERR,Lat,Latitude +GTMNERR,Long,Longitude +GTMNERR,ComponentShort,ComponentShort +GTMNERR,ComponentLong,ComponentLong +GTMNERR,Result,Result +GTMNERR,Remark,Remark +GTMNERR,Flag,Flag +GTMNERR,Unit,Unit +GTMNERR,MRL,MRL +GTMNERR,MDL,MDL +GTMNERR,Dilution,Dilution +GTMNERR,PQL,PQL +GTMNERR,DateRecieved,DateRecieved +GTMNERR,DateAnalyzed,DateAnalyzed +GTMNERR,TestComments,TestComments +GTMNERR,AnalysisMethod,AnalysisMethod +GTMNERR,Lab ID,LabID +GTMNERR,Lab Accredidation Authority,LabAccredidationAuthority +GTMNERR,Laboratory,Laboratory +GTMNERR,RQ#,RQ# \ No newline at end of file diff --git a/03_Data_for_app/WQ_lookup_names_creation.txt b/03_Data_for_app/WQ_lookup_names_creation.txt new file mode 100644 index 0000000..a47b595 --- /dev/null +++ b/03_Data_for_app/WQ_lookup_names_creation.txt @@ -0,0 +1,18 @@ +Guana Dashboard development +13 August 2024 + +For the water quality page, to streamline showing all the WQ data on one page, I manually created +a lookup table to change the headers of the separate files so they are the same. This way we can use +merge the datasets and use the existing functions on them. + +The headers comfr from the files App_dev/01_Data_raw/Water_Quality/WIN/WIN_data_merged_20240501.csv and +App_dev/01_Data_raw/Water_Quality/Guana_WQ/Guana_masterdata.xlsx. + +1. Copy-pasted the header names to App_dev/03_Data_for_app/WQ_lookup_names.csv and named the column original_name +2. Added a column data_sources with either WIN or GTMNERR +3. Created a column dashboard_name and copied all the names from original_name to it +4. For now (08/13/2024) I am only changing latitude, longitude, dates, sample type, components/analytes measured (DEP, not org) to the names in the GTMNERR data. For visualization purposes. We can rename the rest later (analytes themselves will also need to be renamed, as well as info on station names and types). +5. For the new names I also removed the spaces (because R inserts points there). + +23 August 2024 +Updated lookup table so the org result and analyte name are being used instead of DEP (Result and ComponentLong). Also turned "Station ID" into "StationCode", "Station Type" into "bid", and "Station Name" into "site_friendly". \ No newline at end of file diff --git a/03_Data_for_app/WQ_lookup_variables.csv b/03_Data_for_app/WQ_lookup_variables.csv new file mode 100644 index 0000000..87d2bea --- /dev/null +++ b/03_Data_for_app/WQ_lookup_variables.csv @@ -0,0 +1,109 @@ +value,new +"2,4-Dichlorophenoxyacetic acid","2,4-Dichlorophenoxyacetic acid" +"2,4,5-T","2,4,5-T" +Acesulfame K,Acesulfame K +Acetaminophen ,Acetaminophen +Acetamiprid,Acetamiprid +Afidopyropen,Afidopyropen +Air temperature,Air temperature +"Ammonium, Filtered",Ammonium (filtered) +"Ammonium, Filtered ",Ammonium (filtered) +AMPA,AMPA +Bentazon,Bentazon +Bentazon ,Bentazon +Benzovindiflupyr,Benzovindiflupyr +bird specific Helicobacter GFD genetic marker,bird specific Helicobacter GFD genetic marker +Bromide,Bromide +canine-specific DG3 Bacteroides genetic marker,canine-specific DG3 Bacteroides genetic marker +Carbamazepine,Carbamazepine +Carbamazepine ,Carbamazepine +Chloride,Chloride +Chlorophyll,Chlorophyll +Chlorophyll a- corrected,Chlorophyll a (corrected) +Chlorophyll a- uncorrected,Chlorophyll a (uncorrected) +"Chlorophyll a, Corrected (Monochromatic)",Chlorophyll a (corrected) +"Chlorophyll a, Uncorrected (Trichromatic)",Chlorophyll a (uncorrected) +Chlorophyll b (Trichromatic),Chlorophyll b (Trichromatic) +Chlorophyll c (Trichromatic),Chlorophyll c (Trichromatic) +Chlorophyll_bottom,Chlorophyll_bottom +Clothianidin,Clothianidin +coastal bird specific Catellicoccus marimammalium Gull2 genetic marker,coastal bird specific Catellicoccus marimammalium Gull2 genetic marker +"Coliform, Fecal",Fecal coliform +Color (true),Color (true) +Copper,Copper +Dinotefuran,Dinotefuran +Dissolved Oxygen,Dissolved oxygen +Dissolved Oxygen Saturation,Dissolved Oxygen Saturation +"Dissolved oxygen, bottom","Dissolved oxygen, bottom" +"Dissolved oxygen, percent saturation","Dissolved oxygen, percent saturation" +"Dissolved oxygen, percent saturation, bottom","Dissolved oxygen, percent saturation, bottom" +Diuron,Diuron +Endothall,Endothall +Enterococcus,Enterococcus +Escherichia Coli-Quanti-Tray,Escherichia Coli-Quanti-Tray +Fenuron,Fenuron +Fluoride,Fluoride +Fluridone,Fluridone +Fluridone ,Fluridone +Glufosinate,Glufosinate +Glyphosate,Glyphosate +human-specific HF183 Bacteroides genetic marker,human-specific HF183 Bacteroides genetic marker +Hydrocodone,Hydrocodone +Hydrocodone ,Hydrocodone +Ibuprofen,Ibuprofen +Ibuprofen ,Ibuprofen +Imazapyr,Imazapyr +Imidacloprid,Imidacloprid +"Kjeldahl Nitrogen, Filtered","Kjeldahl Nitrogen, Filtered" +"Kjeldahl Nitrogen, Filtered ","Kjeldahl Nitrogen, Filtered " +Linuron,Linuron +Mandestrobin,Mandestrobin +Methylchlorophenoxypropionic acid,Methylchlorophenoxypropionic acid +Naproxen,Naproxen +Nitrate+Nitrite,Nitrate+Nitrite +"Nitrogen, Kjeldahl",TKN (Total Kjeldahl nitrogen: ammonia nitrogen + organic nitrogen) +"Nitrogen, Nitrite (NO2) + Nitrate (NO3) as N",Total nitrogen (TKN + nitrate + nitrite) +OD664b/OD665a,OD664b/OD665a +Organic Carbon,Organic carbon +Orthophosphate,Orthophosphate +Orthophosphate ,Orthophosphate +"Orthophosphate, Filtered","Orthophosphate, Filtered" +pH,pH +"pH, bottom","pH, bottom" +Phaeophytin a,Phaeophytin a +Pheophytin a,Pheophytin a +Phosphorus- Total,Phosphorus (total) +Phycoerythrin,Phycoerythrin +"Phycoerythrin, bottom","Phycoerythrin, bottom" +Primidone,Primidone +Pyraclostrobin,Pyraclostrobin +Ruminant specific Bacteroidetes BacR genetic marker,Ruminant specific Bacteroidetes BacR genetic marker +Salinity,Salinity +"Salinity, bottom","Salinity, bottom" +Secchi Disk,Secchi Disk +Silvex,Silvex +Specific Conductance,Specific conductance +"Specific Conductance, bottom","Specific Conductance, bottom" +Sucralose,Sucralose +Sulfate,Sulfate +TDS,Total dissolved solids +"Temperature, Water",Water temperature +Thiamethoxam,Thiamethoxam +Tolfenpyrad,Tolfenpyrad +Total Alkalinity ,Total Alkalinity +Total Kjeldahl Nitrogen,TKN (Total Kjeldahl nitrogen: ammonia nitrogen + organic nitrogen) +Total Kjeldahl Nitrogen ,TKN (Total Kjeldahl nitrogen: ammonia nitrogen + organic nitrogen) +Total Kjeldahl Nitrogen ,TKN (Total Kjeldahl nitrogen: ammonia nitrogen + organic nitrogen) +Total Kjeldahl Nitrogen Filtered,Total Kjeldahl Nitrogen Filtered +Total Nitrogen,Total nitrogen (TKN + nitrate + nitrite) +Total Phosphorus,Phosphorus (total) +Total Phosphorus ,Phosphorus (total) +Total Suspended Solids,Total dissolved solids +Triclopyr,Triclopyr +Turbidity,Turbidity +Turbidity ,Turbidity +Water Depth,Water Depth +Water temperature,Water temperature +"Water temperature, bottom","Water temperature, bottom" +Wind Direction,Wind Direction +Wind Speed,Wind Speed \ No newline at end of file diff --git a/03_Data_for_app/WQ_lookup_variables_creation.txt b/03_Data_for_app/WQ_lookup_variables_creation.txt new file mode 100644 index 0000000..3d1c8a0 --- /dev/null +++ b/03_Data_for_app/WQ_lookup_variables_creation.txt @@ -0,0 +1,31 @@ +Name: Geraldine Klarenberg +Date: 26 August 2024 + +Created a .csv file as a lookup table to convert names of variables (i.e. analytes) to the same names so we can actually use it in a dropdown. For now I am only changing the ones that we will use in the first prototype of the dashboard. + +1. From WIN_data_merged_20240501 I took all the unique names listed in the column "Org Analyte Name". +2. For the Guana WQ (NUTS?) data I took the unique names in the column ComponentLong in Guana_masterdata.xlsx +3. These were put in the column "original" in the lookup table: 108 variables. Note that some variable names appear duplicated, but that is because some have trailing blanks/white spaces after the names (which R will pick up as a "different" name). +4. These were sorted alphabetically. +5. The following consistent variables names were used and put in the column "new", on the row with the associated original variable name: + +Air temperature +Ammonium (filtered) +Chlorophyll +Chlorophyll a (corrected) +Chlorophyll a (uncorrected) +Fecal coliform +Dissolved oxygen +Organic carbon +pH +Salinity +Specific conductance +Total nitrogen (TKN + nitrate + nitrite) +Phosphorus (total) +Total dissolved solids +Turbidity +Water temperature + +NOTE: The nitrogen variables need to be updated/checked, as right now I do not have the detailed data dictionary for the WIN data. + +6. For the remaining variables the original name was copy-pasted in the "new" column. \ No newline at end of file diff --git a/04_Tests/leaflet_test.R b/04_Tests/leaflet_test.R index 327c117..baf9dd6 100644 --- a/04_Tests/leaflet_test.R +++ b/04_Tests/leaflet_test.R @@ -15,12 +15,23 @@ GTMNERR <- st_read("03_Data_for_app/shapefiles_new/GTMNERR.shp")# CRS: Albers Co GTMNERR <- st_transform(GTMNERR, crs = 4326) -m <- leaflet(data = GTMNERR, options = leafletOptions(minZoom = 9, maxZoom = 18)) %>% - #setView(lng=-81.347388, lat=30.075, zoom = 11) %>% +# Leaflet uses EPSG 3857, change this +# https://gis.stackexchange.com/questions/48949/epsg-3857-or-4326-for-web-mapping +#epsg4326 <- leafletCRS(crsClass = "L.CRS.EPSG4326") +# BUT! It actually seems that Leaflet does still want shapefiles in 4326, see +# https://github.com/Leaflet/Leaflet/issues/4146 I also tried to change GTMNERR +# to crs 3857 but that threw errors. See second paragraph here: +# https://rstudio.github.io/leaflet/articles/projections.html + +m <- leaflet(data = GTMNERR, + options = leafletOptions(#crs = epsg4326, + minZoom = 9, + maxZoom = 18)) %>% + setView(lng=-81.289, lat=29.905, zoom = 11) %>% clearBounds() %>% addTiles() %>% # Add default OpenStreetMap map tiles - addPolygons(color = "purple", fill = NA) #%>% - #addMarkers(lng=-81.347388, lat=30.075, popup="Guana") + addPolygons(color = "purple", fill = NA) %>% + addMarkers(lng=-81.347388, lat=30.075, popup="Guana") m counties_select <- st_read("03_Data_for_app/shapefiles_new/counties_GTMNERR.shp") @@ -45,10 +56,15 @@ leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18)) %>% highlightOptions = highlightOptions(color = "white", weight = 2, bringToFront = TRUE), group = "Counties", popup = ~NAME) %>% - addMarkers(data = HAB_data_locations, - popup = ~paste("Site: ", Site, "
", - "County: ", County), - group = "HAB") %>% + addAwesomeMarkers(icon = makeAwesomeIcon(icon = "flask", markerColor = "blue", library = "fa", + iconColor = "black"), #"", + data = HAB_data_locations, + #lng= rep(-81.347388, 34), lat = rep(30.075,34) + ) %>% + # addMarkers(data = HAB_data_locations, + # popup = ~paste("Site: ", Site, "
", + # "County: ", County), + # group = "HAB") %>% # # Layers control (turning layers on and off) addLayersControl(overlayGroups = c("Counties", "GTMNERR boundaries", "HAB"), options = layersControlOptions(collapsed = FALSE)) diff --git a/04_Tests/plotly_testing_WQ.R b/04_Tests/plotly_testing_WQ.R new file mode 100644 index 0000000..d24f19a --- /dev/null +++ b/04_Tests/plotly_testing_WQ.R @@ -0,0 +1,88 @@ +# Plotly practice / test + +# filter first based on filter_value, which is the StationCode from the clicked station +# then create dropdown with available data -> create reactive selected_column() +# create plot using selected_column() + +# inputs: df, units_df, loc_name = "GTMNERR", selected_column() + +WQ_df <- readRDS("./03_Data_for_app/WQ_all.Rds") + +filter_value = "GTMSSNUT" +df = WQ_df + +if (!is.null(filter_value)) { + # Step 1: Identify the relevant RowIDs + relevant_row_ids <- df %>% + filter(value == filter_value) %>% + pull(RowID) + + # Step 2: Filter the entire dataframe to keep only rows with the relevant RowIDs + filtered_df <- df %>% + filter(RowID %in% relevant_row_ids) +} else { + # If no filter_value is provided, skip the filtering step + filtered_df <- df +} + +wide_df <- filtered_df %>% + # 30 August 2024: after updating the station names for some of the Guana station, + # it seems like there are duplicates for some variable/value pairs. So that would/ + # should mean that it's exactly the same, so we can just pick one. If we don't, we + # end up with a vector for the ComponentLong name. Keep the first value. + pivot_wider(names_from = variable, values_from = value, values_fn = first) %>% + filter(!is.na(ComponentLong)) %>% + select(SampleDate, # we could also make these arguments for the function? + ComponentLong, + Result, + geometry, StationCode, site_friendly) %>% + pivot_wider(names_from = ComponentLong, + values_from = Result, + values_fn = list(Result = ~ mean(as.numeric(.), na.rm = TRUE))) %>% + mutate(SampleDate = ymd_hms(SampleDate)) %>% # + #mutate(SampleDate = str_extract(SampleDate, "[0-9]{4}-[0-9]{2}-[0-9]{2}")) %>% + #mutate(SampleDate = ymd(SampleDate)) %>% # these two lines are another option to only get ymd + mutate(across(-c(SampleDate, geometry, StationCode, site_friendly), ~ as.numeric(.))) %>% + mutate(SampleDate = as.Date(SampleDate)) %>% + group_by(SampleDate, geometry, StationCode, site_friendly) %>% + summarize(across(everything(), ~mean(.x, na.rm = TRUE))) #%>% # across(everything()) is not necessary, +# strictly speaking, but it's nice to keep for if we ever want to adjust this function +# to work for more than 1 variable +#select(where(~ n_distinct(.) > 2)) +############## + +# CHECK: there is a column called NA?? +df <- wide_df + +selected_column = "Air temperature" # does not exist for GTMSSNUT +units_df = WQ_data_units + +fig <- plot_ly(df, x = ~SampleDate) + +# Get the column names except the dates and column names and geometry +column_names <- sort(colnames(df)[!colnames(df) %in% c("SampleDate", "geometry", "StationCode", "site_friendly")]) + +# Create a named vector for Y-axis titles +y_axis_titles <- setNames(units_df$Unit, units_df$ComponentLong) + +# Ensure selected_column is not NULL or empty +if (is.null(selected_column) || selected_column == "") { + selected_column <- column_names[1] +} + +if (selected_column %in% names(df)) { # only plot if variable exists for that station + #create_plot(df, units_df = WQ_data_units, loc_name = unique(df$site_friendly), selected_column = selected_column()) +} else { + plot_ly(type = 'scatter', mode = 'markers') %>% + layout(title = "No data available", xaxis = list(visible = FALSE), yaxis = list(visible = FALSE)) +} + +# Loop through each column and add a trace +for (i in seq_along(column_names)) { + fig <- fig %>% + add_trace(y = df[[column_names[i]]], name = column_names[i], type = 'scatter', mode = 'lines+markers', + showlegend = FALSE, + visible = if (column_names[i] == selected_column) TRUE else FALSE) +} + +fig diff --git a/app.R b/app.R index 39efe18..38065ba 100644 --- a/app.R +++ b/app.R @@ -1,40 +1,65 @@ -# This is the main app page, which will run and read in all the other pages -# and modules, and render the dashboard - -# Note: not necessary to load packages here: this all happens in global.R - -source("global.R") -source("functions.R") -source("modules/main_page.R") -source("modules/waterquality.R") -source("modules/algae.R") -source("modules/win.R") - -ui <- dashboardPage( - dashboardHeader(title = "Guana River Data Dashboard"), - dashboardSidebar( - sidebarMenu(id = "tabs", - menuItem("Main Page", tabName = "main_page", icon = icon("home")), - menuItem("Water Quality Data", tabName = "waterquality", icon = icon("link")), - menuItem("Harmful Algal Bloom Data", tabName = "algae", icon = icon("link")), - menuItem("Water Information Network", tabName = "win", icon = icon("bridge-water", lib="font-awesome")) - ) - ), - dashboardBody( - tabItems( - tabItem(tabName = "main_page", mainPageUI(id = "main_page")), - tabItem(tabName = "waterquality", WQPageUI(id = "waterquality")), - tabItem(tabName = "algae", HABPageUI(id = "algae")), - tabItem(tabName = "win", WINPageUI(id = "win")) - ) - ) -) - -server <- function(input, output, session) { - moduleServer(module = mainPageServer, id = "main_page", session = session) - WQPageServer("waterquality", parentSession = session) - HABPageServer("algae", parentSession = session) - WINPageServer("win", parentSession = session) -} - -shinyApp(ui, server) +# This is the main app page, which will run and read in all the other pages +# and modules, and render the dashboard + +# Note: not necessary to load packages here: this all happens in global.R + +source("global.R") +source("functions.R") +source("modules/main_page.R") +source("modules/waterquality.R") +source("modules/algae.R") +#source("modules/win.R") + +ui <- dashboardPage( + dashboardHeader(title = "Guana River Data Dashboard"), + dashboardSidebar( + sidebarMenu(id = "tabs", + menuItem("MAIN PAGE", tabName = "main_page", icon = icon("home")), + menuItem("Water Quality Data", tabName = "waterquality", + icon = icon("flask-vial", lib="font-awesome"), + badgeLabel = "New!", badgeColor = "green"), + menuItem("Harmful Algal Bloom Data", tabName = "algae", + icon = icon("microscope", lib = "font-awesome"), + badgeLabel = "Coming soon", badgeColor = "yellow"), + menuItem("Water Level Data", tabName = "waterlevel", + icon = icon("water", lib="font-awesome"), + badgeLabel = "Under construction", badgeColor = "light-blue"), + menuItem("Fish and Shellfish", tabName = "shellfish", + icon = icon("fish", lib="font-awesome"), + badgeLabel = "Under construction", badgeColor = "light-blue"), + menuItem("Terrestrial Animal Data", tabName = "animal", + icon = icon("paw", lib="font-awesome"), + badgeLabel = "Under construction", badgeColor = "light-blue"), + menuItem("Vegetation Data", tabName = "animal", + icon = icon("seedling", lib="font-awesome"), + badgeLabel = "Under construction", badgeColor = "light-blue") + ), + # Custom CSS to adjust the vertical position of the menu items + tags$style(HTML(" + .main-sidebar { + display: flex; + flex-direction: column; + } + .sidebar-menu > li { + margin-top: 10px; + margin-bottom: 10px; + } + ")) + ), + dashboardBody( + tabItems( + tabItem(tabName = "main_page", mainPageUI(id = "main_page")), + tabItem(tabName = "algae", HABPageUI(id = "algae")), + tabItem(tabName = "waterquality", WINPageUI(id = "waterquality")) + ) + ) +) + +server <- function(input, output, session) { + moduleServer(module = mainPageServer, id = "main_page", session = session) + #WQPageServer("waterquality", parentSession = session) + HABPageServer("algae", parentSession = session) + WINPageServer("waterquality", parentSession = session) +} + +shinyApp(ui, server) diff --git a/global.R b/global.R index ba70b3d..ab8c38a 100644 --- a/global.R +++ b/global.R @@ -40,10 +40,23 @@ try({ print(paste0("Working dir: ", getwd())) }, silent = FALSE) # Setting silent = FALSE will print the error message to the console -#### GTMNERR shapefile ------------------------------------------------ -GTMNERR <- st_read("./03_Data_for_app/shapefiles_new/GTMNERR.shp") -GTMNERR <- st_transform(GTMNERR, crs = 4326) +### Load shapefiles ------------------------------------------------ -#### county shapefiles ------------------------------------------------ +##### GTMNERR shapefile ------------------------------------------------ +GTMNERR <- st_read("./03_Data_for_app/shapefiles_new/GTMNERR_small_nosea.shp") + +##### county shapefiles ------------------------------------------------ counties_select <- st_read("./03_Data_for_app/shapefiles_new/counties_GTMNERR.shp") -counties_select <- st_transform(counties_select, crs = 4326) + +##### HUC shapefiles ------------------------------------------------ +HUC10 <- st_read("./03_Data_for_app/shapefiles_new/nhdwbd_huc10_dec17_GTMNERR.shp") +HUC12 <- st_read("./03_Data_for_app/shapefiles_new/nhdwbd_huc12_dec17_GTMNERR.shp") + +##### Outstanding Florida Waters (OFW) shapefiles ------------------------------ +ofw <- st_read("./03_Data_for_app/shapefiles_new/ofw_GTMNERR.shp") + +##### mangrove shapefiles ----------------------------------------------------- +mangroves <- st_read("./03_Data_for_app/shapefiles_new/mangrove_GTMNERR.shp") + +##### salt marsh shapefiles ----------------------------------------------------- +saltmarsh <- st_read("./03_Data_for_app/shapefiles_new/salt_marsh_GTMNERR.shp") diff --git a/modules/main_page.R b/modules/main_page.R index 23b9b1b..d203635 100644 --- a/modules/main_page.R +++ b/modules/main_page.R @@ -1,17 +1,77 @@ +######################################################################## +########## NERRS Science Transfer project - GTMNERR ############# +######################################################################## + +# Geraldine Klarenberg, PhD +# gklarenberg@ufl.edu +# Created June 2024 +# Last updated: 12 August 2024 + +# This page shows a map, with a dropdown menu to pick types of +# datasets, as well as shapefiles for the area + +#### Get WIN data locations +# I am putting this here right now, but I feel we should move this to a cleaning +# script so it doesn't need to be run every time someone uses the app (as with +# WQ locations) +WIN_df <- readRDS("./03_Data_for_app/WIN.Rds") + +WIN_data_locations = WIN_df %>% + filter(variable %in% c("geometry", + "StationCode", + "SampleDate", + "Latitude", + "Longitude") + ) %>% + select(c(RowID, variable, value)) %>% + distinct(RowID, variable, value) %>% + pivot_wider( + names_from = variable, + values_from = value, + values_fill = list(value = NA) + ) %>% + distinct(geometry, StationCode, SampleDate, Latitude, Longitude) %>% + mutate( + SampleDate = ymd_hms(SampleDate), + Latitude = as.numeric(Latitude), + Longitude = as.numeric(Longitude), + type = "Water quality", + dataset = "Watershed Information Network (DEP)", # Update this so we use data_source + minYear = min(year(SampleDate)), + maxYear = max(year(SampleDate)) + ) %>% + select(-geometry, -SampleDate) + +#### WQ locations data ------------------------------------------------ +WQ_data_locations <- readRDS("./03_Data_for_app/WQ_locations.Rds") + +# For now, for testing, make WQ_locations the dataframe to be used for filtering +datasets_location <- full_join(WQ_data_locations, WIN_data_locations) +datasets_location <- st_as_sf(datasets_location, coords = c("Longitude", "Latitude"), crs = 4326) +datasets_location <- datasets_location[!duplicated(datasets_location),] + +color_palette <- colorFactor(palette = c("red", "goldenrod1"), #, "blue", "green" + domain = datasets_location$dataset) + +#### HAB locations data ------------------------------------------------ +# Add this at some point so there is another dataset that shows up in the dropdown +# menu + +### Define the UI ------------------------------------------------------------- mainPageUI <- function(id) { ns <- NS(id) # This is an important part to add to all subpages so they use the # correct sessions / ID's that connect the ui and server here tagList( - h2("Main Page"), - p("This is the main page of the Guana River Data Dashboard."), + h2("Welcome!"), + p("This is the main page of the Guana River Data Dashboard. Use the dropdown menu + below to see locations with data. To view these data, use the menu on the + left of the screen."), + # Dropdown menu for markers is above the map + fluidRow( + column(width = 7, uiOutput(ns("dropdown_ui")), style = "position:relative;z-index:10000;"), + ), fluidRow( - # Map occupies 1st column - column(width = 10, leafletOutput(ns("map"), height=750)), - # histogram occupies rows in the 2nd column - # column(width = 5, plotOutput(ns("distPlot")), - # sliderInput(ns("bins"), "Number of bins:", - # min = 1, max = 50, value = 30) - # ) + column(width = 10, leafletOutput(ns("map"), height="500px")), ), # fluidRow( # column(12, @@ -21,29 +81,27 @@ mainPageUI <- function(id) { ) } +### Define the server logic ---------------------------------------------------- mainPageServer <- function(input, output, session) { ns <- session$ns - # Create the histogram - # output$distPlot <- renderPlot({ - # # generate bins based on input$bins from ui.R - # x <- filter(WQ, ComponentShort == "ATEMP") %>% select(Result) %>% pull() - # x <- as.numeric(x) # stop-gap measure because everything is characters - # bins <- seq(min(x, na.rm = TRUE), max(x, na.rm = TRUE), - # length.out = input$bins + 1) - # - # # draw the histogram with the specified number of bins - # hist(x, breaks = bins, col = 'darkgray', border = 'white', - # xlab = 'Air temperature (degrees Celsius)', - # main = 'Histogram of air temperatures') - # }) + # Create the dropdown UI + output$dropdown_ui <- renderUI({ + print("Rendering dropdown UI") + selectInput( + inputId = ns("datatype_selector"), + label = "Select a type of data to see locations with data availability", + choices = unique(datasets_location$type), + selected = unique(datasets_location$type)[1] + ) + }) # Create the map output$map <- renderLeaflet({ - leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18)) %>% - #setView(lng=-81.347388, lat=30.075, zoom = 11) %>% - clearBounds() %>% # centers map on all min/max coords + leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18, scrollWheelZoom = FALSE)) %>% + setView(-81.289, lat=29.905, zoom = 10) %>% + #clearBounds() %>% # centers map on all min/max coords # Base map addTiles() %>% # Add default OpenStreetMap map tiles # Polygons, add groups @@ -55,22 +113,64 @@ mainPageServer <- function(input, output, session) { highlightOptions = highlightOptions(color = "white", weight = 2, bringToFront = TRUE), group = "Counties", popup = ~NAME) %>% - # addMarkers(data = HAB_data_locations, - # popup = ~paste("Site: ", Site, "
", - # "County: ", County), - # group = "HAB") %>% - addMarkers(data = WQ_data_locations, - popup = ~paste("Station: ", site_friendly, "
", - "Location: ", wbid, "
", - "Latest year of sampling: ", maxYear, "% - # # Layers control (turning layers on and off) - addLayersControl(overlayGroups = c("Counties", "GTMNERR boundaries", "WQ"), - options = layersControlOptions(collapsed = FALSE)) %>% - addMeasure(primaryLengthUnit = "miles", primaryAreaUnit = "sqmiles") + addPolygons(data = mangroves, + color = "darkgreen", weight = 2, opacity = 1, + fill = TRUE, fillColor = "darkgreen", fillOpacity = 0.4, + group = "Mangroves") %>% #, popup = ~Area_ha + addPolygons(data = ofw, + color = "darkorange", weight = 2, opacity = 1, + fill = TRUE, fillColor = "darkorange", fillOpacity = 0.4, + group = "Outstanding Florida Waters") %>% + addPolygons(data = saltmarsh, + color = "darkslateblue", weight = 2, opacity = 1, + fill = TRUE, fillColor = "darkslateblue", fillOpacity = 0.4, + group = "Salt marshes") %>% + addPolygons(data = HUC10, + color = "royalblue", weight = 2, opacity = 1, + fill = TRUE, fillColor = "royalblue", fillOpacity = 0.2, + group = "HUC10", popup = ~NAME) %>% + addPolygons(data = HUC12, + color = "darkblue", weight = 2, opacity = 1, + fill = TRUE, fillColor = "darkblue", fillOpacity = 0.2, + group = "HUC12", popup = ~NAME) %>% + # Layers control (turning layers on and off) + addLayersControl(overlayGroups = c("GTMNERR boundaries", "Counties", + "Mangroves", "Salt marshes", + "Outstanding Florida Waters", "HUC10", + "HUC12"), + options = layersControlOptions(collapsed = TRUE)) %>% + hideGroup(c("Counties", "Mangroves", "Salt marshes", + "Outstanding Florida Waters", "HUC10", "HUC12")) %>% + addMeasure(primaryLengthUnit = "miles", primaryAreaUnit = "sqmiles") }) + # Select dataset to add markers to the plot + observeEvent(input$datatype_selector, { + # Filter data based on selected group + filtered_data <- datasets_location[datasets_location$type == input$datatype_selector,] + print(filtered_data) + # Add markers to the map - commented out the popup bc this only works for WQ data + print("Adding markers") + leafletProxy(ns("map")) %>% + clearMarkers() %>% + addAwesomeMarkers(icon = makeAwesomeIcon(icon = "flask", markerColor = "orange", library = "fa", + iconColor = "black"), + data = filtered_data) #%>% + # addCircleMarkers( + # data = filtered_data, + # color = ~color_palette(dataset), + # opacity = 1, + # fillOpacity = 0.5, + # fillColor = ~color_palette(dataset), + # fill = TRUE, + # weight = 3, + # radius = 8, + # popup = ~paste("Station: ", site_friendly, "
", + # "Location: ", wbid, "
", + # "Latest year of sampling: ", maxYear, "% - st_as_sf(coords = c("long", "lat"), crs = 4326) +######################################################################## +########## NERRS Science Transfer project - GTMNERR ############# +######################################################################## -#### WQ data ------------------------------------------------ -load("./03_Data_for_app/WQ.RData") +# Geraldine Klarenberg, PhD +# Email: gklarenberg@ufl.edu +# Christopher Marais +# Email: +# Last updated: 12 August 2024 -WQPageUI <- function(id) { - ns <- NS(id) # This is an important part to add to all sub pages so they use the - # correct sessions / ID's that connect the ui and server here +library(tidyverse) + +# import all WQ data for this page (WIN and Guana spreadsheet) +WQ_df <- readRDS("./03_Data_for_app/WQ_all.Rds") + +#### Process data further #### +# MOVE THIS TO THE CLEANING SCRIPT!! +# make datframe for map display and hover data +WQ_data_locations = WQ_df %>% # site friendly and station code are the names in common + filter(variable %in% c("StationCode", "site_friendly", + "geometry", + #"HUC12Name", # Changed for now (bc GTM WQ data does not have that variable) BUT we should also include a station name of some sort + "SampleDate", # changed, from StartDate - but also not necessary for locations + "Latitude", + "Longitude", + "data_source") + ) %>% + #select(c(RowID, variable, value)) %>% # not necessary + #distinct(RowID, variable, value) %>% # not necessary + pivot_wider( + names_from = variable, + values_from = value, + values_fill = list(value = NA) + ) %>% + distinct(Latitude, Longitude, data_source, geometry, StationCode, site_friendly) %>% + mutate( + Latitude = as.numeric(Latitude), + Longitude = as.numeric(Longitude) + ) + +WQ_data_units = WQ_df %>% + filter(variable %in% c("ComponentLong", # some will be duplicated because they differ between the 2 sets + "Unit", "data_source") + ) %>% + #select(c(RowID, variable, value)) %>% + distinct(RowID, variable, value) %>% # strictly speaking also not necessary + pivot_wider( + names_from = variable, + values_from = value, + values_fill = list(value = NA), + values_fn = list(value = ~ first(.)) + ) %>% + distinct(ComponentLong, Unit, data_source) + +#### Functions #### +# make dataframe for click plots - filter for correct stations +filter_dataframe <- function(df, filter_value = NULL) { + if (!is.null(filter_value)) { + # Step 1: Identify the relevant RowIDs + relevant_row_ids <- df %>% + filter(value == filter_value) %>% + pull(RowID) + + # Step 2: Filter the entire dataframe to keep only rows with the relevant RowIDs + filtered_df <- df %>% + filter(RowID %in% relevant_row_ids) + } else { + # If no filter_value is provided, skip the filtering step + filtered_df <- df + } + + # Step 3: Create wide dataframe + wide_df <- filtered_df %>% + pivot_wider(names_from = variable, values_from = value, values_fn = first) %>% + filter(!is.na(ComponentLong)) %>% # stop gap measure because there are NAs from + # replacing ComponentLong names in the cleaning script + select(SampleDate, # we could also make these arguments for the function? + ComponentLong, + Result, + geometry, StationCode, site_friendly) %>% + pivot_wider(names_from = ComponentLong, + values_from = Result, + values_fn = list(Result = ~ mean(as.numeric(.), na.rm = TRUE))) %>% + mutate(SampleDate = ymd_hms(SampleDate)) %>% # + #mutate(SampleDate = str_extract(SampleDate, "[0-9]{4}-[0-9]{2}-[0-9]{2}")) %>% + #mutate(SampleDate = ymd(SampleDate)) %>% # these two lines are another option to only get ymd + mutate(across(-c(SampleDate, geometry, StationCode, site_friendly), ~ as.numeric(.))) %>% + mutate(SampleDate = as.Date(SampleDate)) %>% + group_by(SampleDate, geometry, StationCode, site_friendly) %>% + summarize(across(everything(), ~mean(.x, na.rm = TRUE))) #%>% # across(everything()) is not necessary, + # strictly speaking, but it's nice to keep for if we ever want to adjust this function + # to work for more than 1 variable + #select(where(~ n_distinct(.) > 2)) + + return(wide_df) +} + +# New function to create the dropdown +create_dropdown <- function(df, ns) { + # Get the column names except the dates and column names and geometry + column_names <- sort(colnames(df)[!colnames(df) %in% c("SampleDate", "geometry", "StationCode", "site_friendly")]) + print(paste("Creating dropdown with choices:", paste(column_names, collapse=", "))) + + selectInput( + inputId = ns("column_selector"), + label = "Select a Variable of Interest", + choices = column_names, + selected = column_names[1] + ) +} + +# Modified create_plot function +create_plot <- function(df, units_df, loc_name = NULL, selected_column) { + print(paste("Creating plot for", selected_column, "at", loc_name)) + # Initialize the plot with the x-axis + fig <- plot_ly(df, x = ~SampleDate) + + # Get the column names except the dates and column names and geometry + column_names <- sort(colnames(df)[!colnames(df) %in% c("SampleDate", "geometry", "StationCode", "site_friendly")]) + + # Create a named vector for Y-axis titles + y_axis_titles <- setNames(units_df$Unit, units_df$ComponentLong) + + # Ensure selected_column is not NULL or empty + # if (is.null(selected_column) || selected_column == "") { + # selected_column <- column_names[1] + # } + + # Loop through each column and add a trace + for (i in seq_along(column_names)) { + fig <- fig %>% + add_trace(y = df[[column_names[i]]], name = column_names[i], type = 'scatter', mode = 'lines+markers', + showlegend = FALSE, + visible = if (column_names[i] == selected_column) TRUE else FALSE) + } + + station_name <- unique(df$StationCode) + + # Customize the layout + fig <- fig %>% + layout(xaxis = list(title = 'Date'), + yaxis = list(title = y_axis_titles[selected_column]), + title = list(text = paste0("Mean daily ", selected_column, "
for ", loc_name, " (station code: ", station_name, ")"), + y = 0.90), + margin = list(t = 60), + plot_bgcolor = '#e5ecf6', + xaxis = list(zerolinecolor = 'black', + zerolinewidth = 2, + gridcolor = 'azure1'), + yaxis = list(zerolinecolor = 'black', + zerolinewidth = 2, + gridcolor = 'azure1')) + + return(fig) +} + + +#### Run the app #### +find_directory_of_file("app.R") + +# Updated UI in WINPageUI +WINPageUI <- function(id) { + ns <- NS(id) tagList( h2("Water Quality Data"), + fluidRow( - # Map occupies 1st column - column(width = 7, leafletOutput(ns("map"), height=750)), # make sure to put the input inside ns() - # histogram occupies rows in the 2nd column - column(width = 5, plotOutput(ns("distPlot")), - sliderInput(ns("bins"), "Number of bins:", - min = 1, max = 50, value = 30) + column(width = 12, + div(style = "margin-bottom: 20px;", + p("This section provides an overview of water quality data. + You can select a water quality variable of interest by using + the dropdown menu. Click on a marker to see a graph of + all available data for that specific location") + ) + ) + ), + fluidRow( + column(width = 12, uiOutput(ns("dropdown_ui")), style = "position:relative;z-index:10000;") + # style is to make sure the dropdown menu shows over the map zoom tools + ), + fluidRow( + column(width = 8, + div(style = "margin-bottom: 20px;", + leafletOutput(ns("map"), height="500px") + ) + ), + column(width = 4, + div(style = "padding: 20px; background-color: #f9f9f9;", + h3("About [variable] and [station]"), + p("Right now this is just some placeholder text. This will be + updated to dynamically show information about the station and + the variable that the user has selected.") + ) + ) + ), + fluidRow( + column(width = 12, + div(style = "margin-bottom: 20px;", + plotlyOutput(ns("plot"), height="350px") + ) ) ), actionButton(inputId = ns("go_back"), label = "Back to Main Page") ) } -WQPageServer <- function(id, parentSession) { - moduleServer(id, function(input, output, session) { # this nested approach is - # necessary to be able to us the "back" button, otherwise Shiny cannot find - # the id for "tabs" - ns <- session$ns - - # Create the histogram - output$distPlot <- renderPlot({ - # generate bins based on input$bins from ui.R - x <- filter(WQ, ComponentShort == "ATEMP") %>% - select(Result) %>% - pull() - x <- as.numeric(x) # stop-gap measure because everything is characters - bins <- seq(min(x, na.rm = TRUE), max(x, na.rm = TRUE), - length.out = input$bins + 1 - ) +# Define custom icons -> move this to a separate script +redIcon <- makeIcon( + iconUrl = "https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-red.png", + iconWidth = 25, iconHeight = 41, + iconAnchorX = 12, iconAnchorY = 41, + shadowUrl = "https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png", + shadowWidth = 41, shadowHeight = 41, + shadowAnchorX = 12, shadowAnchorY = 41 +) - # draw the histogram with the specified number of bins - hist(x, - breaks = bins, col = "darkgray", border = "white", - xlab = "Air temperature (degrees Celsius)", - main = "Histogram of air temperatures" - ) +# Updated Server logic in WINPageServer +WINPageServer <- function(id, parentSession) { + moduleServer(id, function(input, output, session) { + ns <- session$ns + + # Reactive value for the selected column + selected_column <- reactive({ + print(paste("Selected column changed to:", input$column_selector)) + input$column_selector }) - - # Create the map + + # Reactive value to track popup bubble state + popup_visible <- reactiveVal(FALSE) + + # Create the dropdown UI + output$dropdown_ui <- renderUI({ + print("Rendering dropdown UI") + df <- filter_dataframe(WQ_df) + create_dropdown(df, ns) + }) + + # # Default plot + # output$plot <- renderPlotly({ + # df <- filter_dataframe(WQ_df) + # create_plot(df, units_df = WQ_data_units, selected_column = NULL) #selected_column() + # }) + + # Render an empty plot initially + output$plot <- renderPlotly({ + plot_ly(type = 'scatter', mode = 'markers') %>% + layout(title = "No data selected", xaxis = list(visible = FALSE), yaxis = list(visible = FALSE)) + }) + + #### Update plot when dropdown selection changes #### + observeEvent(selected_column(), { + req(clicked_station()) # Ensure station is selected + + print(paste("Updating plot for", selected_column(), "at station", clicked_station())) + + df <- filter_dataframe(WQ_df, filter_value = clicked_station()) # also filter for station here? + # Because then we can create a "no data" available plot + + output$plot <- renderPlotly({ + if (selected_column() %in% names(df)) { # only plot if variable exists for that station + create_plot(df, units_df = WQ_data_units, loc_name = unique(df$site_friendly), selected_column = selected_column()) + } else { + plot_ly(type = 'scatter', mode = 'markers') %>% + layout(title = paste0("No data available on ", selected_column(), "
at ", clicked_station()), + xaxis = list(visible = FALSE), yaxis = list(visible = FALSE)) + } + }) + }, ignoreInit = FALSE) + + + #### Create the map #### output$map <- renderLeaflet({ - leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18)) %>% - # setView(lng=-81.347388, lat=30.075, zoom = 11) %>% - clearBounds() %>% # centers map on all min/max coords - # Base map - addTiles() %>% # Add default OpenStreetMap map tiles - # Polygons, add groups + leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18, scrollWheelZoom = FALSE)) %>% # turn off scroll wheel for now + clearBounds() %>% + addTiles() %>% addPolygons( data = GTMNERR, color = "purple", fill = NA, weight = 2, opacity = 1, group = "GTMNERR boundaries" @@ -69,32 +285,102 @@ WQPageServer <- function(id, parentSession) { color = "white", weight = 2, bringToFront = TRUE ), - group = "Counties", popup = ~NAME + group = "Counties", popup = ~NAME, layerId = ~NAME ) %>% - # addMarkers(data = HAB_data_locations, - # popup = ~paste("Site: ", Site, "
", - # "County: ", County), - # group = "HAB") %>% addMarkers( data = WQ_data_locations, - popup = ~ paste( - "Station: ", site_friendly, "
", - "Location: ", wbid, "
", - "Latest year of sampling: ", maxYear, "", + "Station code: ", StationCode, "
" ), - group = "WQ" + group = "WQ", + layerId = ~geometry ) %>% - # # Layers control (turning layers on and off) addLayersControl( overlayGroups = c("Counties", "GTMNERR boundaries", "WQ"), options = layersControlOptions(collapsed = FALSE) ) %>% - addMeasure(primaryLengthUnit = "miles", primaryAreaUnit = "sqmiles") + addMeasure(primaryLengthUnit = "miles", primaryAreaUnit = "sqmiles") }) - + + #### Observe marker clicks #### + # Reactive value to store the clicked station's ID + clicked_station <- reactiveVal(NULL) + + observeEvent(input$map_marker_click, { + click <- input$map_marker_click # this is a list with lat, lng, id, group, and layerID + if (!is.null(click)) { + + # Update the clicked marker's color using leafletProxy + # If there was a previously clicked marker, reset its color + leafletProxy("map", session) %>% + addMarkers( + data = WQ_data_locations, + popup = ~ paste("Station name: ", site_friendly, "
", + "Station code: ", StationCode, "
" + ), + group = "WQ", + layerId = ~geometry) + + clicked_id <- click$id # the id is geometry + clicked_data <- WQ_data_locations %>% + filter(geometry == clicked_id) + + popup_visible(TRUE) + + # Store the StationCode in a reactive value + clicked_station(clicked_data$StationCode) + + df <- filter_dataframe(WQ_df, filter_value = clicked_station()) + + output$plot <- renderPlotly({ + if (selected_column() %in% names(df)) { # only plot if variable exists for that station + create_plot(df, units_df = WQ_data_units, loc_name = unique(df$site_friendly), selected_column = selected_column()) + } else { + plot_ly(type = 'scatter', mode = 'markers') %>% + layout(title = paste0("No data available on ", selected_column(), "
at ", clicked_station()), + xaxis = list(visible = FALSE), yaxis = list(visible = FALSE)) + } + }) + } + + # Set the new marker color + leafletProxy("map") %>% + addMarkers(lng = input$map_marker_click$lng, lat = input$map_marker_click$lat, + icon = redIcon, layerId = click$id) + + }) + + # Add observeEvent function for input$map_shape_click + # observeEvent(input$map_shape_click, { + # click <- input$map_shape_click + # if (!is.null(click)) { + # clicked_id <- click$id + # clicked_data <- counties_select %>% + # filter(NAME == clicked_id) + # + # popup_visible(TRUE) + # + # output$plot <- renderPlotly({ + # df <- filter_dataframe(WQ_df, filter_value = clicked_data$NAME) + # create_plot(df, units_df = WQ_data_units, loc_name = clicked_data$NAME, selected_column = selected_column()) + # }) + # } + # }) + + # Observe map clicks to hide the popup + # observeEvent(input$map_click, { + # popup_visible(FALSE) + # + # # Default plot + # output$plot <- renderPlotly({ + # df <- filter_dataframe(WQ_df) + # create_plot(df, units_df = WQ_data_units, selected_column = selected_column()) + # }) + # }) + + #### Add 'go back' button #### observeEvent(input$go_back, { updateTabItems(session = parentSession, inputId = "tabs", selected = "main_page") }) }) -} \ No newline at end of file +} diff --git a/modules/waterquality2.R b/modules/waterquality2.R new file mode 100644 index 0000000..813c5bb --- /dev/null +++ b/modules/waterquality2.R @@ -0,0 +1,100 @@ +#### WQ locations data ------------------------------------------------ +WQ_locations <- readRDS("./03_Data_for_app/WQ_locations.Rds") +WQ_data_locations <- WQ_locations %>% + st_as_sf(coords = c("Longitude", "Latitude"), crs = 4326) + +#### WQ data ------------------------------------------------ +WQ <- readRDS("./03_Data_for_app/WQ.Rds") + +WQPageUI <- function(id) { + ns <- NS(id) # This is an important part to add to all sub pages so they use the + # correct sessions / ID's that connect the ui and server here + tagList( + h2("Water Quality Data"), + fluidRow( + # Map occupies 1st column + column(width = 7, leafletOutput(ns("map"), height=750)), # make sure to put the input inside ns() + # histogram occupies rows in the 2nd column + column(width = 5, plotOutput(ns("distPlot")), + sliderInput(ns("bins"), "Number of bins:", + min = 1, max = 50, value = 30) + ) + ), + actionButton(inputId = ns("go_back"), label = "Back to Main Page") + ) +} + +WQPageServer <- function(id, parentSession) { + moduleServer(id, function(input, output, session) { # this nested approach is + # necessary to be able to us the "back" button, otherwise Shiny cannot find + # the id for "tabs" + ns <- session$ns + + # Create the histogram + output$distPlot <- renderPlot({ + # generate bins based on input$bins from ui.R + x <- filter(WQ, ComponentShort == "ATEMP") %>% + select(Result) %>% + pull() + x <- as.numeric(x) # stop-gap measure because everything is characters + bins <- seq(min(x, na.rm = TRUE), max(x, na.rm = TRUE), + length.out = input$bins + 1 + ) + + # draw the histogram with the specified number of bins + hist(x, + breaks = bins, col = "darkgray", border = "white", + xlab = "Air temperature (degrees Celsius)", + main = "Histogram of air temperatures" + ) + }) + + # Create the map + output$map <- renderLeaflet({ + leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18)) %>% + # setView(lng=-81.347388, lat=30.075, zoom = 11) %>% + clearBounds() %>% # centers map on all min/max coords + # Base map + addTiles() %>% # Add default OpenStreetMap map tiles + # Polygons, add groups + addPolygons( + data = GTMNERR, color = "purple", fill = NA, + weight = 2, opacity = 1, group = "GTMNERR boundaries" + ) %>% + addPolygons( + data = counties_select, + color = "black", weight = 2, opacity = 1, + fill = TRUE, fillColor = "white", fillOpacity = 0.01, + highlightOptions = highlightOptions( + color = "white", weight = 2, + bringToFront = TRUE + ), + group = "Counties", popup = ~NAME + ) %>% + # addMarkers(data = HAB_data_locations, + # popup = ~paste("Site: ", Site, "
", + # "County: ", County), + # group = "HAB") %>% + addMarkers( + data = WQ_data_locations, + popup = ~ paste( + "Station: ", site_friendly, "
", + "Location: ", wbid, "
", + "Latest year of sampling: ", maxYear, "% + # # Layers control (turning layers on and off) + addLayersControl( + overlayGroups = c("Counties", "GTMNERR boundaries", "WQ"), + options = layersControlOptions(collapsed = FALSE) + ) %>% + addMeasure(primaryLengthUnit = "miles", primaryAreaUnit = "sqmiles") + }) + + observeEvent(input$go_back, { + updateTabItems(session = parentSession, inputId = "tabs", selected = "main_page") + }) + }) +} \ No newline at end of file diff --git a/modules/win.R b/modules/win.R deleted file mode 100644 index 9dc2d15..0000000 --- a/modules/win.R +++ /dev/null @@ -1,261 +0,0 @@ -# import data for this page -load("./03_Data_for_app/WIN.RData") - -#### Process data further #### -# make datframe for map display and hover data -WIN_data_locations = WIN_df %>% - filter(variable %in% c("geometry", - "HUC12.Name", - "Start.Date", - "latitude", - "longitude") - ) %>% - select(c(RowID, variable, value)) %>% - distinct(RowID, variable, value) %>% - pivot_wider( - names_from = variable, - values_from = value, - values_fill = list(value = NA) - ) %>% - distinct(geometry, HUC12.Name, Start.Date, latitude, longitude) %>% - mutate( - latitude = as.numeric(latitude), - longitude = as.numeric(longitude) - ) - -WIN_data_units = WIN_df %>% - filter(variable %in% c("DEP.Analyte.Name", - "DEP.Result.Unit") - ) %>% - select(c(RowID, variable, value)) %>% - distinct(RowID, variable, value) %>% - pivot_wider( - names_from = variable, - values_from = value, - values_fill = list(value = NA), - values_fn = list(value = ~ first(.)) - ) %>% - distinct(DEP.Analyte.Name, DEP.Result.Unit) - -#### Functions #### -# make dataframe for click plots -filter_dataframe <- function(df, filter_value = NULL) { - if (!is.null(filter_value)) { - # Step 1: Identify the relevant RowIDs - relevant_row_ids <- df %>% - filter(value == filter_value) %>% - pull(RowID) - - # Step 2: Filter the entire dataframe to keep only rows with the relevant RowIDs - filtered_df <- df %>% - filter(RowID %in% relevant_row_ids) - } else { - # If no filter_value is provided, skip the filtering step - filtered_df <- df - } - - # Step 3: Create wide dataframe - wide_df <- filtered_df %>% - pivot_wider(names_from = variable, values_from = value) %>% - select(Activity.Start.Date.Time, - DEP.Analyte.Name, - Org.Result.Value) %>% - pivot_wider(names_from = DEP.Analyte.Name, - values_from = Org.Result.Value, - values_fn = list(Org.Result.Value = ~ mean(as.numeric(.), na.rm = TRUE))) %>% - mutate(Activity.Start.Date.Time = ymd_hms(Activity.Start.Date.Time)) %>% - mutate(across(-Activity.Start.Date.Time, ~ as.numeric(.))) %>% - mutate(Activity.Start.Date.Time = as.Date(Activity.Start.Date.Time)) %>% - group_by(Activity.Start.Date.Time) %>% - summarize(across(everything(), ~mean(.x, na.rm = TRUE))) %>% - select(where(~ n_distinct(.) > 2)) - - return(wide_df) -} - -# New function to create the dropdown -create_dropdown <- function(df, ns) { - column_names <- sort(colnames(df)[colnames(df) != "Activity.Start.Date.Time"]) - print(paste("Creating dropdown with choices:", paste(column_names, collapse=", "))) - - selectInput( - inputId = ns("column_selector"), - label = "Select a Column", - choices = column_names, - selected = column_names[1] - ) -} - -# Modified create_plot function -create_plot <- function(df, units_df, loc_name = "GTMNERR", selected_column) { - print(paste("Creating plot for", selected_column)) - # Initialize the plot with the x-axis - fig <- plot_ly(df, x = ~Activity.Start.Date.Time) - - # Get the column names except the one for the x-axis - column_names <- sort(colnames(df)[colnames(df) != "Activity.Start.Date.Time"]) - - # Create a named vector for Y-axis titles - y_axis_titles <- setNames(units_df$DEP.Result.Unit, units_df$DEP.Analyte.Name) - - # Ensure selected_column is not NULL or empty - if (is.null(selected_column) || selected_column == "") { - selected_column <- column_names[1] - } - - # Loop through each column and add a trace - for (i in seq_along(column_names)) { - fig <- fig %>% - add_trace(y = df[[column_names[i]]], name = column_names[i], type = 'scatter', mode = 'lines', - visible = if (column_names[i] == selected_column) TRUE else FALSE) - } - - # Customize the layout - fig <- fig %>% - layout(xaxis = list(title = 'Date'), - yaxis = list(title = y_axis_titles[selected_column]), - title = paste("Mean ", selected_column, " for ", loc_name)) - - return(fig) -} - - -#### Run the app #### -find_directory_of_file("app.R") - -# Updated UI in WINPageUI -WINPageUI <- function(id) { - ns <- NS(id) - tagList( - h2("Water Information Network"), - fluidRow( - column(width = 7, leafletOutput(ns("map"), height="500px")), - column(width = 5, plotlyOutput(ns("plot"), height="500px")) - ), - fluidRow( - column(width = 12, uiOutput(ns("dropdown_ui"))) - ), - actionButton(inputId = ns("go_back"), label = "Back to Main Page") - ) -} - -# Updated Server logic in WINPageServer -WINPageServer <- function(id, parentSession) { - moduleServer(id, function(input, output, session) { - ns <- session$ns - - # Reactive value for the selected column - selected_column <- reactive({ - print(paste("Selected column changed to:", input$column_selector)) - input$column_selector - }) - - # Reactive value to track popup bubble state - popup_visible <- reactiveVal(FALSE) - - # Create the dropdown UI - output$dropdown_ui <- renderUI({ - print("Rendering dropdown UI") - df <- filter_dataframe(WIN_df) - create_dropdown(df, ns) - }) - - # Update plot when dropdown selection changes - observeEvent(selected_column(), { - print(paste("Updating plot for", selected_column())) - output$plot <- renderPlotly({ - df <- filter_dataframe(WIN_df) - create_plot(df, units_df = WIN_data_units, selected_column = selected_column()) - }) - }, ignoreInit = FALSE) - - # Default plot - output$plot <- renderPlotly({ - df <- filter_dataframe(WIN_df) - create_plot(df, units_df = WIN_data_units, selected_column = selected_column()) - }) - - # Create the map - output$map <- renderLeaflet({ - leaflet(options = leafletOptions(minZoom = 9, maxZoom = 18)) %>% - clearBounds() %>% - addTiles() %>% - addPolygons( - data = GTMNERR, color = "purple", fill = NA, - weight = 2, opacity = 1, group = "GTMNERR boundaries" - ) %>% - addPolygons( - data = counties_select, - color = "black", weight = 2, opacity = 1, - fill = TRUE, fillColor = "white", fillOpacity = 0.01, - highlightOptions = highlightOptions( - color = "white", weight = 2, - bringToFront = TRUE - ), - group = "Counties", popup = ~NAME, layerId = ~NAME - ) %>% - addMarkers( - data = WIN_data_locations, - popup = ~ paste("Station Name: ", HUC12.Name, "
", - "Start Date: ", Start.Date, "
" - ), - group = "WIN", - layerId = ~geometry - ) %>% - addLayersControl( - overlayGroups = c("Counties", "GTMNERR boundaries", "WIN"), - options = layersControlOptions(collapsed = FALSE) - ) %>% - addMeasure(primaryLengthUnit = "miles", primaryAreaUnit = "sqmiles") - }) - - # Observe marker clicks - observeEvent(input$map_marker_click, { - click <- input$map_marker_click - if (!is.null(click)) { - clicked_id <- click$id - clicked_data <- WIN_data_locations %>% - filter(geometry == clicked_id) - - popup_visible(TRUE) - - output$plot <- renderPlotly({ - df <- filter_dataframe(WIN_df, filter_value = clicked_data$HUC12.Name) - create_plot(df, units_df = WIN_data_units, loc_name = clicked_data$HUC12.Name, selected_column = selected_column()) - }) - } - }) - - # Add observeEvent function for input$map_shape_click - observeEvent(input$map_shape_click, { - click <- input$map_shape_click - if (!is.null(click)) { - clicked_id <- click$id - clicked_data <- counties_select %>% - filter(NAME == clicked_id) - - popup_visible(TRUE) - - output$plot <- renderPlotly({ - df <- filter_dataframe(WIN_df, filter_value = clicked_data$NAME) - create_plot(df, units_df = WIN_data_units, loc_name = clicked_data$NAME, selected_column = selected_column()) - }) - } - }) - - # Observe map clicks to hide the popup - observeEvent(input$map_click, { - popup_visible(FALSE) - - # Default plot - output$plot <- renderPlotly({ - df <- filter_dataframe(WIN_df) - create_plot(df, units_df = WIN_data_units, selected_column = selected_column()) - }) - }) - - observeEvent(input$go_back, { - updateTabItems(session = parentSession, inputId = "tabs", selected = "main_page") - }) - }) -}