diff --git a/DESCRIPTION b/DESCRIPTION
index 836bf694b..2b112be12 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -76,7 +76,7 @@ Imports:
jsonlite,
openxlsx,
DT,
- dataRetrieval,
+ dataRetrieval (>= 2.7.21),
dbscan,
janitor,
rExpertQuery,
@@ -86,7 +86,7 @@ Imports:
Depends:
R (>= 4.1.0)
Suggests:
- curl (>= 6.0.0),
+ curl (>= 7.0.0),
xml2,
whisker,
hydroloom,
@@ -106,7 +106,8 @@ Suggests:
yaml,
rvest,
remotes,
- covr
+ covr,
+ httr2 (>= 1.2.1)
Remotes:
USEPA/rExpertQuery@develop
VignetteBuilder: knitr, rmarkdown
diff --git a/NAMESPACE b/NAMESPACE
index 3e8b21dc7..9f64313af 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -79,6 +79,7 @@ export(TADA_PairForCriteriaCalc)
export(TADA_PairReplicates)
export(TADA_RandomTestingData)
export(TADA_ReadWQPWebServices)
+export(TADA_RenametoLegacy)
export(TADA_RetainRequired)
export(TADA_RunKeyFlagFunctions)
export(TADA_Scatterplot)
diff --git a/R/ATTAINSCrosswalks.R b/R/ATTAINSCrosswalks.R
index 8ce07b334..101af0cef 100644
--- a/R/ATTAINSCrosswalks.R
+++ b/R/ATTAINSCrosswalks.R
@@ -38,11 +38,13 @@
#' \dontrun{
#' # Alaska example in
#' AK_crosswalk <- TADA_GetATTAINSAUMLCrosswalk(
-#' org_id = "AKDECWQ", batch_upload = TRUE)
+#' org_id = "AKDECWQ", batch_upload = TRUE
+#' )
#'
#' # Alaska example with ATTAINS prefix compatible with TADA Analysis workflow
#' AK_crosswalk2 <- TADA_GetATTAINSAUMLCrosswalk(
-#' org_id = "AKDECWQ", batch_upload = FALSE)
+#' org_id = "AKDECWQ", batch_upload = FALSE
+#' )
#'
#' # Pueblo of Tesuque example
#' PUEBLOOFTESUQUE_crosswalk <- TADA_GetATTAINSAUMLCrosswalk(
@@ -86,21 +88,27 @@ TADA_GetATTAINSAUMLCrosswalk <- function(org_id = NULL,
) %>%
# paste org_id in front of MLs from the specified org if they are missing
# from ATTAINS
- dplyr::mutate(MonitoringLocationIdentifier = ifelse((
- OrganizationIdentifier == org_id &
- stringr::str_detect(MonitoringLocationIdentifier,
- org_id,
- negate = TRUE
- )),
- paste0(org_id, "-", MonitoringLocationIdentifier),
- MonitoringLocationIdentifier
- ),
- ATTAINS.OrganizationIdentifier = org_id) %>%
- dplyr::rename(ATTAINS.MonitoringLocationIdentifier = MonitoringLocationIdentifier,
- ATTAINS.MonitoringDataLinkText = MonitoringDataLinkText) %>%
- dplyr::select(OrganizationIdentifier, ATTAINS.OrganizationIdentifier,
- ATTAINS.MonitoringLocationIdentifier, ATTAINS.AssessmentUnitIdentifier,
- ATTAINS.MonitoringDataLinkText, ATTAINS.WaterType)
+ dplyr::mutate(
+ MonitoringLocationIdentifier = ifelse((
+ OrganizationIdentifier == org_id &
+ stringr::str_detect(MonitoringLocationIdentifier,
+ org_id,
+ negate = TRUE
+ )),
+ paste0(org_id, "-", MonitoringLocationIdentifier),
+ MonitoringLocationIdentifier
+ ),
+ ATTAINS.OrganizationIdentifier = org_id
+ ) %>%
+ dplyr::rename(
+ ATTAINS.MonitoringLocationIdentifier = MonitoringLocationIdentifier,
+ ATTAINS.MonitoringDataLinkText = MonitoringDataLinkText
+ ) %>%
+ dplyr::select(
+ OrganizationIdentifier, ATTAINS.OrganizationIdentifier,
+ ATTAINS.MonitoringLocationIdentifier, ATTAINS.AssessmentUnitIdentifier,
+ ATTAINS.MonitoringDataLinkText, ATTAINS.WaterType
+ )
rm(au.info)
@@ -113,15 +121,15 @@ TADA_GetATTAINSAUMLCrosswalk <- function(org_id = NULL,
))
if (batch_upload == TRUE) {
-
au.crosswalk <- au.crosswalk %>%
dplyr::select(-ATTAINS.WaterType) %>%
dplyr::select(-ATTAINS.OrganizationIdentifier) %>%
- dplyr::rename(ASSESSMENT_UNIT_ID = ATTAINS.AssessmentUnitIdentifier,
- MS_ORG_ID = ATTAINS.MonitoringLocationIdentifier,
- MS_LOCATION_ID = OrganizationIdentifier,
- MS_DATA_LINK = ATTAINS.MonitoringDataLinkText)
-
+ dplyr::rename(
+ ASSESSMENT_UNIT_ID = ATTAINS.AssessmentUnitIdentifier,
+ MS_ORG_ID = ATTAINS.MonitoringLocationIdentifier,
+ MS_LOCATION_ID = OrganizationIdentifier,
+ MS_DATA_LINK = ATTAINS.MonitoringDataLinkText
+ )
}
return(au.crosswalk)
@@ -296,7 +304,7 @@ TADA_UpdateATTAINSAUMLCrosswalk <- function(org_id = NULL,
check_links = FALSE) {
# get list of organization identifiers from ATTAINS
org.ref <- utils::read.csv(system.file("extdata", "ATTAINSOrgIDsRef.csv",
- package = "EPATADA"
+ package = "EPATADA"
))
# stop function if organization identifiers is not found in ATTAINS
@@ -349,25 +357,31 @@ TADA_UpdateATTAINSAUMLCrosswalk <- function(org_id = NULL,
"MS_DATA_LINK"
)
- if (!all(user_cols %in% names(crosswalk))
- & !all(batch_cols %in% names(crosswalk))) {
-
- stop(paste0("Column names must reflect either the TADA workflow or the ATTAINS ",
- "batch upload requirements. Review function documentation for more information"))
+ if (!all(user_cols %in% names(crosswalk)) &
+ !all(batch_cols %in% names(crosswalk))) {
+ stop(paste0(
+ "Column names must reflect either the TADA workflow or the ATTAINS ",
+ "batch upload requirements. Review function documentation for more information"
+ ))
}
if (all(batch_cols %in% names(crosswalk))) {
crosswalk <- crosswalk %>%
- dplyr::rename(ATTAINS.AssessmentUnitIdentifier = ASSESSMENT_UNIT_ID,
- ATTAINS.MonitoringLocationIdentifier = MS_LOCATION_ID,
- OrganizationIdentifier = MS_ORG_ID,
- ATTAINS.MonitoringDataLinkText = MS_DATA_LINK) %>%
+ dplyr::rename(
+ ATTAINS.AssessmentUnitIdentifier = ASSESSMENT_UNIT_ID,
+ ATTAINS.MonitoringLocationIdentifier = MS_LOCATION_ID,
+ OrganizationIdentifier = MS_ORG_ID,
+ ATTAINS.MonitoringDataLinkText = MS_DATA_LINK
+ ) %>%
dplyr::rowwise() %>%
- dplyr::mutate(ATTAINS.OrganizationIdentifier = org_id,
- ATTAINS.WaterType =
- ifelse(
- "ATTAINS.WaterType" %in% names(.), ATTAINS.WaterType,
- NA_character_ ))
+ dplyr::mutate(
+ ATTAINS.OrganizationIdentifier = org_id,
+ ATTAINS.WaterType =
+ ifelse(
+ "ATTAINS.WaterType" %in% names(.), ATTAINS.WaterType,
+ NA_character_
+ )
+ )
}
}
@@ -410,19 +424,16 @@ TADA_UpdateATTAINSAUMLCrosswalk <- function(org_id = NULL,
# add provider ref if required
- if(wqp_data_links == "add" | wqp_data_links == "replace" |
- update_mlid == TRUE) {
-
+ if (wqp_data_links == "add" | wqp_data_links == "replace" |
+ update_mlid == TRUE) {
provider.ref <- TADA_GetWQPOrgProviderRef() %>%
dplyr::select(OrganizationIdentifier, ProviderName) %>%
dplyr::distinct() %>%
dplyr::mutate(OrgIDForURL = OrganizationIdentifier)
-
}
# internal function to update monitoring location identifiers
updateMonLocIds <- function(.data) {
-
# add additional rows to account for the addition of "_WQX" to many org
# names for WQP data
add.orgs <- provider.ref %>%
@@ -451,14 +462,20 @@ TADA_UpdateATTAINSAUMLCrosswalk <- function(org_id = NULL,
dplyr::filter(ProviderName == "STORET") %>%
dplyr::mutate(
ATTAINS.MonitoringLocationIdentifier =
- stringr::str_remove(ATTAINS.MonitoringLocationIdentifier,
- paste0(OrganizationIdentifier, "-")),
+ stringr::str_remove(
+ ATTAINS.MonitoringLocationIdentifier,
+ paste0(OrganizationIdentifier, "-")
+ ),
ATTAINS.MonitoringLocationIdentifier =
- stringr::str_remove(ATTAINS.MonitoringLocationIdentifier,
- OrganizationIdentifier),
+ stringr::str_remove(
+ ATTAINS.MonitoringLocationIdentifier,
+ OrganizationIdentifier
+ ),
ATTAINS.MonitoringLocationIdentifier = stringr::str_remove(ATTAINS.MonitoringLocationIdentifier, "_WQX"),
- ATTAINS.MonitoringLocationIdentifier = paste0(OrganizationIdentifier, "-",
- ATTAINS.MonitoringLocationIdentifier)
+ ATTAINS.MonitoringLocationIdentifier = paste0(
+ OrganizationIdentifier, "-",
+ ATTAINS.MonitoringLocationIdentifier
+ )
)
# join nwis and storet crosswalks
@@ -473,16 +490,15 @@ TADA_UpdateATTAINSAUMLCrosswalk <- function(org_id = NULL,
# internal function to create new urls for monitoring locations
createNewMLUrls <- function(.data) {
-
- if(!"ProviderName" %in% names(.data)) {
-
+ if (!"ProviderName" %in% names(.data)) {
.data <- .data %>%
dplyr::left_join(provider.ref,
- by = dplyr::join_by(OrganizationIdentifier))
+ by = dplyr::join_by(OrganizationIdentifier)
+ )
}
new.urls <- .data %>%
- #dplyr::filter(ProviderName == "STORET") %>%
+ # dplyr::filter(ProviderName == "STORET") %>%
dplyr::mutate(ATTAINS.MonitoringDataLinkText.New = as.character(ifelse(
is.na(OrgIDForURL), NA,
URLencode(paste0(
@@ -496,58 +512,59 @@ TADA_UpdateATTAINSAUMLCrosswalk <- function(org_id = NULL,
}
if (check_links == TRUE) {
- # internal function to check urls
- checkUrlResp <- function(.data, url.col) {
- # create df of urls to check
- urls.to.check <- .data %>%
- dplyr::filter(!is.na(!!rlang::sym(url.col)))
-
- # check to see if any urls to check
- if (dim(urls.to.check)[1] == 0) {
- .data <- .data %>%
- dplyr::mutate(response.code = "none")
+ # internal function to check urls
+ checkUrlResp <- function(.data, url.col) {
+ # create df of urls to check
+ urls.to.check <- .data %>%
+ dplyr::filter(!is.na(!!rlang::sym(url.col)))
- rm(urls.to.check)
+ # check to see if any urls to check
+ if (dim(urls.to.check)[1] == 0) {
+ .data <- .data %>%
+ dplyr::mutate(response.code = "none")
- return(.data)
- }
+ rm(urls.to.check)
- if (dim(urls.to.check)[1] > 0) {
- # retrieve http response headers from url list
- headers <- urls.to.check %>%
- dplyr::select(!!rlang::sym(url.col)) %>%
- dplyr::pull() %>%
- purrr::map(~ tryCatch(curlGetHeaders(.x), error = function(e) NA))
+ return(.data)
+ }
- # extract response code from first line of header response
- response.code <- sapply(headers, "[[", 1)
+ if (dim(urls.to.check)[1] > 0) {
+ # retrieve http response headers from url list
+ headers <- urls.to.check %>%
+ dplyr::select(!!rlang::sym(url.col)) %>%
+ dplyr::pull() %>%
+ purrr::map(~ tryCatch(curlGetHeaders(.x), error = function(e) NA))
- # create dataframe of urls and response codes
- response.df <- data.frame(urls.to.check, response.code) %>%
- dplyr::distinct()
+ # extract response code from first line of header response
+ response.code <- sapply(headers, "[[", 1)
- # join response codes to add.urls df
- .data <- .data %>%
- dplyr::left_join(response.df, by = names(update.crosswalk))
+ # create dataframe of urls and response codes
+ response.df <- data.frame(urls.to.check, response.code) %>%
+ dplyr::distinct()
+
+ # join response codes to add.urls df
+ .data <- .data %>%
+ dplyr::left_join(response.df, by = names(update.crosswalk))
- rm(urls.to.check, headers, response.code, response.df)
+ rm(urls.to.check, headers, response.code, response.df)
- return(.data)
+ return(.data)
+ }
}
}
-}
if (update_mlid == TRUE & wqp_data_links == "none") {
update.crosswalk <- updateMonLocIds(update.crosswalk)
if (check_links == TRUE) {
update.crosswalk <- checkUrlResp(update.crosswalk,
- url.col = "ATTAINS.MonitoringDataLinkText"
+ url.col = "ATTAINS.MonitoringDataLinkText"
)
update.crosswalk <- update.crosswalk %>%
dplyr::mutate(ATTAINS.MonitoringDataLinkText = ifelse(stringr::str_detect(response.code, "200"),
- ATTAINS.MonitoringDataLinkText.New, NA))
+ ATTAINS.MonitoringDataLinkText.New, NA
+ ))
}
}
@@ -560,13 +577,13 @@ TADA_UpdateATTAINSAUMLCrosswalk <- function(org_id = NULL,
if (check_links == TRUE) {
update.crosswalk <- checkUrlResp(update.crosswalk,
- url.col = "ATTAINS.MonitoringDataLinkText"
+ url.col = "ATTAINS.MonitoringDataLinkText"
)
update.crosswalk <- update.crosswalk %>%
dplyr::mutate(ATTAINS.MonitoringDataLinkText = ifelse(stringr::str_detect(response.code, "200"),
- ATTAINS.MonitoringDataLinkText.New,
- NA
+ ATTAINS.MonitoringDataLinkText.New,
+ NA
))
}
}
@@ -578,24 +595,24 @@ TADA_UpdateATTAINSAUMLCrosswalk <- function(org_id = NULL,
if (check_links == TRUE) {
update.crosswalk <- checkUrlResp(update.crosswalk,
- url.col = "ATTAINS.MonitoringDataLinkText"
+ url.col = "ATTAINS.MonitoringDataLinkText"
)
update.crosswalk <- update.crosswalk %>%
dplyr::mutate(ATTAINS.MonitoringDataLinkText = ifelse(stringr::str_detect(response.code, "200"),
- ATTAINS.MonitoringDataLinkText.New,
- NA
+ ATTAINS.MonitoringDataLinkText.New,
+ NA
)) %>%
dplyr::select(-response.code)
update.crosswalk <- checkUrlResp(update.crosswalk,
- url.col = "ATTAINS.MonitoringDataLinkText.New"
+ url.col = "ATTAINS.MonitoringDataLinkText.New"
)
update.crosswalk <- update.crosswalk %>%
dplyr::mutate(ATTAINS.MonitoringDataLinkText.New = ifelse(stringr::str_detect(response.code, "200"),
- ATTAINS.MonitoringDataLinkText.New,
- NA
+ ATTAINS.MonitoringDataLinkText.New,
+ NA
)) %>%
dplyr::select(-response.code)
}
@@ -612,7 +629,6 @@ TADA_UpdateATTAINSAUMLCrosswalk <- function(org_id = NULL,
is.na(ATTAINS.MonitoringDataLinkText) & is.na(ATTAINS.MonitoringDataLinkText.New) ~ NA
)) %>%
dplyr::select(-ATTAINS.MonitoringDataLinkText.New)
-
}
if (update_mlid == FALSE & wqp_data_links == "none") {
@@ -640,24 +656,24 @@ TADA_UpdateATTAINSAUMLCrosswalk <- function(org_id = NULL,
if (check_links == TRUE) {
update.crosswalk <- checkUrlResp(update.crosswalk,
- url.col = "ATTAINS.MonitoringDataLinkText"
+ url.col = "ATTAINS.MonitoringDataLinkText"
)
update.crosswalk <- update.crosswalk %>%
dplyr::mutate(ATTAINS.MonitoringDataLinkText = ifelse(stringr::str_detect(response.code, "200"),
- ATTAINS.MonitoringDataLinkText.New,
- NA
+ ATTAINS.MonitoringDataLinkText.New,
+ NA
)) %>%
dplyr::select(-response.code)
update.crosswalk <- checkUrlResp(update.crosswalk,
- url.col = "ATTAINS.MonitoringDataLinkText.New"
+ url.col = "ATTAINS.MonitoringDataLinkText.New"
)
update.crosswalk <- update.crosswalk %>%
dplyr::mutate(ATTAINS.MonitoringDataLinkText.New = ifelse(stringr::str_detect(response.code, "200"),
- ATTAINS.MonitoringDataLinkText.New,
- NA
+ ATTAINS.MonitoringDataLinkText.New,
+ NA
)) %>%
dplyr::select(-response.code)
@@ -695,19 +711,23 @@ TADA_UpdateATTAINSAUMLCrosswalk <- function(org_id = NULL,
# select relevant column names and ordering for output in TADA workflow format.
update.crosswalk <- update.crosswalk %>%
- dplyr::select(OrganizationIdentifier, ATTAINS.OrganizationIdentifier,
- ATTAINS.MonitoringLocationIdentifier, ATTAINS.AssessmentUnitIdentifier,
- ATTAINS.MonitoringDataLinkText, ATTAINS.WaterType)
+ dplyr::select(
+ OrganizationIdentifier, ATTAINS.OrganizationIdentifier,
+ ATTAINS.MonitoringLocationIdentifier, ATTAINS.AssessmentUnitIdentifier,
+ ATTAINS.MonitoringDataLinkText, ATTAINS.WaterType
+ )
# If batch upload is desired, format the output in the required format.
if (batch_upload == TRUE) {
update.crosswalk <- update.crosswalk %>%
dplyr::filter(!is.na(ATTAINS.AssessmentUnitIdentifier)) %>%
dplyr::select(-c(ATTAINS.WaterType, ATTAINS.OrganizationIdentifier)) %>%
- dplyr::rename(ASSESSMENT_UNIT_ID = ATTAINS.AssessmentUnitIdentifier,
- MS_ORG_ID = ATTAINS.MonitoringLocationIdentifier,
- MS_LOCATION_ID = OrganizationIdentifier,
- MS_DATA_LINK = ATTAINS.MonitoringDataLinkText)
+ dplyr::rename(
+ ASSESSMENT_UNIT_ID = ATTAINS.AssessmentUnitIdentifier,
+ MS_ORG_ID = ATTAINS.MonitoringLocationIdentifier,
+ MS_LOCATION_ID = OrganizationIdentifier,
+ MS_DATA_LINK = ATTAINS.MonitoringDataLinkText
+ )
}
return(update.crosswalk)
@@ -904,7 +924,7 @@ TADA_CreateParamRef <- function(.data, org_id = NULL, paramRef = NULL, auto_assi
ATTAINS.OrganizationIdentifier = character(0),
ATTAINS.ParameterName = character(0),
ATTAINS.FlagParameterName = character(0),
- Flag.ParameterInput = character(0)
+ Flag.ParameterInput = character(0)
)
return(empty_df)
@@ -1549,7 +1569,7 @@ TADA_CreateUseParamRef <- function(.data, org_id = NULL, paramRef = NULL, usePar
TADA.ComparableDataIdentifier = character(0),
ATTAINS.OrganizationIdentifier = character(0),
ATTAINS.ParameterName = character(0),
- ATTAINS.UseName = character(0),
+ ATTAINS.UseName = character(0),
IncludeOrExclude = character(0),
ATTAINS.FlagUseName = character(0),
Flag.UseInput = character(0)
@@ -2100,12 +2120,12 @@ TADA_CreateUseParamRef <- function(.data, org_id = NULL, paramRef = NULL, usePar
#' For any NEW AUs and/or NEW uses, users must modify
#' the output of this function to manually add those uses and AU's to the crosswalk.
#' Alternatively, we have developed a helper function, [TADA_CreateWaterUseRef()],
-#' to assist with assigning uses to NEW AU's. This can be levereaged to assign
+#' to assist with assigning uses to NEW AU's. This can be leveraged to assign
#' uses for any new AUs based on the water type of the AU.
#' Users can either supply their own Water
#' Type to Use crosswalk or utilize ATTAINS webservices to pull in the Water Type to
#' Use reference file. This Water to Use reference file can be used to assign all
-#' unique Uses to a new/modified AU based on which uses have been assisgned to that
+#' unique Uses to a new/modified AU based on which uses have been assigned to that
#' water type in the past for the specified ATTAINS organization.
#' Any new or modified AU and use information that gets submitted to ATTAINS
#' in the current assessment cycle will not be available in ATTAINS until the
@@ -2246,7 +2266,6 @@ TADA_CreateUseParamRef <- function(.data, org_id = NULL, paramRef = NULL, usePar
#' AUMLRef = AK_appenduserdata,
#' excel = FALSE
#' )
-#'
#' }
#'
TADA_CreateUseAURef <- function(.data, org_id = NULL, AUMLRef = NULL, # Required inputs in this line
@@ -2260,7 +2279,7 @@ TADA_CreateUseAURef <- function(.data, org_id = NULL, AUMLRef = NULL, # Required
ATTAINS.OrganizationIdentifier = character(0),
ATTAINS.AssessmentUnitIdentifier = character(0), # ATTAINS.assessmentunitname,
ATTAINS.UseName = character(0),
- ATTAINS.WaterType = character(0),
+ ATTAINS.WaterType = character(0),
TADA.AssessmentUnitStatus = character(0),
IncludeOrExclude = character(0)
)
@@ -2311,8 +2330,10 @@ TADA_CreateUseAURef <- function(.data, org_id = NULL, AUMLRef = NULL, # Required
}
AULMLRef <- AUMLRef %>%
- dplyr::select(ATTAINS.AssessmentUnitIdentifier, ATTAINS.WaterType,
- ATTAINS.OrganizationIdentifier)
+ dplyr::select(
+ ATTAINS.AssessmentUnitIdentifier, ATTAINS.WaterType,
+ ATTAINS.OrganizationIdentifier
+ )
}
}
@@ -2482,12 +2503,13 @@ TADA_CreateUseAURef <- function(.data, org_id = NULL, AUMLRef = NULL, # Required
# data validation drop down list created below.
suppressWarnings(openxlsx::dataValidation(
- wb, sheet = "CreateUseAURef",
+ wb,
+ sheet = "CreateUseAURef",
cols = 6, rows = 2:10000,
type = "list",
value = sprintf("'Index'!$A$2:$A$5"),
- allowBlank = TRUE, showErrorMsg = TRUE, showInputMsg = TRUE)
- )
+ allowBlank = TRUE, showErrorMsg = TRUE, showInputMsg = TRUE
+ ))
# Conditional Formatting
openxlsx::conditionalFormatting(
@@ -2517,7 +2539,7 @@ TADA_CreateUseAURef <- function(.data, org_id = NULL, AUMLRef = NULL, # Required
}
return(CreateUseAURef)
- }
+ }
}
@@ -2604,8 +2626,10 @@ TADA_CreateWaterUseRef <- function(.data, org_id = NULL, waterUseRef = NULL) {
}
# Calls on EQ_Assessments from latest assessment cycle. Pulls in unique water types and uses by org
- print(paste0("TADA_CreateWaterUseParamRef: Importing unique water types and uses ",
- "by organization from Expert Query."))
+ print(paste0(
+ "TADA_CreateWaterUseParamRef: Importing unique water types and uses ",
+ "by organization from Expert Query."
+ ))
OrgID_assessments <- spsUtil::quiet(rExpertQuery::EQ_Assessments(org_id = org_id, api_key = tadakey))
diff --git a/R/ATTAINSRefTables.R b/R/ATTAINSRefTables.R
index 6770791a5..efb2fa51c 100644
--- a/R/ATTAINSRefTables.R
+++ b/R/ATTAINSRefTables.R
@@ -22,7 +22,7 @@ TADA_GetATTAINSParameterWQPCharRef <- function() {
raw.data <- tryCatch(
{
# get data from ATTAINS
- attainsParamRef <-spsUtil::quiet(data.frame(name = rExpertQuery::EQ_DomainValues("param_name")[, "name"]))
+ attainsParamRef <- spsUtil::quiet(data.frame(name = rExpertQuery::EQ_DomainValues("param_name")[, "name"]))
WQXCharRef <- utils::read.csv(system.file("extdata", "WQXCharacteristicRef.csv", package = "EPATADA"))
@@ -190,16 +190,20 @@ TADA_GetATTAINSParamUseOrgRef <- function() {
dplyr::distinct() %>%
dplyr::ungroup()
- latest.params <- latest.assessments %>%
- dplyr::select(organizationId, organizationName,
- organizationType, parameterName,
- useName) %>%
- dplyr::rename( ATTAINS.OrganizationIdentifier = organizationId,
- ATTAINS.OrganizationName = organizationName,
- ATTAINS.OrganizationType = organizationType,
- ATTAINS.ParameterName = parameterName,
- ATTAINS.UseName = useName) %>%
- dplyr::distinct()
+ latest.params <- latest.assessments %>%
+ dplyr::select(
+ organizationId, organizationName,
+ organizationType, parameterName,
+ useName
+ ) %>%
+ dplyr::rename(
+ ATTAINS.OrganizationIdentifier = organizationId,
+ ATTAINS.OrganizationName = organizationName,
+ ATTAINS.OrganizationType = organizationType,
+ ATTAINS.ParameterName = parameterName,
+ ATTAINS.UseName = useName
+ ) %>%
+ dplyr::distinct()
# remove intermediate variables
rm(nat.assessments, latest.assessments)
diff --git a/R/CensoredDataSuite.R b/R/CensoredDataSuite.R
index e337c12d6..015fc7809 100644
--- a/R/CensoredDataSuite.R
+++ b/R/CensoredDataSuite.R
@@ -37,18 +37,18 @@
#' because user-supplied Result Measure Qualifier codes are also used to ID censored results.
#'
#' @export
-#'
-#'
+#'
+#'
TADA_IDCensoredData <- function(.data) {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
# check .data has all of the required columns
expected_cols <- c(
"ResultDetectionConditionText",
@@ -94,12 +94,12 @@ TADA_IDCensoredData <- function(.data) {
"Result Value/Unit Copied from Detection Limit",
.data$TADA.ResultMeasureValueDataTypes.Flag
)
-
+
# this updates the TADA.ResultMeasureValueDataTypes.Flag if there are only NAs
.data$TADA.ResultMeasureValueDataTypes.Flag <- ifelse(
(.data$ResultMeasureValue == "BPQL" |
- .data$ResultMeasureValue == "BDL" |
- .data$ResultMeasureValue == "ND") &
+ .data$ResultMeasureValue == "BDL" |
+ .data$ResultMeasureValue == "ND") &
is.na(.data$TADA.DetectionQuantitationLimitMeasure.MeasureValue) &
is.na(.data$TADA.DetectionQuantitationLimitMeasure.MeasureUnitCode),
"Result Value/Unit Cannot Be Estimated From Detection Limit",
@@ -109,7 +109,7 @@ TADA_IDCensoredData <- function(.data) {
# Copy detection limit value and unit to TADA Result Measure Value and Unit columns
# this first row copies all over when TADA.DetectionQuantitationLimitMeasure.MeasureValue is not NA and the
# TADA.ResultMeasureValueDataTypes.Flag is "NA - Not Available"
- # Imp note: TADA result values are NA for text and other values (coerced in TADA_ConvertSpecialChars)
+ # Imp note: TADA result values are NA for text and other values (coerced in TADA_ConvertSpecialChars)
# even though they are not NA in the original result value
.data$TADA.ResultMeasureValue <- ifelse(
!is.na(.data$TADA.DetectionQuantitationLimitMeasure.MeasureValue) &
@@ -136,7 +136,7 @@ TADA_IDCensoredData <- function(.data) {
"Result Value/Unit Copied from Detection Limit",
.data$TADA.ResultMeasureValueDataTypes.Flag
)
-
+
# If user has not previously run TADA_FlagMeasureQualifierCode, run it here
# to add column TADA.MeasureQualifier.Flag to allow for using user-supplied
# Result Measure Qualifier codes to identify censored samples.
@@ -145,7 +145,7 @@ TADA_IDCensoredData <- function(.data) {
} else {
data_mq_flag <- .data
}
-
+
# update TADA.ResultMeasureValueDataTypes.Flag if TADA.ResultMeasureValue is still NA
data_mq_flag <- data_mq_flag %>%
dplyr::mutate(TADA.ResultMeasureValueDataTypes.Flag = ifelse(
@@ -156,25 +156,25 @@ TADA_IDCensoredData <- function(.data) {
## Identify censored data using TADA.ResultMeasureValueDataTypes.Flag and TADA.MeasureQualifierCode.Flag
cens_rm_flag <- data_mq_flag %>% dplyr::filter(TADA.ResultMeasureValueDataTypes.Flag == "Result Value/Unit Copied from Detection Limit")
-
+
cens_mq_flag <- data_mq_flag %>%
dplyr::filter(TADA.MeasureQualifierCode.Flag %in% c("Non-Detect", "Over-Detect")) %>%
dplyr::filter(!ResultIdentifier %in% cens_rm_flag$ResultIdentifier)
-
+
cens <- cens_rm_flag %>%
rbind(cens_mq_flag)
-
+
# Perform the filtering operation
not_cens <- data_mq_flag %>% dplyr::filter(!ResultIdentifier %in% cens$ResultIdentifier)
-
+
# Check if the dataframe is empty
if (nrow(not_cens) > 0) {
# If not empty, assign "Uncensored" to the TADA.CensoredData.Flag column
not_cens$TADA.CensoredData.Flag <- "Uncensored"
} else {
# If empty, create an empty dataframe with the same columns as data_mq_flag
- not_cens <- data_mq_flag[0, ] # Selects zero rows but retains all columns
- not_cens$TADA.CensoredData.Flag <- character(0) # Ensure the column exists
+ not_cens <- data_mq_flag[0, ] # Selects zero rows but retains all columns
+ not_cens$TADA.CensoredData.Flag <- character(0) # Ensure the column exists
}
rm(cens_rm_flag, cens_mq_flag, data_mq_flag)
@@ -259,9 +259,11 @@ TADA_IDCensoredData <- function(.data) {
cens$TADA.CensoredData.Flag
)
# Identify where there are conflicts
- cens$TADA.CensoredData.Flag <- ifelse(cens$TADA.Detection_Type %in% c("Non-Detect",
- "Over-Detect",
- "Other") &
+ cens$TADA.CensoredData.Flag <- ifelse(cens$TADA.Detection_Type %in% c(
+ "Non-Detect",
+ "Over-Detect",
+ "Other"
+ ) &
cens$TADA.Limit_Type %in% c("Non-Detect", "Over-Detect", "Other") &
!cens$TADA.Detection_Type == cens$TADA.Limit_Type,
"Conflict between Condition and Limit",
@@ -277,27 +279,28 @@ TADA_IDCensoredData <- function(.data) {
## warn when some limit metadata may be problematic & revert result value back to NA and update flags
# Check if the flag "Conflict between Condition and Limit" exists in the dataset
if ("Conflict between Condition and Limit" %in% cens$TADA.CensoredData.Flag) {
-
# Count the number of records with the conflicting flag
- num <- length(cens$TADA.CensoredData.Flag[cens$TADA.CensoredData.Flag ==
- "Conflict between Condition and Limit"])
-
+ num <- length(cens$TADA.CensoredData.Flag[cens$TADA.CensoredData.Flag ==
+ "Conflict between Condition and Limit"])
+
# Print a warning message about the number of conflicting records
- print(paste0("TADA_IDCensoredData: ", num,
- " records in supplied dataset have conflicting detection condition and detection limit type information. These records will not be included in detection limit handling calculations."))
-
+ print(paste0(
+ "TADA_IDCensoredData: ", num,
+ " records in supplied dataset have conflicting detection condition and detection limit type information. These records will not be included in detection limit handling calculations."
+ ))
+
# Update the ResultMeasureValueDataTypes.Flag for records with the conflicting flag
- cens$TADA.ResultMeasureValueDataTypes.Flag[cens$TADA.CensoredData.Flag ==
- "Conflict between Condition and Limit"] <-
+ cens$TADA.ResultMeasureValueDataTypes.Flag[cens$TADA.CensoredData.Flag ==
+ "Conflict between Condition and Limit"] <-
"Result Value/Unit Cannot Be Estimated From Detection Limit"
-
+
# Set TADA.ResultMeasureValue to NA for records with the conflicting flag
- cens$TADA.ResultMeasureValue[cens$TADA.CensoredData.Flag ==
- "Conflict between Condition and Limit"] <- NA
-
+ cens$TADA.ResultMeasureValue[cens$TADA.CensoredData.Flag ==
+ "Conflict between Condition and Limit"] <- NA
+
# Set TADA.ResultMeasure.MeasureUnitCode to NA for records with the conflicting flag
- cens$TADA.ResultMeasure.MeasureUnitCode[cens$TADA.CensoredData.Flag ==
- "Conflict between Condition and Limit"] <- NA
+ cens$TADA.ResultMeasure.MeasureUnitCode[cens$TADA.CensoredData.Flag ==
+ "Conflict between Condition and Limit"] <- NA
}
if ("Detection condition or detection limit is not documented in TADA reference tables." %in% cens$TADA.CensoredData.Flag) {
@@ -312,7 +315,7 @@ TADA_IDCensoredData <- function(.data) {
cens.check <- not_cens
print("TADA_IDCensoredData: No censored data detected in your dataframe. Returning input dataframe with new column TADA.CensoredData.Flag set to Uncensored")
}
-
+
# double check that detection values are not copied when there are conflicts...
cens.check <- cens.check %>%
dplyr::mutate(
@@ -332,7 +335,7 @@ TADA_IDCensoredData <- function(.data) {
TADA.ResultMeasure.MeasureUnitCode
)
)
-
+
cens.check <- TADA_OrderCols(cens.check)
return(cens.check)
}
@@ -397,13 +400,13 @@ TADA_SimpleCensoredMethods <- function(.data, nd_method = "multiplier",
od_multiplier = "null") {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
# check .data has all of the required columns
expected_cols <- c(
"ResultDetectionConditionText",
@@ -438,10 +441,12 @@ TADA_SimpleCensoredMethods <- function(.data, nd_method = "multiplier",
no.ref <- subset(cens.data, cens.data$TADA.CensoredData.Flag == "Detection condition is missing and required for censored data ID.")
missing.ref <- subset(cens.data, cens.data$TADA.CensoredData.Flag == "Detection condition or detection limit is not documented in TADA reference tables.")
- all_others <- subset(cens.data, !cens.data$ResultIdentifier %in% c(nd$ResultIdentifier, od$ResultIdentifier,
- no.ref$ResultIdentifier, missing.ref$ResultIdentifier))
+ all_others <- subset(cens.data, !cens.data$ResultIdentifier %in% c(
+ nd$ResultIdentifier, od$ResultIdentifier,
+ no.ref$ResultIdentifier, missing.ref$ResultIdentifier
+ ))
- # HRM note 7/15/2025 still need to add code to set no.ref.missing results to NA
+ # HRM note 7/15/2025 still need to add code to set no.ref.missing results to NA
# ND handling
if (dim(nd)[1] > 0) {
@@ -477,9 +482,9 @@ TADA_SimpleCensoredMethods <- function(.data, nd_method = "multiplier",
# handling for results with missing detection conditions or with a detection condition or limit not in TADA ref table
if (dim(no.ref)[1] > 0) {
- no.ref$TADA.ResultMeasureValue <- NA
- no.refTADA.CensoredMethod <- "Result set to NA due to Missing Detection Condition"
- no.ref$TADA.ResultMeasureValueDataTypes.Flag <- "Result Value/Unit Cannot Be Estimated From Detection Limit"
+ no.ref$TADA.ResultMeasureValue <- NA
+ no.refTADA.CensoredMethod <- "Result set to NA due to Missing Detection Condition"
+ no.ref$TADA.ResultMeasureValueDataTypes.Flag <- "Result Value/Unit Cannot Be Estimated From Detection Limit"
}
# handling for results with missing detection conditions or with a detection condition or limit not in TADA ref table
diff --git a/R/DataDiscoveryRetrieval.R b/R/DataDiscoveryRetrieval.R
index 21aa99fa5..6c6e24521 100644
--- a/R/DataDiscoveryRetrieval.R
+++ b/R/DataDiscoveryRetrieval.R
@@ -473,11 +473,15 @@ TADA_DataRetrieval <- function(startDate = "null",
# Reformat returned info as sf
bbox_sites_sf <- quiet_bbox_sites$result %>%
- dplyr::rename(TADA.LatitudeMeasure = LatitudeMeasure,
- TADA.LongitudeMeasure = LongitudeMeasure) %>%
+ dplyr::rename(
+ TADA.LatitudeMeasure = LatitudeMeasure,
+ TADA.LongitudeMeasure = LongitudeMeasure
+ ) %>%
TADA_MakeSpatial(crs = 4326) %>%
- dplyr::rename(LatitudeMeasure = TADA.LatitudeMeasure,
- LongitudeMeasure = TADA.LongitudeMeasure)
+ dplyr::rename(
+ LatitudeMeasure = TADA.LatitudeMeasure,
+ LongitudeMeasure = TADA.LongitudeMeasure
+ )
# Subset sites to only within shapefile and get IDs
clipped_sites_sf <- bbox_sites_sf[aoi_sf, ]
@@ -1052,7 +1056,7 @@ TADA_TribalOptions <- function(tribal_area_type, return_sf = FALSE) {
#' Note: It may be useful to save the Query URL from the WQP as well as a
#' comment within your code. This URL let's you return to the WQP query page
#' with all your selected data filters. See example below.
-#'
+#'
#' **Extra tip:** Note that the web service call built using the Water
#' Quality Portal uses the inputs startDateLo and startDateHi rather than
#' startDate and endDate, and dates are in the format MM-DD-YYYY rather
@@ -1069,7 +1073,7 @@ TADA_TribalOptions <- function(tribal_area_type, return_sf = FALSE) {
#' @return WQP Data Profile
#'
#' @export
-#'
+#'
#' @examples
#' \dontrun{
#' # Define base URL and common components
@@ -1183,16 +1187,43 @@ TADA_BigDataHelper <- function(record_summary, WQPquery, maxrecs = 250000, maxsi
smallsitesgrp$MonitoringLocationIdentifier,
smallsitesgrp$group == i
)
- # Query result data
- results_small <- suppressMessages(
- dataRetrieval::readWQPdata(
- siteid = small_site_chunk,
- WQPquery,
- dataProfile = "resultPhysChem",
- ignore_attributes = TRUE
- )
- ) %>%
- dplyr::mutate(dplyr::across(everything(), as.character))
+ query_data_with_retry <- function(site_chunk, query, max_attempts = 3) {
+ attempt <- 1
+ while (attempt <= max_attempts) {
+ tryCatch(
+ {
+ # Query result data
+ results_small <- suppressMessages(
+ dataRetrieval::readWQPdata(
+ siteid = site_chunk,
+ query,
+ dataProfile = "resultPhysChem",
+ ignore_attributes = TRUE
+ )
+ ) %>%
+ dplyr::mutate(dplyr::across(tidyselect::everything(), as.character))
+
+ # Return the results if successful
+ return(results_small)
+ },
+ error = function(e) {
+ # Check if the error is an HTTP 500 error
+ if (grepl("HTTP 500", e$message)) {
+ message("HTTP 500 error encountered. Retrying... (Attempt ", attempt, " of ", max_attempts, ")")
+ attempt <- attempt + 1
+ Sys.sleep(2) # Optional: wait for a few seconds before retrying
+ } else {
+ stop("An unexpected error occurred: ", e$message)
+ }
+ }
+ )
+ }
+ # If max attempts reached, stop with an error message
+ stop("Failed to retrieve data after ", max_attempts, " attempts due to repeated HTTP 500 errors.")
+ }
+
+ # Use the function to query data
+ results_small <- query_data_with_retry(small_site_chunk, WQPquery)
# If data is returned, stack with what's already been retrieved
if (dim(results_small)[1] > 0) {
@@ -1235,7 +1266,7 @@ TADA_BigDataHelper <- function(record_summary, WQPquery, maxrecs = 250000, maxsi
ignore_attributes = TRUE
)
) %>%
- dplyr::mutate(dplyr::across(everything(), as.character))
+ dplyr::mutate(dplyr::across(tidyselect::everything(), as.character))
if (dim(results_big)[1] > 0) {
df_big <- dplyr::bind_rows(df_big, results_big)
@@ -1289,8 +1320,10 @@ TADA_BigDataHelper <- function(record_summary, WQPquery, maxrecs = 250000, maxsi
#'
#' # Construct URLs for different profiles
#' station_url <- paste0(baseurl, "/data/Station", filters, dates, type, providers)
-#' result_url <- paste0(baseurl, "/data/Result", filters,
-#' dates, type, "&dataProfile=resultPhysChem", providers)
+#' result_url <- paste0(
+#' baseurl, "/data/Result", filters,
+#' dates, type, "&dataProfile=resultPhysChem", providers
+#' )
#' project_url <- paste0(baseurl, "/data/Project", filters, dates, type, providers)
#'
#' # Retrieve data from Water Quality Portal web services
@@ -1479,7 +1512,7 @@ make_groups <- function(x, maxrecs) {
#' baseurl, "/data/Project", filters, dates, type, providers
#' )
#'
-#' # Use TADA_ReadWQPWebServices to load Station, Project,
+#' # Use TADA_ReadWQPWebServices to load Station, Project,
#' # and Phys-Chem Result profiles
#' stationProfile <- TADA_ReadWQPWebServices(station_url)
#' physchemProfile <- TADA_ReadWQPWebServices(result_url)
diff --git a/R/DepthProfile.R b/R/DepthProfile.R
index 5ba1f5597..b8baec03a 100644
--- a/R/DepthProfile.R
+++ b/R/DepthProfile.R
@@ -89,8 +89,8 @@
#' bycategory = "all", dailyagg = "avg", aggregatedonly = FALSE
#' )
#'
-TADA_FlagDepthCategory <- function(.data, bycategory = "no", bottomvalue = 2,
- surfacevalue = 2, dailyagg = "none",
+TADA_FlagDepthCategory <- function(.data, bycategory = "no", bottomvalue = 2,
+ surfacevalue = 2, dailyagg = "none",
aggregatedonly = FALSE, clean = FALSE) {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
diff --git a/R/GeospatialFunctions.R b/R/GeospatialFunctions.R
index 143d8c2d6..652b98dd8 100644
--- a/R/GeospatialFunctions.R
+++ b/R/GeospatialFunctions.R
@@ -1238,8 +1238,8 @@ fetchNHD <- function(.data, resolution = "Hi", features = "catchments") {
#' )
#' }
TADA_CreateATTAINSAUMLCrosswalk <- function(.data, return_nearest = FALSE,
- fill_catchments = FALSE, resolution = "Hi",
- return_sf = TRUE) {
+ fill_catchments = FALSE, resolution = "Hi",
+ return_sf = TRUE) {
# function settings that we ensure go back to their original settings
# after the function stops running:
original_s2 <- sf::sf_use_s2() # Store the original s2 setting first
@@ -1344,42 +1344,43 @@ TADA_CreateATTAINSAUMLCrosswalk <- function(.data, return_nearest = FALSE,
# select only catchments that have WQP observations in them:
.[TADA_DataRetrieval_data, ] %>%
# add prefix "ATTAINS" to ATTAINS data
- dplyr::rename(ATTAINS.SubmissionId = submissionid,
- ATTAINS.NhdPlusId = nhdplusid,
- ATTAINS.State = state,
- ATTAINS.Region = region,
- ATTAINS.OrganizationId = organizationid,
- ATTAINS.OrgType = orgtype,
- ATTAINS.Tas303d = tas303d,
- ATTAINS.OrganizationName = organizationname,
- ATTAINS.ReportingCycle = reportingcycle,
- ATTAINS.AssessmentUnitIdentifier = assessmentunitidentifier,
- ATTAINS.AssessmentUnitName = assessmentunitname,
- ATTAINS.WaterbodyReportLink = waterbodyreportlink,
- ATTAINS.AssmntJoinKey = assmnt_joinkey,
- ATTAINS.PermIdJoinKey = permid_joinkey,
- ATTAINS.IrCategory = ircategory,
- ATTAINS.OverallStatus = overallstatus,
- ATTAINS.IsAssessed = isassessed,
- ATTAINS.IsImpaired = isimpaired,
- ATTAINS.IsThreatened = isthreatened,
- ATTAINS.On303dList = on303dlist,
- ATTAINS.HasTmdl = hastmdl,
- ATTAINS.Has4bPlan = has4bplan,
- ATTAINS.HasAlternativePlan = hasalternativeplan,
- ATTAINS.HasProtectionPlan = hasprotectionplan,
- ATTAINS.VisionPriority303d = visionpriority303d,
- ATTAINS.AreaSqkm = areasqkm,
- ATTAINS.Huc12 = huc12,
- ATTAINS.XwalkMethod = xwalk_method,
- ATTAINS.WwalkHuc12Version= xwalk_huc12_version,
- ATTAINS.CatchmentAreaSqkm = catchmentareasqkm,
- ATTAINS.CatchmentStateCode = catchmentstatecode,
- ATTAINS.CatchmentIsTribal = catchmentistribal,
- ATTAINS.CatchmentResolution = catchmentresolution,
- ATTAINS.ShapeLength = Shape_Length,
- ATTAINS.ShapeArea = Shape_Area,
- ATTAINS.WaterType = waterTypeCode
+ dplyr::rename(
+ ATTAINS.SubmissionId = submissionid,
+ ATTAINS.NhdPlusId = nhdplusid,
+ ATTAINS.State = state,
+ ATTAINS.Region = region,
+ ATTAINS.OrganizationId = organizationid,
+ ATTAINS.OrgType = orgtype,
+ ATTAINS.Tas303d = tas303d,
+ ATTAINS.OrganizationName = organizationname,
+ ATTAINS.ReportingCycle = reportingcycle,
+ ATTAINS.AssessmentUnitIdentifier = assessmentunitidentifier,
+ ATTAINS.AssessmentUnitName = assessmentunitname,
+ ATTAINS.WaterbodyReportLink = waterbodyreportlink,
+ ATTAINS.AssmntJoinKey = assmnt_joinkey,
+ ATTAINS.PermIdJoinKey = permid_joinkey,
+ ATTAINS.IrCategory = ircategory,
+ ATTAINS.OverallStatus = overallstatus,
+ ATTAINS.IsAssessed = isassessed,
+ ATTAINS.IsImpaired = isimpaired,
+ ATTAINS.IsThreatened = isthreatened,
+ ATTAINS.On303dList = on303dlist,
+ ATTAINS.HasTmdl = hastmdl,
+ ATTAINS.Has4bPlan = has4bplan,
+ ATTAINS.HasAlternativePlan = hasalternativeplan,
+ ATTAINS.HasProtectionPlan = hasprotectionplan,
+ ATTAINS.VisionPriority303d = visionpriority303d,
+ ATTAINS.AreaSqkm = areasqkm,
+ ATTAINS.Huc12 = huc12,
+ ATTAINS.XwalkMethod = xwalk_method,
+ ATTAINS.WwalkHuc12Version = xwalk_huc12_version,
+ ATTAINS.CatchmentAreaSqkm = catchmentareasqkm,
+ ATTAINS.CatchmentStateCode = catchmentstatecode,
+ ATTAINS.CatchmentIsTribal = catchmentistribal,
+ ATTAINS.CatchmentResolution = catchmentresolution,
+ ATTAINS.ShapeLength = Shape_Length,
+ ATTAINS.ShapeArea = Shape_Area,
+ ATTAINS.WaterType = waterTypeCode
) %>%
# get rid of dupes (as a precaution)
dplyr::distinct(.keep_all = TRUE),
@@ -1694,7 +1695,7 @@ TADA_CreateATTAINSAUMLCrosswalk <- function(.data, return_nearest = FALSE,
#' @examples
#' \dontrun{
#' # Example 1: Basic usage with default settings
-#' # Assume `my_data` is a TADA data frame with some monitoring
+#' # Assume `my_data` is a TADA data frame with some monitoring
#' # location results
#' # Assume `my_au_ref` is a data frame containing known AU and monitoring
#' # location combinations
@@ -1702,11 +1703,13 @@ TADA_CreateATTAINSAUMLCrosswalk <- function(.data, return_nearest = FALSE,
#'
#' # Example 2: Fetching ATTAINS data with catchment information
#' # Set `add_catch` to TRUE to include catchment data in the output
-#' result_with_catch <- TADA_GetATTAINSByAUID(my_data, au_ref = my_au_ref,
-#' add_catch = TRUE)
+#' result_with_catch <- TADA_GetATTAINSByAUID(my_data,
+#' au_ref = my_au_ref,
+#' add_catch = TRUE
+#' )
#'
#' # Example 3: Handling empty data frames
-#' # If the input data frame has no observations, the function returns an
+#' # If the input data frame has no observations, the function returns an
#' # empty data frame with ATTAINS columns
#' empty_data <- data.frame()
#' empty_result <- TADA_GetATTAINSByAUID(empty_data, au_ref = my_au_ref)
@@ -1714,8 +1717,9 @@ TADA_CreateATTAINSAUMLCrosswalk <- function(.data, return_nearest = FALSE,
#' # Example 4: Custom AU reference data from an external file
#' # Load AU reference data from a CSV file and use it in the function
#' au_ref_from_file <- read.csv("path/to/au_ref.csv")
-#' result_with_file_au_ref <- TADA_GetATTAINSByAUID(my_data,
-#' au_ref = au_ref_from_file)
+#' result_with_file_au_ref <- TADA_GetATTAINSByAUID(my_data,
+#' au_ref = au_ref_from_file
+#' )
#' }
#'
TADA_GetATTAINSByAUID <- function(.data, au_ref = NULL, add_catch = FALSE) {
@@ -1788,16 +1792,20 @@ TADA_GetATTAINSByAUID <- function(.data, au_ref = NULL, add_catch = FALSE) {
# drop provider from au_ref
au_ref <- au_ref %>%
- dplyr::select(ATTAINS.AssessmentUnitIdentifier,
- ATTAINS.MonitoringLocationIdentifier)
+ dplyr::select(
+ ATTAINS.AssessmentUnitIdentifier,
+ ATTAINS.MonitoringLocationIdentifier
+ )
# filter detain to retain only results with known AUIDs
.data <- .data %>%
dplyr::filter(TADA.MonitoringLocationIdentifier %in% au_ref$ATTAINS.MonitoringLocationIdentifier)
filt.data <- .data %>%
- dplyr::select(TADA.MonitoringLocationIdentifier, TADA.LatitudeMeasure,
- TADA.LongitudeMeasure, HorizontalCoordinateReferenceSystemDatumName) %>%
+ dplyr::select(
+ TADA.MonitoringLocationIdentifier, TADA.LatitudeMeasure,
+ TADA.LongitudeMeasure, HorizontalCoordinateReferenceSystemDatumName
+ ) %>%
dplyr::distinct() %>%
TADA_MakeSpatial()
@@ -1814,7 +1822,6 @@ TADA_GetATTAINSByAUID <- function(.data, au_ref = NULL, add_catch = FALSE) {
# get water type info using EQ
get_wb_type <- function(au_list) {
-
au_list <- unique(au_list)
# split the au_list into chunks
@@ -1826,7 +1833,8 @@ TADA_GetATTAINSByAUID <- function(.data, au_ref = NULL, add_catch = FALSE) {
wat_type <- function(chunk) {
results <- spsUtil::quiet(rExpertQuery::EQ_AssessmentUnits(
api_key = "lfzVzpwIlKS1O4l1QmbOLUeTzxyql4QdbHVR5Yf5",
- auid = chunk))
+ auid = chunk
+ ))
}
results <- purrr::map_dfr(.x = chunks, .f = wat_type)
@@ -1842,7 +1850,8 @@ TADA_GetATTAINSByAUID <- function(.data, au_ref = NULL, add_catch = FALSE) {
# get water types
water_types <- try(
get_wb_type(au_ref$ATTAINS.AssessmentUnitIdentifier),
- silent = TRUE)
+ silent = TRUE
+ )
# function to download ATTAINS features API based on their name
@@ -1911,19 +1920,18 @@ TADA_GetATTAINSByAUID <- function(.data, au_ref = NULL, add_catch = FALSE) {
)
try(points <- points %>% dplyr::left_join(., water_types, by = c("assessmentunitidentifier" = "assessmentUnitId")),
- silent = TRUE
+ silent = TRUE
)
try(lines <- lines %>% dplyr::left_join(., water_types, by = c("assessmentunitidentifier" = "assessmentUnitId")),
- silent = TRUE
+ silent = TRUE
)
try(polygons <- polygons %>% dplyr::left_join(., water_types, by = c("assessmentunitidentifier" = "assessmentUnitId")),
- silent = TRUE
+ silent = TRUE
)
- if(add_catch == TRUE) {
-
+ if (add_catch == TRUE) {
try(
catchments <- fetch_au(
baseurls = baseurls[1],
@@ -1951,103 +1959,113 @@ TADA_GetATTAINSByAUID <- function(.data, au_ref = NULL, add_catch = FALSE) {
dplyr::distinct()
try(catchments <- catchments.filt %>% dplyr::left_join(., water_types, by = c("assessmentunitidentifier" = "assessmentUnitId")),
- silent = TRUE
+ silent = TRUE
)
# create internal function to rename cols coming from ATTAINS geospatial
TADA_with_ATTAINS <- .data %>%
- dplyr::left_join(au_ref, by = c("TADA.MonitoringLocationIdentifier" =
- "ATTAINS.MonitoringLocationIdentifier")) %>%
- dplyr::left_join(catchments.cw,
- dplyr::join_by(TADA.MonitoringLocationIdentifier)) %>%
+ dplyr::left_join(au_ref, by = c(
+ "TADA.MonitoringLocationIdentifier" =
+ "ATTAINS.MonitoringLocationIdentifier"
+ )) %>%
+ dplyr::left_join(
+ catchments.cw,
+ dplyr::join_by(TADA.MonitoringLocationIdentifier)
+ ) %>%
dplyr::left_join(catchments.no.geo,
- by = c("nhdplusid" = "nhdplusid",
- "ATTAINS.AssessmentUnitIdentifier" =
- "assessmentunitidentifier")) %>%
+ by = c(
+ "nhdplusid" = "nhdplusid",
+ "ATTAINS.AssessmentUnitIdentifier" =
+ "assessmentunitidentifier"
+ )
+ ) %>%
dplyr::select(-OBJECTID) %>%
- dplyr::rename(ATTAINS.SubmissionId = submissionid,
- ATTAINS.NhdPlusId = nhdplusid,
- ATTAINS.State = state,
- ATTAINS.Region = region,
- ATTAINS.OrganizationId = organizationid,
- ATTAINS.OrgType = orgtype,
- ATTAINS.Tas303d = tas303d,
- ATTAINS.OrganizationName = organizationname,
- ATTAINS.ReportingCycle = reportingcycle,
- ATTAINS.AssessmentUnitName = assessmentunitname,
- ATTAINS.WaterbodyReportLink = waterbodyreportlink,
- ATTAINS.AssmntJoinKey = assmnt_joinkey,
- ATTAINS.PermIdJoinKey = permid_joinkey,
- ATTAINS.IrCategory = ircategory,
- ATTAINS.OverallStatus = overallstatus,
- ATTAINS.IsAssessed = isassessed,
- ATTAINS.IsImpaired = isimpaired,
- ATTAINS.IsThreatened = isthreatened,
- ATTAINS.On303dList = on303dlist,
- ATTAINS.HasTmdl = hastmdl,
- ATTAINS.Has4bPlan = has4bplan,
- ATTAINS.HasAlternativePlan = hasalternativeplan,
- ATTAINS.HasProtectionPlan = hasprotectionplan,
- ATTAINS.VisionPriority303d = visionpriority303d,
- ATTAINS.AreaSqkm = areasqkm,
- ATTAINS.Huc12 = huc12,
- ATTAINS.XwalkMethod = xwalk_method,
- ATTAINS.WwalkHuc12Version= xwalk_huc12_version,
- ATTAINS.CatchmentAreaSqkm = catchmentareasqkm,
- ATTAINS.CatchmentStateCode = catchmentstatecode,
- ATTAINS.CatchmentIsTribal = catchmentistribal,
- ATTAINS.CatchmentResolution = catchmentresolution,
- ATTAINS.ShapeLength = Shape_Length,
- ATTAINS.ShapeArea = Shape_Area,
- ATTAINS.WaterType = waterType
+ dplyr::rename(
+ ATTAINS.SubmissionId = submissionid,
+ ATTAINS.NhdPlusId = nhdplusid,
+ ATTAINS.State = state,
+ ATTAINS.Region = region,
+ ATTAINS.OrganizationId = organizationid,
+ ATTAINS.OrgType = orgtype,
+ ATTAINS.Tas303d = tas303d,
+ ATTAINS.OrganizationName = organizationname,
+ ATTAINS.ReportingCycle = reportingcycle,
+ ATTAINS.AssessmentUnitName = assessmentunitname,
+ ATTAINS.WaterbodyReportLink = waterbodyreportlink,
+ ATTAINS.AssmntJoinKey = assmnt_joinkey,
+ ATTAINS.PermIdJoinKey = permid_joinkey,
+ ATTAINS.IrCategory = ircategory,
+ ATTAINS.OverallStatus = overallstatus,
+ ATTAINS.IsAssessed = isassessed,
+ ATTAINS.IsImpaired = isimpaired,
+ ATTAINS.IsThreatened = isthreatened,
+ ATTAINS.On303dList = on303dlist,
+ ATTAINS.HasTmdl = hastmdl,
+ ATTAINS.Has4bPlan = has4bplan,
+ ATTAINS.HasAlternativePlan = hasalternativeplan,
+ ATTAINS.HasProtectionPlan = hasprotectionplan,
+ ATTAINS.VisionPriority303d = visionpriority303d,
+ ATTAINS.AreaSqkm = areasqkm,
+ ATTAINS.Huc12 = huc12,
+ ATTAINS.XwalkMethod = xwalk_method,
+ ATTAINS.WwalkHuc12Version = xwalk_huc12_version,
+ ATTAINS.CatchmentAreaSqkm = catchmentareasqkm,
+ ATTAINS.CatchmentStateCode = catchmentstatecode,
+ ATTAINS.CatchmentIsTribal = catchmentistribal,
+ ATTAINS.CatchmentResolution = catchmentresolution,
+ ATTAINS.ShapeLength = Shape_Length,
+ ATTAINS.ShapeArea = Shape_Area,
+ ATTAINS.WaterType = waterType
)
}
- if(add_catch == FALSE) {
-
+ if (add_catch == FALSE) {
catchments <- NULL
- TADA_with_ATTAINS <- .data %>%
- dplyr::left_join(au_ref, by = c("TADA.MonitoringLocationIdentifier" =
- "ATTAINS.MonitoringLocationIdentifier")) %>%
- # when catchment/monitoring location crosswalk is available, that info can be added here
- # can add the assessment related info sooner via rExpertQuery functions (HRM 8/7/25)
- dplyr::mutate(ATTAINS.SubmissionId = NA,
- ATTAINS.NhdPlusId = NA,
- ATTAINS.State = NA,
- ATTAINS.Region = NA,
- ATTAINS.OrganizationId = NA,
- ATTAINS.OrgType = NA,
- ATTAINS.Tas303d = NA,
- ATTAINS.OrganizationName = NA,
- ATTAINS.ReportingCycle = NA,
- ATTAINS.AssessmentUnitName = NA,
- ATTAINS.WaterbodyReportLink = NA,
- ATTAINS.AssmntJoinKey = NA,
- ATTAINS.PermIdJoinKey = NA,
- ATTAINS.IrCategory = NA,
- ATTAINS.OverallStatus = NA,
- ATTAINS.IsAssessed = NA,
- ATTAINS.IsImpaired = NA,
- ATTAINS.IsThreatened = NA,
- ATTAINS.On303dList = NA,
- ATTAINS.HasTmdl = NA,
- ATTAINS.Has4bPlan = NA,
- ATTAINS.HasAlternativePlan = NA,
- ATTAINS.HasProtectionPlan = NA,
- ATTAINS.VisionPriority303d = NA,
- ATTAINS.AreaSqkm = NA,
- ATTAINS.Huc12 = NA,
- ATTAINS.XwalkMethod = NA,
- ATTAINS.WwalkHuc12Version= NA,
- ATTAINS.CatchmentAreaSqkm = NA,
- ATTAINS.CatchmentStateCode = NA,
- ATTAINS.CatchmentIsTribal = NA,
- ATTAINS.CatchmentResolution = NA,
- ATTAINS.ShapeLength = NA,
- ATTAINS.ShapeArea = NA,
- ATTAINS.WaterType = NA
- )
+ TADA_with_ATTAINS <- .data %>%
+ dplyr::left_join(au_ref, by = c(
+ "TADA.MonitoringLocationIdentifier" =
+ "ATTAINS.MonitoringLocationIdentifier"
+ )) %>%
+ # when catchment/monitoring location crosswalk is available, that info can be added here
+ # can add the assessment related info sooner via rExpertQuery functions (HRM 8/7/25)
+ dplyr::mutate(
+ ATTAINS.SubmissionId = NA,
+ ATTAINS.NhdPlusId = NA,
+ ATTAINS.State = NA,
+ ATTAINS.Region = NA,
+ ATTAINS.OrganizationId = NA,
+ ATTAINS.OrgType = NA,
+ ATTAINS.Tas303d = NA,
+ ATTAINS.OrganizationName = NA,
+ ATTAINS.ReportingCycle = NA,
+ ATTAINS.AssessmentUnitName = NA,
+ ATTAINS.WaterbodyReportLink = NA,
+ ATTAINS.AssmntJoinKey = NA,
+ ATTAINS.PermIdJoinKey = NA,
+ ATTAINS.IrCategory = NA,
+ ATTAINS.OverallStatus = NA,
+ ATTAINS.IsAssessed = NA,
+ ATTAINS.IsImpaired = NA,
+ ATTAINS.IsThreatened = NA,
+ ATTAINS.On303dList = NA,
+ ATTAINS.HasTmdl = NA,
+ ATTAINS.Has4bPlan = NA,
+ ATTAINS.HasAlternativePlan = NA,
+ ATTAINS.HasProtectionPlan = NA,
+ ATTAINS.VisionPriority303d = NA,
+ ATTAINS.AreaSqkm = NA,
+ ATTAINS.Huc12 = NA,
+ ATTAINS.XwalkMethod = NA,
+ ATTAINS.WwalkHuc12Version = NA,
+ ATTAINS.CatchmentAreaSqkm = NA,
+ ATTAINS.CatchmentStateCode = NA,
+ ATTAINS.CatchmentIsTribal = NA,
+ ATTAINS.CatchmentResolution = NA,
+ ATTAINS.ShapeLength = NA,
+ ATTAINS.ShapeArea = NA,
+ ATTAINS.WaterType = NA
+ )
}
final_features <- list(
@@ -2058,9 +2076,8 @@ TADA_GetATTAINSByAUID <- function(.data, au_ref = NULL, add_catch = FALSE) {
"ATTAINS_polygons" = polygons
)
- return(final_features)
-
- }
+ return(final_features)
+}
#' TADA_ViewATTAINS
@@ -2202,8 +2219,9 @@ TADA_ViewATTAINS <- function(.data) {
Organization_Count = length(unique(OrganizationIdentifier)),
ATTAINS_AUs = as.character(list(unique(ATTAINS.AssessmentUnitIdentifier))),
TADA.AURefSource = ifelse("TADA.AURefSource" %in% names(ATTAINS_table),
- as.character(TADA.AURefSource),
- "not provided")
+ as.character(TADA.AURefSource),
+ "not provided"
+ )
) %>%
dplyr::mutate(
ATTAINS_AUs = ifelse(is.na(ATTAINS_AUs), "None", ATTAINS_AUs),
@@ -2327,34 +2345,34 @@ TADA_ViewATTAINS <- function(.data) {
silent = TRUE
)
- if("TADA.AURefSource" %in% names(ATTAINS_table)) {
-
- # if TADA_AUSourceRef col exists in data
- set.fill <- leaflet::colorFactor(
- palette = c(tada.pal[1], tada.pal[12], tada.pal[13]),
- domain = c("User-supplied Ref",
- "ATTAINS crosswalk",
- "TADA_CreateATTAINSAUMLCrosswalk"))
-
- set.popup <- paste0(
- "Site ID: ", sumdat$MonitoringLocationIdentifier,
- "
Site Name: ", sumdat$MonitoringLocationName,
- "
Measurement Count: ", sumdat$Sample_Count,
- "
Visit Count: ", sumdat$Visit_Count,
- "
Characteristic Count: ", sumdat$Parameter_Count,
- "
ATTAINS Assessment Unit(s): ", sumdat$ATTAINS_AUs,
- "
Crosswalk Source: ", sumdat$TADA.AURefSource
- )
-
+ if ("TADA.AURefSource" %in% names(ATTAINS_table)) {
+ # if TADA_AUSourceRef col exists in data
+ set.fill <- leaflet::colorFactor(
+ palette = c(tada.pal[1], tada.pal[12], tada.pal[13]),
+ domain = c(
+ "User-supplied Ref",
+ "ATTAINS crosswalk",
+ "TADA_CreateATTAINSAUMLCrosswalk"
+ )
+ )
+ set.popup <- paste0(
+ "Site ID: ", sumdat$MonitoringLocationIdentifier,
+ "
Site Name: ", sumdat$MonitoringLocationName,
+ "
Measurement Count: ", sumdat$Sample_Count,
+ "
Visit Count: ", sumdat$Visit_Count,
+ "
Characteristic Count: ", sumdat$Parameter_Count,
+ "
ATTAINS Assessment Unit(s): ", sumdat$ATTAINS_AUs,
+ "
Crosswalk Source: ", sumdat$TADA.AURefSource
+ )
}
- if(!"TADA.AURefSource" %in% names(ATTAINS_table)) {
-
+ if (!"TADA.AURefSource" %in% names(ATTAINS_table)) {
# if TADA_AUSourceRef col exists in data
set.fill <- leaflet::colorFactor(
palette = c(tada.pal[1]),
- domain = sumdat$TADA.AURefSource)
+ domain = sumdat$TADA.AURefSource
+ )
set.popup <- paste0(
"Site ID: ", sumdat$MonitoringLocationIdentifier,
@@ -2367,16 +2385,16 @@ TADA_ViewATTAINS <- function(.data) {
}
- # Add WQP observation features (should always exist):
+ # Add WQP observation features (should always exist):
try(
map <- map %>%
leaflet::addCircleMarkers(
data = sumdat,
lng = ~LongitudeMeasure, lat = ~LatitudeMeasure,
- color = "grey", fillColor = ~set.fill(TADA.AURefSource),
+ color = "grey", fillColor = ~ set.fill(TADA.AURefSource),
fillOpacity = 0.8, stroke = TRUE, weight = 1.5, radius = 6,
popup = set.popup
- ),
+ ),
silent = TRUE
)
@@ -2816,7 +2834,7 @@ TADA_FindNearbySites <- function(.data, dist_buffer = 100,
# subset nearby sites
near.sites <- unique.mls %>%
dplyr::filter(TADA.MonitoringLocationIdentifier %in%
- group.sites$TADA.MonitoringLocationIdentifier) %>%
+ group.sites$TADA.MonitoringLocationIdentifier) %>%
dplyr::left_join(group.sites, by = dplyr::join_by(TADA.MonitoringLocationIdentifier))
# break into multiple dfs
@@ -2826,7 +2844,7 @@ TADA_FindNearbySites <- function(.data, dist_buffer = 100,
# fetch nhdplus catchment information
nhd.catch <- near.dfs %>%
purrr::map(~ .x %>%
- fetchNHD(resolution = nhd_res))
+ fetchNHD(resolution = nhd_res))
# remove any fetchNHD dfs that do not contain any data (to prevent bind rows error)
nhd.catch.filt <- purrr::keep(nhd.catch, ~ nrow(.) > 0)
@@ -2948,7 +2966,7 @@ TADA_FindNearbySites <- function(.data, dist_buffer = 100,
"TADA_FindNearbySites: ", length(missing.orgs),
" organization identifiers are missing from org_hierarchy (",
stringi::stri_replace_last(paste(missing.orgs, collapse = ", "),
- fixed = ", ", " and "
+ fixed = ", ", " and "
), ").",
" Function will continue to run using partial org_hierarchy."
))
@@ -3007,7 +3025,7 @@ TADA_FindNearbySites <- function(.data, dist_buffer = 100,
random.meta <- org.ranks.added %>%
dplyr::ungroup() %>%
dplyr::filter(!TADA.NearbySiteGroup %in%
- org.meta.filter$TADA.NearbySiteGroup) %>%
+ org.meta.filter$TADA.NearbySiteGroup) %>%
dplyr::group_by(TADA.NearbySiteGroup) %>%
dplyr::slice_min(OrgRank) %>%
dplyr::select(
@@ -3052,7 +3070,7 @@ TADA_FindNearbySites <- function(.data, dist_buffer = 100,
OrganizationIdentifier
)) %>%
dplyr::filter(!TADA.MonitoringLocationIdentifier.New %in%
- org.meta.filter$TADA.MonitoringLocationIdentifier.New) %>%
+ org.meta.filter$TADA.MonitoringLocationIdentifier.New) %>%
dplyr::mutate(OrgRank = ifelse(is.na(OrgRank), rank.default, OrgRank)) %>%
dplyr::group_by(TADA.MonitoringLocationIdentifier.New)
@@ -3148,24 +3166,24 @@ TADA_FindNearbySites <- function(.data, dist_buffer = 100,
dplyr::ungroup() %>%
dplyr::mutate(
TADA.MonitoringLocationName = ifelse(!is.na(TADA.MonitoringLocationName.New),
- TADA.MonitoringLocationName.New,
- TADA.MonitoringLocationName
+ TADA.MonitoringLocationName.New,
+ TADA.MonitoringLocationName
),
TADA.LatitudeMeasure = ifelse(!is.na(TADA.LatitudeMeasure.New),
- TADA.LatitudeMeasure.New,
- TADA.LatitudeMeasure
+ TADA.LatitudeMeasure.New,
+ TADA.LatitudeMeasure
),
TADA.LongitudeMeasure = ifelse(!is.na(TADA.LongitudeMeasure.New),
- TADA.LongitudeMeasure.New,
- TADA.LongitudeMeasure
+ TADA.LongitudeMeasure.New,
+ TADA.LongitudeMeasure
),
TADA.MonitoringLocationTypeName = ifelse(!is.na(TADA.MonitoringLocationTypeName.New),
- TADA.MonitoringLocationTypeName.New,
- TADA.MonitoringLocationTypeName
+ TADA.MonitoringLocationTypeName.New,
+ TADA.MonitoringLocationTypeName
),
TADA.MonitoringLocationIdentifier = ifelse(!is.na(TADA.MonitoringLocationIdentifier.New),
- TADA.MonitoringLocationIdentifier.New,
- TADA.MonitoringLocationIdentifier
+ TADA.MonitoringLocationIdentifier.New,
+ TADA.MonitoringLocationIdentifier
)
) %>%
dplyr::select(
@@ -3181,8 +3199,8 @@ TADA_FindNearbySites <- function(.data, dist_buffer = 100,
# add flag for any ungrouped sites and order columns correctly
.data <- TADA_OrderCols(.data) %>%
dplyr::mutate(TADA.NearbySites.Flag = ifelse(is.na(TADA.NearbySiteGroup),
- "No nearby sites detected using input buffer distance.",
- TADA.NearbySites.Flag
+ "No nearby sites detected using input buffer distance.",
+ TADA.NearbySites.Flag
))
# return TADA df with added columns for tracking
@@ -3357,7 +3375,7 @@ TADA_RandomTestingData <- function(number_of_days = 1, choose_random_state = FAL
#' @return A list containing a modified TADA data frame with added ATTAINS columns and
#' data frames for ATTAINS data and features for points, lines, polygons and catchments.
#' When batch_upload = TRUE, the list will contain an additional data frame formatted
-#' for compatibilty with ATTAINS batch upload for Monitoring_Stations.
+#' for compatibility with ATTAINS batch upload for Monitoring_Stations.
#'
#' @seealso [TADA_CreateATTAINSAUMLCrosswalk()]
#' [TADA_GetATTAINSAUMLCrosswalk()]
@@ -3366,13 +3384,12 @@ TADA_RandomTestingData <- function(number_of_days = 1, choose_random_state = FAL
#' @export
#'
TADA_CreateAUMLCrosswalk <- function(.data, au_ref = NULL,
- org_id = NULL, add_catch = FALSE,
- batch_upload = TRUE) {
+ org_id = NULL, add_catch = FALSE,
+ batch_upload = TRUE) {
# need to write checks for each component
# check for user supplied ref
- if(is.null(au_ref)) {
-
+ if (is.null(au_ref)) {
user.matches <- list(
"TADA_with_ATTAINS" = NULL,
"ATTAINS_catchments" = NULL,
@@ -3382,28 +3399,32 @@ TADA_CreateAUMLCrosswalk <- function(.data, au_ref = NULL,
)
}
- if(!is.null(au_ref)) {
-
- if(!is.data.frame(au_ref)) {
- stop(paste0("TADA_CreateAUMLCrosswalk: The user supplied au_ref must be a data frame ",
- "containg the columns AssessmentUnitIdentifier and MonitoringLocationIdentifier.",
- "MonitoringLocationIdentifiers must be WQP compatible."))
+ if (!is.null(au_ref)) {
+ if (!is.data.frame(au_ref)) {
+ stop(paste0(
+ "TADA_CreateAUMLCrosswalk: The user supplied au_ref must be a data frame ",
+ "containg the columns AssessmentUnitIdentifier and MonitoringLocationIdentifier.",
+ "MonitoringLocationIdentifiers must be WQP compatible."
+ ))
}
- if(is.data.frame(au_ref)) {
-
+ if (is.data.frame(au_ref)) {
print("TADA_CreateAUMLCrosswalk: fetching geospatial data for user-supplied crosswalk.")
- req.cols <- c("AssessmentUnitIdentifier",
- "MonitoringLocationIdentifier")
+ req.cols <- c(
+ "AssessmentUnitIdentifier",
+ "MonitoringLocationIdentifier"
+ )
# should this be using a more generic function?
TADA_CheckColumns(au_ref, req.cols)
# rename au_ref cols for nex function
au_ref <- au_ref %>%
- dplyr::rename(ATTAINS.MonitoringLocationIdentifier = MonitoringLocationIdentifier,
- ATTAINS.AssessmentUnitIdentifier = AssessmentUnitIdentifier)
+ dplyr::rename(
+ ATTAINS.MonitoringLocationIdentifier = MonitoringLocationIdentifier,
+ ATTAINS.AssessmentUnitIdentifier = AssessmentUnitIdentifier
+ )
# subset data for au_ref
au.ref.mls <- .data %>%
@@ -3412,7 +3433,8 @@ TADA_CreateAUMLCrosswalk <- function(.data, au_ref = NULL,
# get geospatial data for au_ref monitoring locations
user.matches <- spsUtil::quiet(
- TADA_GetATTAINSByAUID(au.ref.mls, au_ref = au_ref, add_catch = add_catch))
+ TADA_GetATTAINSByAUID(au.ref.mls, au_ref = au_ref, add_catch = add_catch)
+ )
}
}
@@ -3422,12 +3444,14 @@ TADA_CreateAUMLCrosswalk <- function(.data, au_ref = NULL,
print("TADA_CreateAUMLCrosswalk: checking for crosswalk in ATTAINS.")
attains.cw <- spsUtil::quiet(
- TADA_GetATTAINSAUMLCrosswalk(org_id = org_id))
-
- if(is.null(attains.cw)) {
+ TADA_GetATTAINSAUMLCrosswalk(org_id = org_id)
+ )
- print(paste0("TADA_CreateAUMLCrosswalk: There are no MonitoringLocation records ",
- "in ATTAINS for ", org_id, "."))
+ if (is.null(attains.cw)) {
+ print(paste0(
+ "TADA_CreateAUMLCrosswalk: There are no MonitoringLocation records ",
+ "in ATTAINS for ", org_id, "."
+ ))
attains.matches <- list(
"TADA_with_ATTAINS" = NULL,
@@ -3438,26 +3462,32 @@ TADA_CreateAUMLCrosswalk <- function(.data, au_ref = NULL,
)
}
- if(!is.null(attains.cw)) {
+ if (!is.null(attains.cw)) {
# we could remove or make this step optional, but it is very helpful for making sure
# monitoring location identifiers are WQP compatible
print("TADA_CreateAUMLCrosswalk: crosswalk from ATTAINS has been imported.")
attains.cw <- spsUtil::quiet(
- TADA_UpdateATTAINSAUMLCrosswalk(crosswalk = attains.cw,
- org_id = org_id,
- attains_replace = TRUE))
+ TADA_UpdateATTAINSAUMLCrosswalk(
+ crosswalk = attains.cw,
+ org_id = org_id,
+ attains_replace = TRUE
+ )
+ )
attains.cw.mls <- .data %>%
- dplyr::filter(!TADA.MonitoringLocationIdentifier %in% au.ref.mls$TADA.MonitoringLocationIdentifier,
- TADA.MonitoringLocationIdentifier %in% attains.cw$ATTAINS.MonitoringLocationIdentifier) %>%
+ dplyr::filter(
+ !TADA.MonitoringLocationIdentifier %in% au.ref.mls$TADA.MonitoringLocationIdentifier,
+ TADA.MonitoringLocationIdentifier %in% attains.cw$ATTAINS.MonitoringLocationIdentifier
+ ) %>%
dplyr::mutate(TADA.AURefSource = "ATTAINS crosswalk")
print("TADA_CreateAUMLCrosswalk: fetching geospatial data for crosswalk from ATTAINS.")
# get geospatial data for attains cw monitoring locations
attains.matches <- spsUtil::quiet(
- TADA_GetATTAINSByAUID(attains.cw.mls, au_ref = attains.cw, add_catch = add_catch))
+ TADA_GetATTAINSByAUID(attains.cw.mls, au_ref = attains.cw, add_catch = add_catch)
+ )
}
# TADA_CreateATTAINSAUMLCrosswalk section
@@ -3465,13 +3495,14 @@ TADA_CreateAUMLCrosswalk <- function(.data, au_ref = NULL,
print("TADA_CreateAUMLCrosswalk: checking to see if any unmatched MonitoringLocations remain")
get.attains.mls <- .data %>%
- dplyr::filter(!TADA.MonitoringLocationIdentifier %in% au.ref.mls$TADA.MonitoringLocationIdentifier,
- !TADA.MonitoringLocationIdentifier %in% attains.cw.mls$TADA.MonitoringLocationIdentifier) %>%
+ dplyr::filter(
+ !TADA.MonitoringLocationIdentifier %in% au.ref.mls$TADA.MonitoringLocationIdentifier,
+ !TADA.MonitoringLocationIdentifier %in% attains.cw.mls$TADA.MonitoringLocationIdentifier
+ ) %>%
dplyr::mutate(TADA.AURefSource = "TADA_CreateATTAINSAUMLCrosswalk")
# add code here for if there are no remaning mls to match
- if(dim(get.attains.mls)[1] == 0) {
-
+ if (dim(get.attains.mls)[1] == 0) {
print("TADA_CreateAUMLCrosswalk: all MonitoringLocations have already been matched by user or ATTAINS.")
get.attains.matches <- list(
@@ -3481,20 +3512,19 @@ TADA_CreateAUMLCrosswalk <- function(.data, au_ref = NULL,
"ATTAINS_lines" = NULL,
"ATTAINS_polygons" = NULL
)
-
}
- if(dim(get.attains.mls)[1] > 0) {
-
+ if (dim(get.attains.mls)[1] > 0) {
print("TADA_CreateAUMLCrosswalk: using TADA_CreateATTAINSAUMLCrosswalk to match remaining MonitoringLocations.")
# use get attains for matching remaining monitoring locations
- get.attains.matches <- spsUtil::quiet(
- TADA_CreateATTAINSAUMLCrosswalk(get.attains.mls, return_nearest = TRUE))
+ get.attains.matches <- spsUtil::quiet(
+ TADA_CreateATTAINSAUMLCrosswalk(get.attains.mls, return_nearest = TRUE)
+ )
}
# join all the resulting tables within each list to return as one large list
- #TADA_with_ATTAINS
+ # TADA_with_ATTAINS
print("TADA_CreateAUMLCrosswalk: joining results to return list of dataframes compatible with TADA_ViewATTAINS.")
@@ -3537,20 +3567,26 @@ TADA_CreateAUMLCrosswalk <- function(.data, au_ref = NULL,
"ATTAINS_polygons" = ATTAINS_polygons
)
- if(batch_upload == TRUE) {
+ if (batch_upload == TRUE) {
ATTAINS_batchupload <- TADA_with_ATTAINS %>%
sf::st_drop_geometry() %>%
- dplyr::select(TADA.MonitoringLocationIdentifier,
- ATTAINS.AssessmentUnitIdentifier,
- OrganizationIdentifier,
- ATTAINS.WaterType) %>%
+ dplyr::select(
+ TADA.MonitoringLocationIdentifier,
+ ATTAINS.AssessmentUnitIdentifier,
+ OrganizationIdentifier,
+ ATTAINS.WaterType
+ ) %>%
dplyr::distinct() %>%
- dplyr::rename(MS_LOCATION_ID = TADA.MonitoringLocationIdentifier,
- ASSESSMENT_UNIT_ID = ATTAINS.AssessmentUnitIdentifier,
- MS_ORG_ID = OrganizationIdentifier) %>%
+ dplyr::rename(
+ MS_LOCATION_ID = TADA.MonitoringLocationIdentifier,
+ ASSESSMENT_UNIT_ID = ATTAINS.AssessmentUnitIdentifier,
+ MS_ORG_ID = OrganizationIdentifier
+ ) %>%
dplyr::mutate(MS_DATA_LINK = NA) %>%
- dplyr::select(ASSESSMENT_UNIT_ID, MS_ORG_ID, MS_LOCATION_ID,
- MS_DATA_LINK, ATTAINS.WaterType)
+ dplyr::select(
+ ASSESSMENT_UNIT_ID, MS_ORG_ID, MS_LOCATION_ID,
+ MS_DATA_LINK, ATTAINS.WaterType
+ )
final_list <- c(final_list, list("ATTAINS_batchupload" = ATTAINS_batchupload))
}
diff --git a/R/RequiredCols.R b/R/RequiredCols.R
index b6e9f2a9a..028f7057b 100644
--- a/R/RequiredCols.R
+++ b/R/RequiredCols.R
@@ -298,8 +298,10 @@ last.cols <- c(
#'
#' # Construct URLs for different profiles
#' station_url <- paste0(baseurl, "/data/Station", filters, dates, type, providers)
-#' result_url <- paste0(baseurl, "/data/Result", filters, dates, type,
-#' "&dataProfile=resultPhysChem", providers)
+#' result_url <- paste0(
+#' baseurl, "/data/Result", filters, dates, type,
+#' "&dataProfile=resultPhysChem", providers
+#' )
#' project_url <- paste0(baseurl, "/data/Project", filters, dates, type, providers)
#'
#' # Use TADA_ReadWQPWebServices to load Station, Project, and Phys-Chem Result profiles
@@ -471,7 +473,7 @@ TADA_CheckRequiredFields <- function(.data) {
#' other TADA functions or are commonly used filters. Using this function allows the user to accept
#' all TADA created changes and reduce the size of the data set before using TADA mapping or data
#' visualization features in the TADA package or Shiny app.
-#'
+#'
#' This function also removes any columns not required for the TADA workflow
#' where all values are equal to NA. It provides a warning message identifying
#' any TADA required columns containing only NA values.
@@ -488,42 +490,41 @@ TADA_CheckRequiredFields <- function(.data) {
#' reducedcols_Data_Nutrients_UT <- TADA_RetainRequired(Data_Nutrients_UT)
#'
TADA_RetainRequired <- function(.data) {
-
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
# execute function after TADA_CheckType passes
-
+
############################
# first, remove columns that are not required for TADA workflow and contain only NA
print("TADA_RetainRequired: removing columns not required for TADA workflow if they contain only NAs.")
-
+
# create list of columns containing all NA values.
na.cols <- .data %>%
purrr::keep(~ all(is.na(.x))) %>%
names()
-
+
# create list of columns to be removed by comparing columns containing all NA
# values to required columns.
# any required columns with all NA values will be excluded from the list of
# columns to remove.
remove.cols <- setdiff(na.cols, require.cols)
-
+
# remove not required columns containing all NA values from dataframe.
.data <- .data %>%
dplyr::select(-dplyr::contains(remove.cols))
-
+
# check to make sure required columns contain some data that is not NA
req.check <- intersect(require.cols, na.cols)
-
+
# create character string for list of required columns containing only NAs
req.paste <- stringi::stri_replace_last_fixed(paste(as.character(req.check), collapse = ", ", sep = ""), ", ", " and ")
-
+
# remove column name lists
rm(na.cols)
-
+
# create character string for list of removed columns
remove.paste <- stringi::stri_replace_last_fixed(paste(as.character(remove.cols), collapse = ", ", sep = ""), ", ", " and ")
-
+
# print list of columns removed from data frame
if (length(remove.cols) > 0) {
print(paste0(
@@ -533,10 +534,10 @@ TADA_RetainRequired <- function(.data) {
} else {
print("All columns contained some non-NA values and were retained in the dataframe.")
}
-
+
# remove columns that are not required for TADA workflow
print("TADA_RetainRequired: checking required columns for non-NA values.")
-
+
# if some required columns contain only NA values print a warning message.
if (length(req.check) > 0) {
print(paste0(
@@ -546,12 +547,12 @@ TADA_RetainRequired <- function(.data) {
} else {
print("TADA_RetainRequired: All TADA Required columns contain some non-NA values.")
}
-
+
# remove intermediate objects
rm(req.paste, remove.cols, remove.paste, req.check)
-
+
######################
-
+
# Now removing any columns not required for the TADA workflow where all values are equal to NA
print("TADA_RetainRequired: removing columns not required for TADA workflow including original columns that have been replaced with TADA prefix duplicates.")
@@ -575,7 +576,7 @@ TADA_RetainRequired <- function(.data) {
print(paste("TADA_RetainRequired: The following non-required columns were removed: ", remove.paste, ".", sep = ""))
return(.data)
-
+
# remove intermediate objects
rm(keep.cols, original.cols, remove.cols, remove.paste)
}
@@ -599,37 +600,37 @@ TADA_RetainRequired <- function(.data) {
#' TADA_AutoFilter <- function(.data) {
#' # check .data is data.frame
#' TADA_CheckType(.data, "data.frame", "Input object")
-#'
+#'
#' # remove columns that are not required for TADA workflow
#' print("TADA_AutoFilter: removing columns not required for TADA workflow if they contain only NAs.")
-#'
+#'
#' # create list of columns containing all NA values.
#' na.cols <- .data %>%
#' purrr::keep(~ all(is.na(.x))) %>%
#' names()
-#'
+#'
#' # create list of columns to be removed by comparing columns containing all NA
#' # values to required columns.
#' # any required columns with all NA values will be excluded from the list of
#' # columns to remove.
#' remove.cols <- setdiff(na.cols, require.cols)
-#'
+#'
#' # remove not required columns containing all NA values from dataframe.
#' .data <- .data %>%
#' dplyr::select(-dplyr::contains(remove.cols))
-#'
+#'
#' # check to make sure required columns contain some data that is not NA
#' req.check <- intersect(require.cols, na.cols)
-#'
+#'
#' # create character string for list of required columns containing only NAs
#' req.paste <- stringi::stri_replace_last_fixed(paste(as.character(req.check), collapse = ", ", sep = ""), ", ", " and ")
-#'
+#'
#' # remove column name lists
#' rm(na.cols)
-#'
+#'
#' # create character string for list of removed columns
#' remove.paste <- stringi::stri_replace_last_fixed(paste(as.character(remove.cols), collapse = ", ", sep = ""), ", ", " and ")
-#'
+#'
#' # print list of columns removed from data frame
#' if (length(remove.cols) > 0) {
#' print(paste0(
@@ -639,10 +640,10 @@ TADA_RetainRequired <- function(.data) {
#' } else {
#' print("All columns contained some non-NA values and were retained in the dataframe.")
#' }
-#'
+#'
#' # remove columns that are not required for TADA workflow
#' print("TADA_AutoFilter: checking required columns for non-NA values.")
-#'
+#'
#' # if some required columns contain only NA values print a warning message.
#' if (length(req.check) > 0) {
#' print(paste0(
@@ -652,9 +653,9 @@ TADA_RetainRequired <- function(.data) {
#' } else {
#' print("TADA_AutoFilter: All TADA Required columns contain some non-NA values.")
#' }
-#'
+#'
#' # remove intermediate objects
#' rm(req.paste, remove.cols, remove.paste, req.check)
-#'
+#'
#' return(.data)
#' }
diff --git a/R/ResultFlagsDependent.R b/R/ResultFlagsDependent.R
index d18273d44..908244b2d 100644
--- a/R/ResultFlagsDependent.R
+++ b/R/ResultFlagsDependent.R
@@ -56,7 +56,8 @@ TADA_FlagFraction <- function(.data, clean = TRUE, flaggedonly = FALSE) {
TADA_CheckColumns(.data, c("TADA.CharacteristicName", "TADA.ResultSampleFractionText"))
# check that both clean and flaggedonly are not TRUE
if (clean == TRUE & flaggedonly == TRUE) {
- stop("Function not executed because clean and flaggedonly cannot both be TRUE")
+ message("Function not executed because clean and flaggedonly cannot both be TRUE")
+ return(.data)
}
# execute function after checks are passed - removes flag column in case reference table has changed.
@@ -722,11 +723,13 @@ TADA_PairReplicates <- function(.data, type = c("QC_replicate"), time_difference
# execute function after checks are passed
if ("QC_replicate" %in% type) {
if (nrow(dplyr::filter(.data, .data$TADA.ActivityType.Flag == "QC_replicate")) == 0) {
- stop("Function not executed because no replicates found in dataframe.")
+ message("Function not executed because no replicates found in dataframe.")
+ return(.data)
}
} else {
if (nrow(dplyr::filter(.data, .data$ActivityTypeCode %in% type)) == 0) {
- stop(paste0("Function not executed because no replicates of type '", type, "' found in dataframe."))
+ message(paste0("Function not executed because no replicates of type '", type, "' found in dataframe."))
+ return(.data)
}
}
# check type is character
diff --git a/R/ResultFlagsIndependent.R b/R/ResultFlagsIndependent.R
index 725d16e68..9d67114a0 100644
--- a/R/ResultFlagsIndependent.R
+++ b/R/ResultFlagsIndependent.R
@@ -427,11 +427,11 @@ TADA_FlagContinuousData <- function(.data, clean = FALSE, flaggedonly = FALSE, t
#' and flaggedonly = FALSE.
#'
#' This function will add the column `TADA.ResultValueAboveUpperThreshold.Flag` which
-#' will be populated with the values: `Pass`, `Suspect`, `Not Reviewed`,
+#' will be populated with the values: `Pass`, `Suspect`, `Not Reviewed`,
#' or `NA - Not Available`. The `Not Reviewed` value means that the EPA WQX team
#' has not yet reviewed the range yet for the characteristic and unit combination combination
#' in that row (see https://cdx.epa.gov/wqx/download/DomainValues/QAQCCharacteristicValidation.CSV).
-#' The WQX team plans to review and update these new combinations quarterly.
+#' The WQX team plans to review and update these new combinations quarterly.
#' The `NA - Not Available` flag means that the characteristic, media, and/or unit combination
#' for that row is not fully populated (is NA or does not match the WQX data standard)
#' or the result value is NA.
@@ -635,11 +635,11 @@ TADA_FlagAboveThreshold <- function(.data, clean = FALSE, flaggedonly = FALSE) {
#' and flaggedonly = FALSE.
#'
#' This function will add the column `TADA.ResultValueBelowLowerThreshold.Flag` which
-#' will be populated with the values: `Pass`, `Suspect`, `Not Reviewed`,
+#' will be populated with the values: `Pass`, `Suspect`, `Not Reviewed`,
#' or `NA - Not Available`. The “Not Reviewed” value means that the EPA WQX team
#' has not yet reviewed the range yet for the characteristic and unit combination combination
#' in that row (see https://cdx.epa.gov/wqx/download/DomainValues/QAQCCharacteristicValidation.CSV).
-#' The WQX team plans to review and update these new combinations quarterly.
+#' The WQX team plans to review and update these new combinations quarterly.
#' The `NA - Not Available` flag means that the characteristic, media, and/or unit combination
#' for that row is not fully populated (is NA or does not match the WQX data standard)
#' or the result value is NA.
@@ -827,18 +827,18 @@ TADA_FlagBelowThreshold <- function(.data, clean = FALSE, flaggedonly = FALSE) {
#' Check Data for an Approved QAPP
#'
-#' This function evaluates the data submitted under the "QAPPApprovedIndicator"
-#' column to determine if it has an approved Quality Assurance Project Plan (QAPP).
-#' Organizations use this field to indicate approval status,
-#' where 'Y' denotes approval and 'N' denotes non-approval.
-#' The function provides flexibility through three
-#' boolean arguments: `clean`, `cleanNA`, and `flaggedonly`, which control the
+#' This function evaluates the data submitted under the "QAPPApprovedIndicator"
+#' column to determine if it has an approved Quality Assurance Project Plan (QAPP).
+#' Organizations use this field to indicate approval status,
+#' where 'Y' denotes approval and 'N' denotes non-approval.
+#' The function provides flexibility through three
+#' boolean arguments: `clean`, `cleanNA`, and `flaggedonly`, which control the
#' filtering behavior of the data.
#'
#' @param .data A dataframe containing the QAPP data.
-#' @param clean Logical. If `TRUE`, removes rows where `QAPPApprovedIndicator`
+#' @param clean Logical. If `TRUE`, removes rows where `QAPPApprovedIndicator`
#' equals 'N'. Default is `FALSE`.
-#' @param cleanNA Logical. If `TRUE`, removes rows where `QAPPApprovedIndicator`
+#' @param cleanNA Logical. If `TRUE`, removes rows where `QAPPApprovedIndicator`
#' is NA. Default is `FALSE`.
#' @param flaggedonly Logical. If `TRUE`, filters out rows where
#' `QAPPApprovedIndicator` equals 'Y'. Default is `FALSE`.
@@ -853,9 +853,9 @@ TADA_FlagBelowThreshold <- function(.data, clean = FALSE, flaggedonly = FALSE) {
#' - Set `cleanNA = TRUE` to remove rows with NA values.
#' - Set `flaggedonly = TRUE` to filter out rows where `QAPPApprovedIndicator` equals 'Y'.
#'
-#' Note: The `QAPPApprovedIndicator` field is optional and often left blank (NA),
-#' even if the data is associated with a QAPP. Most organizations collecting
-#' monitoring data using 106 funding are required to have an EPA-approved QAPP,
+#' Note: The `QAPPApprovedIndicator` field is optional and often left blank (NA),
+#' even if the data is associated with a QAPP. Most organizations collecting
+#' monitoring data using 106 funding are required to have an EPA-approved QAPP,
#' hence most data should have an approved QAPP even if submitted as NA.
#'
#' @return A filtered dataframe based on the combination of input parameters:
diff --git a/R/TADARefTables.R b/R/TADARefTables.R
index 49b29fe00..5df3d254e 100644
--- a/R/TADARefTables.R
+++ b/R/TADARefTables.R
@@ -11,9 +11,10 @@
#' @export
TADA_GetNutrientSummationRef <- function() {
- ref <- utils::read.csv(system.file("extdata",
- "NPsummation_key.csv",
- package = "EPATADA"))
+ ref <- utils::read.csv(system.file("extdata",
+ "NPsummation_key.csv",
+ package = "EPATADA"
+ ))
return(ref)
}
diff --git a/R/Transformations.R b/R/Transformations.R
index 3a69671a1..2661ec0b5 100644
--- a/R/Transformations.R
+++ b/R/Transformations.R
@@ -24,7 +24,7 @@
#' NO3 will be converted to as N using molecular weight conversion factors.
#'
#' @return The input TADA dataframe with the TADA.CharacteristicName,
-#' TADA.ResultSampleFractionText, and TADA.MethodSpeciationName columns
+#' TADA.ResultSampleFractionText, and TADA.MethodSpeciationName columns
#' converted to the target values,
#' if supplied. Also includes additional columns
#' TADA.CharacteristicNameAssumptions, TADA.FractionAssumptions, and
@@ -65,11 +65,11 @@
TADA_HarmonizeSynonyms <- function(.data, ref, np_speciation = TRUE) {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
+ return(NULL) # Exit the function early
}
# check .data has the required columns
@@ -227,10 +227,10 @@ TADA_HarmonizeSynonyms <- function(.data, ref, np_speciation = TRUE) {
#' and date. Where necessary, it uses conversion factors to convert
#' nitrogen subspecies expressed as nitrate, nitrite, ammonia, ammonium, etc. to
#' as nitrogen based on the atomic weights of the different elements in the
-#' compound. Similarly, phosphate and other phosphorus forms are converted to
+#' compound. Similarly, phosphate and other phosphorus forms are converted to
#' AS P where applicable. The reference table is contained within the package but may be
-#' edited/customized by users.
-#'
+#' edited/customized by users.
+#'
#' Nutrient equations are as follows:
#'
#' NITROGEN:
@@ -254,13 +254,13 @@ TADA_HarmonizeSynonyms <- function(.data, ref, np_speciation = TRUE) {
#' and fewer subspecies). Eventually, even groups with only one subspecies will
#' be used to represent a TOTAL N value for that site/day/depth.
#'
-#' @param .data TADA dataframe. TADA_AutoClean() must have been run (and the
+#' @param .data TADA dataframe. TADA_AutoClean() must have been run (and the
#' TADA.ResultMeasureValueDataTypes.Flag added)
-#' before this TM/TP summation function can be used.
-#' This function runs required flag functions
+#' before this TM/TP summation function can be used.
+#' This function runs required flag functions
#' (TADA_FindQCActivities, TADA_FlagResultUnit, TADA_FlagFraction, TADA_FlagSpeciation) if
-#' they have not yet been run. Suspect and invalid combinations are not included in
-#' TN and TP summation. While not required for this function to run, ideally,
+#' they have not yet been run. Suspect and invalid combinations are not included in
+#' TN and TP summation. While not required for this function to run, ideally,
#' users should also run TADA_SimpleCensoredMethods
#' and TADA_HarmonizeSynonyms before this function.
#' If user wants to consider grouping N or P subspecies across multiple
@@ -270,10 +270,10 @@ TADA_HarmonizeSynonyms <- function(.data, ref, np_speciation = TRUE) {
#' @param sum_ref Optional. A custom summation reference dataframe the user has
#' loaded into the R environment. Dataframe must have same columns as default
#' TADA.summation reference table.
-#' @param daily_agg If there are multiple measurements for the same
-#' characteristic-unit-fraction-speciation-media combination at the same location
-#' (TADA.MonitoringLocationIdentifier) on the same day (ActivityStartDate),
-#' this will select a single measurement to use in the
+#' @param daily_agg If there are multiple measurements for the same
+#' characteristic-unit-fraction-speciation-media combination at the same location
+#' (TADA.MonitoringLocationIdentifier) on the same day (ActivityStartDate),
+#' this will select a single measurement to use in the
#' Total N or Total P summation. Defaults to 'max', but can be set
#' to 'min' or 'mean'.
#'
@@ -297,38 +297,41 @@ TADA_HarmonizeSynonyms <- function(.data, ref, np_speciation = TRUE) {
#' @seealso [TADA_FlagFraction()]
#' @seealso [TADA_FlagSpeciation()]
#' @seealso [TADA_AutoClean()]
-#'
+#'
#' @export
-#'
+#'
#' @examples
#' \dontrun{
-#' df <- TADA_DataRetrieval(statecode = "UT", startDate = "2024-06-01",
-#' endDate = "2024-07-01", characteristicType = "Nutrient", applyautoclean = TRUE,
-#' ask = FALSE)
-#'
-#' df2 <- TADA_SimpleCensoredMethods(df, nd_method = "multiplier",
-#' nd_multiplier = 0.5, od_method = "as-is", od_multiplier = "null")
-#'
+#' df <- TADA_DataRetrieval(
+#' statecode = "UT", startDate = "2024-06-01",
+#' endDate = "2024-07-01", characteristicType = "Nutrient", applyautoclean = TRUE,
+#' ask = FALSE
+#' )
+#'
+#' df2 <- TADA_SimpleCensoredMethods(df,
+#' nd_method = "multiplier",
+#' nd_multiplier = 0.5, od_method = "as-is", od_multiplier = "null"
+#' )
+#'
#' df2 <- TADA_RunKeyFlagFunctions(df2, clean = TRUE)
-#'
+#'
#' df2 <- TADA_HarmonizeSynonyms(df2)
-#'
+#'
#' df3 <- TADA_CalculateTotalNP(df2, daily_agg = "max")
#' }
-#'
-TADA_CalculateTotalNP <- function(.data,
- sum_ref,
+#'
+TADA_CalculateTotalNP <- function(.data,
+ sum_ref,
daily_agg = c("max", "min", "mean")) {
-
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
+ return(NULL) # Exit the function early
}
-
+
# check to make sure daily_agg is populated with allowable value
daily_agg <- match.arg(daily_agg)
@@ -365,92 +368,109 @@ TADA_CalculateTotalNP <- function(.data,
# check if QC flag function ran and message warning if not
if (!"TADA.ActivityType.Flag" %in% names(.data)) {
message("TADA_CalculateTotalNP: Your input dataset was missing the TADA.ActivityType.Flag column, suggesting that QC replicates have not been addressed or reviewed. Running the TADA_FindQCActivities function with the clean = FALSE option before executing this function. This function will not include QC results when aggregating to a daily maximum and total nutrient value.")
- .data = TADA_FindQCActivities(.data, clean = FALSE)
+ .data <- TADA_FindQCActivities(.data, clean = FALSE)
}
-
+
# check if unit flag function ran and message warning if not
if (!"TADA.ResultUnit.Flag" %in% names(.data)) {
message("TADA_CalculateTotalNP: Your input dataset was missing the TADA.ResultUnit.Flag column, suggesting that unit and characteristic combinations have not been addressed or reviewed. Running the TADA_FlagResultUnit function with the clean = FALSE option before executing this function. This function will not include results with invalid or suspect units when aggregating to a daily maximum and total nutrient value.")
- .data = TADA_FlagResultUnit(.data, clean = "none")
+ .data <- TADA_FlagResultUnit(.data, clean = "none")
}
-
+
# check if fraction flag function ran and message if not
if (!"TADA.SampleFraction.Flag" %in% names(.data)) {
message("TADA_CalculateTotalNP: Your input dataset was missing the TADA.SampleFraction.Flag column, suggesting that fraction and characteristic combinations have not been addressed or reviewed. Running the TADA_FlagFraction function with the clean = FALSE option before executing this function. This function will not include results with invalid or suspect fractions when aggregating to a daily maximum and total nutrient value.")
- .data = TADA_FlagFraction(.data, clean = FALSE)
+ .data <- TADA_FlagFraction(.data, clean = FALSE)
}
-
+
# check if speciation flag function ran and message warning if not
if (!"TADA.MethodSpeciation.Flag" %in% names(.data)) {
message("TADA_CalculateTotalNP: Your input dataset was missing the TADA.MethodSpeciation.Flag column, suggesting that speciation and characteristic combinations have not been addressed or reviewed. Running the TADA_FlagSpeciation function with the clean = FALSE option before executing this function. This function will not include results with invalid or suspect speciations when aggregating to a daily maximum and total nutrient value.")
- .data = TADA_FlagSpeciation(.data, clean = "none")
+ .data <- TADA_FlagSpeciation(.data, clean = "none")
}
-
+
# Check if the specified values are present in the TADA.ResultMeasureValueDataTypes.Flag column
- if (any(.data$TADA.ResultMeasureValueDataTypes.Flag %in% c("TP estimated from one or more subspecies.",
- "TN estimated from one or more subspecies."))) {
+ if (any(.data$TADA.ResultMeasureValueDataTypes.Flag %in% c(
+ "TP estimated from one or more subspecies.",
+ "TN estimated from one or more subspecies."
+ ))) {
# Notify the user that execution is halted
message(paste("TADA_CalculateTotalNP has already been run. Returning data unchanged. See TADA.ResultMeasureValueDataTypes.Flag column."))
return(.data)
}
-
+
# Create the include and exclude data frames
include_df <- .data[.data$TADA.ActivityType.Flag == "Non_QC" &
- (.data$TADA.ResultMeasureValueDataTypes.Flag %in%
- c("Numeric",
- "Result Value/Unit Estimated from Detection Limit",
- "Less Than",
- "Percentage",
- "Approximate Value",
- "Greater Than",
- "Comma-Separated Numeric",
- "Numeric Range - Averaged",
- "Percentage Range - Averaged",
- "Approximate Value",
- "Result Value/Unit Copied from Detection Limit"
- )) &
- (.data$TADA.ResultUnit.Flag %in%
- c("Pass",
- "Not Reviewed")) &
- (.data$TADA.SampleFraction.Flag %in%
- c("Pass",
- "Not Reviewed")) &
- (.data$TADA.MethodSpeciation.Flag %in%
- c("Pass",
- "Not Reviewed")), ]
-
+ (.data$TADA.ResultMeasureValueDataTypes.Flag %in%
+ c(
+ "Numeric",
+ "Result Value/Unit Estimated from Detection Limit",
+ "Less Than",
+ "Percentage",
+ "Approximate Value",
+ "Greater Than",
+ "Comma-Separated Numeric",
+ "Numeric Range - Averaged",
+ "Percentage Range - Averaged",
+ "Approximate Value",
+ "Result Value/Unit Copied from Detection Limit"
+ )) &
+ (.data$TADA.ResultUnit.Flag %in%
+ c(
+ "Pass",
+ "Not Reviewed"
+ )) &
+ (.data$TADA.SampleFraction.Flag %in%
+ c(
+ "Pass",
+ "Not Reviewed"
+ )) &
+ (.data$TADA.MethodSpeciation.Flag %in%
+ c(
+ "Pass",
+ "Not Reviewed"
+ )), ]
+
exclude_df <- .data[.data$TADA.ActivityType.Flag != "Non_QC" |
- is.na(.data$TADA.ResultMeasureValueDataTypes.Flag) |
- (.data$TADA.ResultMeasureValueDataTypes.Flag %in%
- c("NA - Not Available",
- "Text",
- "Non-ASCII Character(s)",
- "Result Value/Unit Cannot Be Estimated From Detection Limit",
- "Coerced to NA")) |
- !(.data$TADA.ResultUnit.Flag %in%
- c("Pass",
- "Not Reviewed")) |
- !(.data$TADA.SampleFraction.Flag %in%
- c("Pass",
- "Not Reviewed")) |
- !(.data$TADA.MethodSpeciation.Flag %in%
- c("Pass",
- "Not Reviewed")), ]
-
+ is.na(.data$TADA.ResultMeasureValueDataTypes.Flag) |
+ (.data$TADA.ResultMeasureValueDataTypes.Flag %in%
+ c(
+ "NA - Not Available",
+ "Text",
+ "Non-ASCII Character(s)",
+ "Result Value/Unit Cannot Be Estimated From Detection Limit",
+ "Coerced to NA"
+ )) |
+ !(.data$TADA.ResultUnit.Flag %in%
+ c(
+ "Pass",
+ "Not Reviewed"
+ )) |
+ !(.data$TADA.SampleFraction.Flag %in%
+ c(
+ "Pass",
+ "Not Reviewed"
+ )) |
+ !(.data$TADA.MethodSpeciation.Flag %in%
+ c(
+ "Pass",
+ "Not Reviewed"
+ )), ]
+
# add flags noting these are not used in TN/TP summation
exclude_df <- exclude_df %>%
dplyr::mutate(TADA.NutrientSummation.Flag = "Not used to calculate Total N or P.") %>%
dplyr::mutate(TADA.ResultValueAggregation.Flag = "Not considered in max aggregation function")
-
+
# # For function testing only
# # Calculate the number of rows in each data frame
# total_rows_data <- nrow(.data)
# total_rows_include <- nrow(include_df)
# total_rows_exclude <- nrow(exclude_df)
- #
+ #
# # Check if the sum of rows in include_df and exclude_df equals the total rows in .data
# test_result <- total_rows_include + total_rows_exclude == total_rows_data
- #
+ #
# # Print the test result
# if (test_result) {
# print("Test passed: The sum of rows in include_df and exclude_df equals the total rows in .data.")
@@ -465,10 +485,10 @@ TADA_CalculateTotalNP <- function(.data,
} else {
sum_ref <- TADA_GetNutrientSummationRef()
}
-
+
# Get grouping cols for daily aggregation
# create nutrient groups by site and date
-
+
# # used to include depth as well. cm removed 8/6/25
# depths <- names(include_df)[grepl("DepthHeightMeasure", names(include_df))]
# depths <- depths[grepl("TADA.", depths)]
@@ -480,10 +500,10 @@ TADA_CalculateTotalNP <- function(.data,
"TADA.LatitudeMeasure",
"TADA.ActivityMediaName",
"TADA.ComparableDataIdentifier",
- "TADA.ResultMeasure.MeasureUnitCode",
- "TADA.CharacteristicName",
+ "TADA.ResultMeasure.MeasureUnitCode",
+ "TADA.CharacteristicName",
"TADA.MethodSpeciationName",
- "TADA.ResultSampleFractionText",
+ "TADA.ResultSampleFractionText",
"OrganizationIdentifier",
"OrganizationFormalName",
"CountryCode",
@@ -493,13 +513,14 @@ TADA_CalculateTotalNP <- function(.data,
"MonitoringLocationTypeName",
"MonitoringLocationDescriptionText"
# "ActivityRelativeDepthName"
- # depths # does not make sense for daily aggregation of a max value. Use max value for day regardless of depth
+ # depths # does not make sense for daily aggregation of a max value. Use max value for day regardless of depth
)
- dat <- suppressMessages(TADA_AggregateMeasurements(include_df,
- grouping_cols = grpcols,
- agg_fun = daily_agg,
- clean = FALSE))
+ dat <- suppressMessages(TADA_AggregateMeasurements(include_df,
+ grouping_cols = grpcols,
+ agg_fun = daily_agg,
+ clean = FALSE
+ ))
# # for function review only
# dat_subset <- dat %>%
# select(all_of(c(
@@ -508,7 +529,7 @@ TADA_CalculateTotalNP <- function(.data,
# "TADA.ActivityMediaName",
# "TADA.ComparableDataIdentifier",
# "TADA.ResultValueAggregation.Flag")))
-
+
# Add rows not selected back at end but do not include in TN/TP summation
# Define the condition for rows to be added back
condition <- paste0("Considered in ", daily_agg, " aggregation function but not selected")
@@ -522,27 +543,30 @@ TADA_CalculateTotalNP <- function(.data,
if (dim(dat_addback)[1] > 0) {
dat_addback$TADA.NutrientSummation.Flag <- "Not used to calculate Total N or P."
}
+
+ # Move forward with this subset of data (dat_TNTP)
+ # Define the valid flags for aggregation
+ valid_flags <- c("No aggregation needed", paste0("Selected as ", daily_agg, " aggregate value"))
- # move forward with only max values selected for each grouping (dat_TNTP)
- # TADA.ResultValueAggregation.Flag should be "No aggregation needed" OR "Selected as max aggregate value"
- # no longer need "Considered in max aggregation function but not selected"
- # Define the condition for filtering
- matching_rows <- dat$TADA.ResultValueAggregation.Flag %in%
- c("No aggregation needed", paste0("Selected as ", daily_agg, " aggregate value"))
- # Check if matching_rows is not empty
- if (length(matching_rows) > 0) {
- # Filter dat based on the condition
+ # Check if the flag column exists in the data frame and if any rows match the condition
+ if ("TADA.ResultValueAggregation.Flag" %in% names(dat) && any(dat$TADA.ResultValueAggregation.Flag %in% valid_flags)) {
+ # Filter rows based on valid flags
+ matching_rows <- dat$TADA.ResultValueAggregation.Flag %in% valid_flags
+
+ # Filter the data
dat_TNTP <- dat[matching_rows, ]
} else {
- # Stop function execution and return a message
+ # Handle the case where the column does not exist or no rows match the condition
message("There is no applicable data to calculate TN or TP. Returning data unchanged.")
- return(.data)
+ return(.data) # Stop execution and return the original data
}
+ # If execution reaches here, dat_TNTP contains the filtered data
+
# join data to summation table and keep only those that match for summations
sum_dat <- merge(dat_TNTP, sum_ref, all.x = TRUE)
sum_dat <- subset(sum_dat, !is.na(sum_dat$NutrientGroup))
-
+
# # REMINDER FOR TADA TEAM: NEED TO ENSURE ALL COMBOS PRESENT IN TABLE
# # for review only: what is not matching?
# sum_dat_review <- sum_dat %>%
@@ -557,11 +581,13 @@ TADA_CalculateTotalNP <- function(.data,
# If the join results in matching rows
if (dim(sum_dat)[1] > 0) {
- thecols <- grpcols[!grpcols %in% c("TADA.ComparableDataIdentifier",
- "TADA.ResultMeasure.MeasureUnitCode",
- "TADA.CharacteristicName",
- "TADA.MethodSpeciationName",
- "TADA.ResultSampleFractionText" )]
+ thecols <- grpcols[!grpcols %in% c(
+ "TADA.ComparableDataIdentifier",
+ "TADA.ResultMeasure.MeasureUnitCode",
+ "TADA.CharacteristicName",
+ "TADA.MethodSpeciationName",
+ "TADA.ResultSampleFractionText"
+ )]
# create nutrient group ID's.
sum_dat <- sum_dat %>%
@@ -569,9 +595,10 @@ TADA_CalculateTotalNP <- function(.data,
dplyr::mutate(TADA.NutrientSummationGroup = dplyr::cur_group_id())
# bring in equations
- eqns <- utils::read.csv(system.file("extdata",
- "NP_equations.csv",
- package = "EPATADA"))
+ eqns <- utils::read.csv(system.file("extdata",
+ "NP_equations.csv",
+ package = "EPATADA"
+ ))
# dataframe to hold results
summeddata <- data.frame()
@@ -583,10 +610,11 @@ TADA_CalculateTotalNP <- function(.data,
for (j in 1:length(unique(nutqns$EQN))) {
eqnum <- unique(nutqns$EQN)[j]
eqn <- subset(nutqns, nutqns$EQN == eqnum)$SummationName
- nutrient <- ifelse(nut == "N",
- "Total Nitrogen as N",
- "Total Phosphorus as P")
- # for each equation, see if any groups contain all required subspecies,
+ nutrient <- ifelse(nut == "N",
+ "Total Nitrogen as N",
+ "Total Phosphorus as P"
+ )
+ # for each equation, see if any groups contain all required subspecies,
# and for each pick the variant with the lowest rank.
# combine group with other groups and remove group ID from consideration
# for the next equation
@@ -606,7 +634,7 @@ TADA_CalculateTotalNP <- function(.data,
grps <- c(grps, unique(out$TADA.NutrientSummationGroup))
}
}
-
+
# Convert speciation if needed
summeddata$TADA.ResultMeasureValue <- ifelse(!is.na(summeddata$SummationSpeciationConversionFactor), summeddata$TADA.ResultMeasureValue * summeddata$SummationSpeciationConversionFactor, summeddata$TADA.ResultMeasureValue)
summeddata$TADA.MethodSpeciationName <- ifelse(!is.na(summeddata$SummationSpeciationConversionFactor) & summeddata$nutrient == "Total Nitrogen as N", "AS N", summeddata$TADA.MethodSpeciationName)
@@ -618,49 +646,60 @@ TADA_CalculateTotalNP <- function(.data,
dplyr::filter(nutrient == "Total Nitrogen as N") %>%
dplyr::group_by(dplyr::across(dplyr::all_of(totncols))) %>%
dplyr::summarise(TADA.ResultMeasureValue = sum(TADA.ResultMeasureValue)) %>%
- dplyr::mutate(TADA.CharacteristicName = "TOTAL NITROGEN, MIXED FORMS",
- TADA.ResultSampleFractionText = "UNFILTERED",
- TADA.MethodSpeciationName = "AS N",
- TADA.ResultMeasure.MeasureUnitCode = "MG/L",
- TADA.ComparableDataIdentifier = "TOTAL NITROGEN, MIXED FORMS_UNFILTERED_AS N_MG/L",
- TADA.NutrientSummation.Flag = "New row added: Nutrient summation from one or more subspecies.",
- TADA.ResultMeasureValueDataTypes.Flag = "TN estimated from one or more subspecies.",
- TADA.ResultValueAggregation.Flag = "Nutrient summation from selected aggregate values and values where no aggregation was needed.")
+ dplyr::mutate(
+ TADA.CharacteristicName = "TOTAL NITROGEN, MIXED FORMS",
+ TADA.ResultSampleFractionText = "UNFILTERED",
+ TADA.MethodSpeciationName = "AS N",
+ TADA.ResultMeasure.MeasureUnitCode = "MG/L",
+ TADA.ComparableDataIdentifier = "TOTAL NITROGEN, MIXED FORMS_UNFILTERED_AS N_MG/L",
+ TADA.NutrientSummation.Flag = "New row added: Nutrient summation from one or more subspecies.",
+ TADA.ResultMeasureValueDataTypes.Flag = "TN estimated from one or more subspecies.",
+ TADA.ResultValueAggregation.Flag = "Nutrient summation from selected aggregate values and values where no aggregation was needed."
+ )
TotalP <- summeddata %>%
dplyr::filter(nutrient == "Total Phosphorus as P") %>%
dplyr::group_by(dplyr::across(dplyr::all_of(totncols))) %>%
dplyr::summarise(TADA.ResultMeasureValue = sum(TADA.ResultMeasureValue)) %>%
- dplyr::mutate(TADA.CharacteristicName = "TOTAL PHOSPHORUS, MIXED FORMS",
- TADA.ResultSampleFractionText = "UNFILTERED",
- TADA.MethodSpeciationName = "AS P",
- TADA.ResultMeasure.MeasureUnitCode = "UG/L",
- TADA.ComparableDataIdentifier = "TOTAL PHOSPHORUS, MIXED FORMS_UNFILTERED_AS P_UG/L",
- TADA.NutrientSummation.Flag = "New row added: Nutrient summation from one subspecies.",
- TADA.ResultMeasureValueDataTypes.Flag = "TP estimated from one or more subspecies.",
- TADA.ResultValueAggregation.Flag = "Nutrient summation from selected aggregate values and values where no aggregation was needed.")
+ dplyr::mutate(
+ TADA.CharacteristicName = "TOTAL PHOSPHORUS, MIXED FORMS",
+ TADA.ResultSampleFractionText = "UNFILTERED",
+ TADA.MethodSpeciationName = "AS P",
+ TADA.ResultMeasure.MeasureUnitCode = "UG/L",
+ TADA.ComparableDataIdentifier = "TOTAL PHOSPHORUS, MIXED FORMS_UNFILTERED_AS P_UG/L",
+ TADA.NutrientSummation.Flag = "New row added: Nutrient summation from one subspecies.",
+ TADA.ResultMeasureValueDataTypes.Flag = "TP estimated from one or more subspecies.",
+ TADA.ResultValueAggregation.Flag = "Nutrient summation from selected aggregate values and values where no aggregation was needed."
+ )
# If summation is zero....include anyway
# Generate unique ResultIdentifier
Totals <- plyr::rbind.fill(TotalN, TotalP) %>%
- dplyr::mutate(ResultIdentifier = paste0("TADA-",
- sample(seq_len(1000000000),
- dplyr::n())))
-
+ dplyr::mutate(ResultIdentifier = paste0(
+ "TADA-",
+ sample(
+ seq_len(1000000000),
+ dplyr::n()
+ )
+ ))
+
# Combine all data back into dat_TNTP and get rid of unneeded columns
dat_TNTP_combined <- dat_TNTP %>%
base::merge(summeddata, all.x = TRUE) %>%
plyr::rbind.fill(Totals) %>%
- dplyr::select(-SummationFractionNotes,
- -SummationSpeciationNotes,
- -SummationSpeciationConversionFactor,
- -SummationName,
- -SummationRank,
- -SummationNote,
- -nutrient,
- -NutrientGroup) %>%
- dplyr::mutate(TADA.NutrientSummation.Flag = dplyr::if_else(is.na(TADA.NutrientSummation.Flag),
- "Not used to calculate Total N or P.",
- TADA.NutrientSummation.Flag))
+ dplyr::select(
+ -SummationFractionNotes,
+ -SummationSpeciationNotes,
+ -SummationSpeciationConversionFactor,
+ -SummationName,
+ -SummationRank,
+ -SummationNote,
+ -nutrient,
+ -NutrientGroup
+ ) %>%
+ dplyr::mutate(TADA.NutrientSummation.Flag = dplyr::if_else(is.na(TADA.NutrientSummation.Flag),
+ "Not used to calculate Total N or P.",
+ TADA.NutrientSummation.Flag
+ ))
# At end... summation complete at this point
# Check if each data frame is not empty
dat_TNTP_combined_non_empty <- if (nrow(dat_TNTP_combined) > 0) dat_TNTP_combined else NULL
@@ -672,40 +711,39 @@ TADA_CalculateTotalNP <- function(.data,
exclude_df_non_empty,
dat_addback_non_empty
)
-
- # Filter rows based on specific conditions
- duplicates <- final_TNTP %>%
- dplyr::group_by(TADA.NutrientSummationGroup) %>%
- dplyr::filter(
- dplyr::n() == 2 &
- TADA.ResultMeasureValue[1] == TADA.ResultMeasureValue[2]
- ) %>%
- dplyr::filter(TADA.NutrientSummation.Flag == "New row added: Nutrient summation from one or more subspecies.")
-
- remove_list = unique(duplicates$ResultIdentifier)
-
- # Filter the data frame
- complete_df <- final_TNTP %>%
- dplyr::filter(!ResultIdentifier %in% remove_list)
-
+
+ # Filter rows based on specific conditions
+ duplicates <- final_TNTP %>%
+ dplyr::group_by(TADA.NutrientSummationGroup) %>%
+ dplyr::filter(
+ dplyr::n() == 2 &
+ TADA.ResultMeasureValue[1] == TADA.ResultMeasureValue[2]
+ ) %>%
+ dplyr::filter(TADA.NutrientSummation.Flag == "New row added: Nutrient summation from one or more subspecies.")
+
+ remove_list <- unique(duplicates$ResultIdentifier)
+
+ # Filter the data frame
+ complete_df <- final_TNTP %>%
+ dplyr::filter(!ResultIdentifier %in% remove_list)
} else {
# Check if each data frame is not empty
dat_TNTP_non_empty <- if (nrow(dat_TNTP) > 0) dat_TNTP else NULL
exclude_df_non_empty <- if (nrow(exclude_df) > 0) exclude_df else NULL
dat_addback_non_empty <- if (nrow(dat_addback) > 0) dat_addback else NULL
-
+
# Bind rows only if the data frames are not NULL
complete_df <- dplyr::bind_rows(
dat_TNTP_non_empty,
exclude_df_non_empty,
dat_addback_non_empty
)
-
+
# if there are no data to sum
complete_df$TADA.NutrientSummation.Flag <- "Not used to calculate Total N or P."
message("No Total N or P subspecies exist in dataset. Returning input dataset with TADA.NutrientSummation.Flag set to 'Not used to calculate Total N or P'")
}
-
+
# order columns and return complete_df
complete_df <- TADA_CreateComparableID(complete_df)
complete_df <- TADA_OrderCols(complete_df)
@@ -720,16 +758,16 @@ TADA_CalculateTotalNP <- function(.data,
#' TADA.ResultMeasureValue to a minimum, maximum, or mean value.
#'
#' @param .data A TADA dataframe
-#'
+#'
#' @param grouping_cols The column names used to group the data
-#'
+#'
#' @param agg_fun The aggregation function used on the grouped data. This can
#' either be 'min', 'max', or 'mean'.
-#'
+#'
#' @param clean Boolean. Determines whether other measurements from the group
#' aggregation should be removed or kept in the dataframe. If clean = FALSE,
#' additional measurements that were considered are indicated in the
-#' TADA.ResultValueAggregation.Flag. The default is clean = FALSE.
+#' TADA.ResultValueAggregation.Flag. The default is clean = FALSE.
#'
#' @return A TADA dataframe with aggregated values combined into one row. If the
#' agg_fun is 'min' or 'max', the function will select the row matching the
@@ -745,23 +783,23 @@ TADA_CalculateTotalNP <- function(.data,
#' @examples
#' # Load example dataset
#' data(Data_6Tribes_5y)
-#' # Select maximum value per day, site, comparable data identifier,
+#' # Select maximum value per day, site, comparable data identifier,
#' # unit, result detection condition,
#' # and activity type code. Clean all non-maximum measurements from grouped data.
#' Data_6Tribes_5y_max <- TADA_AggregateMeasurements(Data_6Tribes_5y,
#' grouping_cols = c(
-#' "ActivityStartDate",
+#' "ActivityStartDate",
#' "TADA.MonitoringLocationIdentifier",
-#' "TADA.ComparableDataIdentifier",
+#' "TADA.ComparableDataIdentifier",
#' "ResultDetectionConditionText",
#' "ActivityTypeCode",
#' "TADA.ResultMeasure.MeasureUnitCode"
#' ),
-#' agg_fun = "max",
+#' agg_fun = "max",
#' clean = TRUE
#' )
#'
-#' # Calculate a mean value per day, site, comparable data identifier, unit,
+#' # Calculate a mean value per day, site, comparable data identifier, unit,
#' # result detection condition,
#' # and activity type code. Keep all measurements used to calculate mean measurement.
#' Data_6Tribes_5y_mean <- TADA_AggregateMeasurements(Data_6Tribes_5y,
@@ -770,51 +808,53 @@ TADA_CalculateTotalNP <- function(.data,
#' "TADA.ComparableDataIdentifier", "ResultDetectionConditionText",
#' "ActivityTypeCode", "TADA.ResultMeasure.MeasureUnitCode"
#' ),
-#' agg_fun = "mean",
+#' agg_fun = "mean",
#' clean = FALSE
#' )
-#'
-TADA_AggregateMeasurements <- function(.data,
- grouping_cols = c("ActivityStartDate",
- "TADA.MonitoringLocationIdentifier",
- "TADA.ComparableDataIdentifier",
- "ResultDetectionConditionText",
- "ActivityTypeCode",
- "TADA.ResultMeasure.MeasureUnitCode"),
- agg_fun = c("max", "min", "mean"),
+#'
+TADA_AggregateMeasurements <- function(.data,
+ grouping_cols = c(
+ "ActivityStartDate",
+ "TADA.MonitoringLocationIdentifier",
+ "TADA.ComparableDataIdentifier",
+ "ResultDetectionConditionText",
+ "ActivityTypeCode",
+ "TADA.ResultMeasure.MeasureUnitCode"
+ ),
+ agg_fun = c("max", "min", "mean"),
clean = FALSE) {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
+ return(NULL) # Exit the function early
}
-
+
TADA_CheckColumns(.data, grouping_cols)
agg_fun <- match.arg(agg_fun)
-
+
# Find multiple values in groups
ncount <- .data %>%
dplyr::group_by(dplyr::across(dplyr::all_of(grouping_cols))) %>%
dplyr::summarise(ncount = length(ResultIdentifier))
-
+
if (max(ncount$ncount) < 2) {
message("TADA_AggregateMeasurements: No rows to aggregate.")
return(.data)
} else {
dat <- merge(.data, ncount, all.x = TRUE)
-
+
if (any(is.na(dat$TADA.ResultMeasureValue))) {
"TADA_AggregateMeasurements: Your dataset contains one or more rows where TADA.ResultMeasureValue = NA. Recommend removing these rows before proceeding. Otherwise, the function will not consider NAs in its calculations."
}
-
+
dat$TADA.ResultValueAggregation.Flag <- ifelse(dat$ncount == 1, "No aggregation needed", paste0("Considered in ", agg_fun, " aggregation function but not selected"))
multiples <- dat %>% dplyr::filter(ncount > 1)
-
+
dat <- dat %>% dplyr::select(-ncount)
-
+
if (agg_fun == "max") {
out <- multiples %>%
dplyr::group_by(dplyr::across(dplyr::all_of(grouping_cols))) %>%
@@ -839,11 +879,11 @@ TADA_AggregateMeasurements <- function(.data,
dplyr::mutate(ResultIdentifier = paste0("TADA-", ResultIdentifier))
dat <- plyr::rbind.fill(dat, out)
}
-
+
if (clean == TRUE) {
dat <- subset(dat, !dat$TADA.ResultValueAggregation.Flag %in% c(paste0("Considered in ", agg_fun, " aggregation function but not selected")))
}
-
+
dat <- TADA_CreateComparableID(dat)
dat <- TADA_OrderCols(dat)
message("Aggregation results:")
diff --git a/R/UnitConversions.R b/R/UnitConversions.R
index 2fc9bc83f..e0efee9f0 100644
--- a/R/UnitConversions.R
+++ b/R/UnitConversions.R
@@ -104,9 +104,10 @@ TADA_CreateUnitRef <- function(.data, print.message = TRUE) {
# import TADA specific conversion reference, created by HRM on 4/30/2024
file_path <- system.file("extdata",
- "TADAPriorityCharConvertRef.csv",
- package = "EPATADA")
-
+ "TADAPriorityCharConvertRef.csv",
+ package = "EPATADA"
+ )
+
if (file.exists(file_path)) {
# Specify all columns as character using readr
tada.unit.ref <- readr::read_csv(
@@ -120,13 +121,13 @@ TADA_CreateUnitRef <- function(.data, print.message = TRUE) {
),
show_col_types = FALSE # Suppress the column specification message
)
-
+
# # Print column names to verify
# print(colnames(tada.unit.ref))
} else {
stop("File not found: TADAPriorityCharConvertRef.csv")
}
-
+
# make all codes and target units uppercase
tada.unit.ref <- tada.unit.ref %>%
dplyr::mutate(
@@ -443,7 +444,7 @@ TADA_ConvertResultUnits <- function(.data, ref = "tada", transform = TRUE) {
usgs.results <- .data %>%
dplyr::filter(ResultMeasure.MeasureUnitCode %in% usgs.spec$ResultMeasure.MeasureUnitCode)
- if(dim(usgs.results)[1] == 0) {
+ if (dim(usgs.results)[1] == 0) {
# remove intermediate objects
rm(usgs.ref, usgs.spec, usgs.unit)
}
@@ -455,7 +456,6 @@ TADA_ConvertResultUnits <- function(.data, ref = "tada", transform = TRUE) {
# internal functions
# internal function to join unit.ref to data
joinUnitRef <- function(.data, ref, convert.col = conversion.cols, spec = FALSE) {
-
# ref join
ref.join <- c(
"TADA.CharacteristicName",
@@ -493,28 +493,27 @@ TADA_ConvertResultUnits <- function(.data, ref = "tada", transform = TRUE) {
}
# internal function to create usgs unit ref from main unit ref if needed
- if(dim(usgs.results)[1] > 0){
-
- createUSGSUnitRef <- function(.data, ref, spec) {
- meth.spec.usgs <- .data %>%
- dplyr::select(
- ResultMeasure.MeasureUnitCode,
- TADA.MethodSpeciationName
- ) %>%
- dplyr::distinct()
+ if (dim(usgs.results)[1] > 0) {
+ createUSGSUnitRef <- function(.data, ref, spec) {
+ meth.spec.usgs <- .data %>%
+ dplyr::select(
+ ResultMeasure.MeasureUnitCode,
+ TADA.MethodSpeciationName
+ ) %>%
+ dplyr::distinct()
- unit.ref.usgs <- ref %>%
- dplyr::filter(ResultMeasure.MeasureUnitCode %in%
- usgs.spec$ResultMeasure.MeasureUnitCode) %>%
- dplyr::left_join(spec, by = dplyr::join_by(ResultMeasure.MeasureUnitCode)) %>%
- dplyr::left_join(meth.spec.usgs, by = dplyr::join_by(ResultMeasure.MeasureUnitCode)) %>%
- dplyr::distinct()
+ unit.ref.usgs <- ref %>%
+ dplyr::filter(ResultMeasure.MeasureUnitCode %in%
+ usgs.spec$ResultMeasure.MeasureUnitCode) %>%
+ dplyr::left_join(spec, by = dplyr::join_by(ResultMeasure.MeasureUnitCode)) %>%
+ dplyr::left_join(meth.spec.usgs, by = dplyr::join_by(ResultMeasure.MeasureUnitCode)) %>%
+ dplyr::distinct()
- rm(meth.spec.usgs)
+ rm(meth.spec.usgs)
- return(unit.ref.usgs)
+ return(unit.ref.usgs)
+ }
}
-}
# if user supplied unit reference was provided
if (is.data.frame(ref)) {
@@ -650,8 +649,7 @@ TADA_ConvertResultUnits <- function(.data, ref = "tada", transform = TRUE) {
# internal function to set other.results or usgs.results as null if not included in df
setNull <- function(df.name) {
-
- if(dim(df.name)[1] == 0) {
+ if (dim(df.name)[1] == 0) {
df.name <- NULL
}
@@ -739,13 +737,13 @@ TADA_ConvertResultUnits <- function(.data, ref = "tada", transform = TRUE) {
if (!is.null(usgs.data)) {
print(paste0("NOTE: Dataset contains ", dim(usgs.data)[1], " USGS results with speciation information in both the result unit and method speciation columns. This function overwrites the TADA method speciation column with the speciation provided in the result unit column."))
- # add target method speciation name when needed
- usgs.data <- usgs.data %>%
- dplyr::mutate(
- TADA.MethodSpeciationName = ifelse(!is.na(TADA.Target.MethodSpeciationName), TADA.Target.MethodSpeciationName, toupper(TADA.MethodSpeciationName)),
- # replace UNKNOWN or NONE method speciation name with NA
- TADA.MethodSpeciationName = ifelse(TADA.MethodSpeciationName %in% c("UNKNOWN", "NONE"), NA, TADA.MethodSpeciationName)
- )
+ # add target method speciation name when needed
+ usgs.data <- usgs.data %>%
+ dplyr::mutate(
+ TADA.MethodSpeciationName = ifelse(!is.na(TADA.Target.MethodSpeciationName), TADA.Target.MethodSpeciationName, toupper(TADA.MethodSpeciationName)),
+ # replace UNKNOWN or NONE method speciation name with NA
+ TADA.MethodSpeciationName = ifelse(TADA.MethodSpeciationName %in% c("UNKNOWN", "NONE"), NA, TADA.MethodSpeciationName)
+ )
}
clean.data <- joinUSGSOther(usgs.data = usgs.data, other.data = other.data)
@@ -806,8 +804,8 @@ TADA_ConvertResultUnits <- function(.data, ref = "tada", transform = TRUE) {
# Remove unneccessary conversion columns
dplyr::select(-tidyselect::any_of(conversion.cols)) %>%
# update ID and column ordering
- TADA_CreateComparableID() %>%
- TADA_OrderCols()
+ TADA_CreateComparableID() %>%
+ TADA_OrderCols()
rm(clean.data, det.data, det.ref)
}
@@ -983,9 +981,10 @@ TADA_ConvertDepthUnits <- function(.data,
# import TADA specific conversion reference, created by HRM on 4/30/2024
file_path <- system.file("extdata",
- "TADAPriorityCharConvertRef.csv",
- package = "EPATADA")
-
+ "TADAPriorityCharConvertRef.csv",
+ package = "EPATADA"
+ )
+
if (file.exists(file_path)) {
# Specify all columns as character using readr
length.ref <- readr::read_csv(
@@ -999,13 +998,13 @@ TADA_ConvertDepthUnits <- function(.data,
),
show_col_types = FALSE # Suppress the column specification message
)
-
+
# # Print column names to verify
# print(colnames(tada.unit.ref))
} else {
stop("File not found: TADAPriorityCharConvertRef.csv")
}
-
+
# subset to include only "Length Distance" units; filter by target unit defined in 'unit' argument
length.ref <- length.ref %>%
dplyr::filter(Code %in% c(
@@ -1074,23 +1073,23 @@ TADA_ConvertDepthUnits <- function(.data,
# function to run through each depth column
conv_unit <- function(.data, coln) {
if (coln %in% colnames(.data)) {
- .data$cf <- as.numeric(.data[, coln]) # Convert to numeric
+ .data$cf <- as.numeric(.data[, coln]) # Convert to numeric
colnv <- paste0(gsub("TADA.WQXConversionFactor", "TADA", coln), ".MeasureValue")
- .data$val <- as.numeric(.data[, colnv]) # Convert to numeric
+ .data$val <- as.numeric(.data[, colnv]) # Convert to numeric
colnu <- paste0(gsub("TADA.WQXConversionFactor", "TADA", coln), ".MeasureUnitCode")
.data$unit <- .data[, colnu]
-
+
# Apply conversion factor, handling NA values
.data$val <- ifelse(!is.na(.data$val), .data$val * .data$cf, .data$val)
-
+
# Update units
.data$unit[which(!is.na(.data$unit))] <- unit
-
+
# Remove unnecessary columns and rename
.data <- dplyr::select(.data, -cf, -dplyr::all_of(coln), -dplyr::all_of(colnv), -dplyr::all_of(colnu))
names(.data)[names(.data) == "val"] <- colnv
names(.data)[names(.data) == "unit"] <- colnu
-
+
return(.data)
} else {
return(.data)
diff --git a/R/Utilities.R b/R/Utilities.R
index 1dc76c8ad..652b7735f 100644
--- a/R/Utilities.R
+++ b/R/Utilities.R
@@ -18,9 +18,9 @@
#' # Example: Using the pipe operator to transform data
#' library(magrittr)
#' result <- iris %>%
-#' head(10) %>%
-#' subset(Species == "setosa") %>%
-#' summary()
+#' head(10) %>%
+#' subset(Species == "setosa") %>%
+#' summary()
#' print(result)
NULL
@@ -143,19 +143,19 @@ utils::globalVariables(c(
"parm_cd", "site_no", "stat_cd", "stat_type", "grouped.sites", "n",
"nearby", "rainbow", "monitoringLocationId", "monitoringLocationOrgId",
"monitoringLocationDataLink", "ATTAINS.OrganizationName", "ATTAINS.WaterType",
- "ATTAINS.MonitoringDataLinkText", "ATTAINS.MonitoringDataLinkText.New",
- "ATTAINS.MonitoringLocationIdentifier", "AssessmentUnitIdentifier",
- "DetectionQuantitationLimitMeasure.MeasureUnitCode", "MS_DATA_LINK",
+ "ATTAINS.MonitoringDataLinkText", "ATTAINS.MonitoringDataLinkText.New",
+ "ATTAINS.MonitoringLocationIdentifier", "AssessmentUnitIdentifier",
+ "DetectionQuantitationLimitMeasure.MeasureUnitCode", "MS_DATA_LINK",
"OLD_ATTAINS.MonitoringLocationIdentifier", "Shape_Area", "Shape_Length",
- "TADA.AURefSource", "TADA.NutrientSummation.Flag", "assessmentunitname",
- "assmnt_joinkey", "catchmentistribal", "catchmentresolution",
+ "TADA.AURefSource", "TADA.NutrientSummation.Flag", "assessmentunitname",
+ "assmnt_joinkey", "catchmentistribal", "catchmentresolution",
"catchmentstatecode", "has4bplan", "hasalternativeplan", "hasprotectionplan",
- "hastmdl", "huc12", "ircategory", "isassessed", "isimpaired", "isthreatened",
+ "hastmdl", "huc12", "ircategory", "isassessed", "isimpaired", "isthreatened",
"objectId", "on303dlist", "organizationid", "organizationname", "orgtype",
- "overallstatus", "permid_joinkey", "region", "reportingCycle",
- "reportingcycle", "response.code", "return_sf", "state", "submissionid",
- "tas303d", "visionpriority303d", "waterbodyreportlink", "xwalk_huc12_version",
- "xwalk_method"
+ "overallstatus", "permid_joinkey", "region", "reportingCycle",
+ "reportingcycle", "response.code", "return_sf", "state", "submissionid",
+ "tas303d", "visionpriority303d", "waterbodyreportlink", "xwalk_huc12_version",
+ "xwalk_method", "WqxV2.FieldName"
))
# global variables for tribal feature layers used in TADA_OverviewMap in Utilities.R
@@ -168,17 +168,17 @@ VATribeUrl <- "https://geopub.epa.gov/arcgis/rest/services/EMEF/Tribal/MapServer
#' Calculate Decimal Places
#'
-#' This function calculates the number of decimal places in a numeric value.
+#' This function calculates the number of decimal places in a numeric value.
#' It returns the number of digits to the right of the decimal point for numeric data.
#'
#' @param x A numeric value or vector from the TADA profile.
-#'
+#'
#' @return An integer representing the number of decimal places in the numeric value.
#' If the input is an integer or a numeric value with no decimal places, the function returns 0.
TADA_DecimalPlaces <- function(x) {
# Convert the number to a character string, remove trailing zeros, and split by the decimal point
parts <- strsplit(sub("0+$", "", as.character(x)), ".", fixed = TRUE)[[1]]
-
+
# If there is a decimal part, return its length; otherwise, return 0
if (length(parts) > 1) {
return(nchar(parts[[2]]))
@@ -222,13 +222,13 @@ TADA_CheckColumns <- function(.data, expected_cols) {
if (!inherits(.data, "data.frame")) {
stop("Input must be a dataframe.")
}
-
+
if (!is.vector(expected_cols) || !is.character(expected_cols)) {
stop("Expected columns must be a character vector.")
}
-
+
missing_cols <- setdiff(expected_cols, colnames(.data))
-
+
if (length(missing_cols) > 0) {
stop(paste(
"The dataframe does not contain the required field(s):",
@@ -236,7 +236,7 @@ TADA_CheckColumns <- function(.data, expected_cols) {
". Use either the full physical/chemical profile downloaded from WQP or download the TADA profile template available on the EPA TADA webpage."
))
}
-
+
invisible(NULL)
}
@@ -296,16 +296,15 @@ TADA_CheckColumns <- function(.data, expected_cols) {
#' TADA.DetectionQuantitationLimitMeasure.MeasureValueDataTypes.Flag)
TADA_ConvertSpecialChars <- function(.data, col, percent.ave = TRUE,
clean = FALSE, flaggedonly = FALSE) {
-
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
if (!col %in% names(.data)) {
stop("Suspect column name specified for input dataset.")
}
@@ -316,36 +315,35 @@ TADA_ConvertSpecialChars <- function(.data, col, percent.ave = TRUE,
}
if (!any(grepl("TADA.", col))) {
-
# Define new column names
numcol <- paste0("TADA.", col)
flagcol <- paste0("TADA.", col, "DataTypes.Flag")
-
+
# Create dummy columns for easy handling in function
chars.data <- .data
names(chars.data)[names(chars.data) == col] <- "orig"
chars.data <- chars.data %>%
dplyr::select(-tidyselect::any_of(c(col, numcol, flagcol)))
chars.data$masked <- chars.data$orig
-
+
# Add percentage character to dissolved oxygen saturation ResultMeasureValue
# so percentage and percentage - range averaged can be identified correctly
if (col == "ResultMeasureValue") {
do.units <- c("%", "% SATURATN")
-
+
chars.data$masked <- ifelse(chars.data$CharacteristicName == "Dissolved oxygen (DO)" & chars.data$ResultMeasure.MeasureUnitCode %in% do.units,
- paste(chars.data$masked, "%"), chars.data$masked
+ paste(chars.data$masked, "%"), chars.data$masked
)
-
+
# updates percentage units where NA
chars.data$TADA.ResultMeasure.MeasureUnitCode <- ifelse(
grepl("%", chars.data$masked), "%", chars.data$ResultMeasure.MeasureUnitCode
)
-
+
# TADA.ResultMeasure.MeasureUnitCode to uppercase
chars.data$TADA.ResultMeasure.MeasureUnitCode <- toupper(chars.data$TADA.ResultMeasure.MeasureUnitCode)
}
-
+
# If column is already numeric, just discern between NA and numeric
if (is.numeric(chars.data$orig)) {
clean.data <- chars.data %>%
@@ -377,22 +375,22 @@ TADA_ConvertSpecialChars <- function(.data, col, percent.ave = TRUE,
TRUE ~ "Coerced to NA"
),
flag = ifelse(flag == "Greater Than" & grepl("%", masked) & grepl("-", masked),
- "Percentage Range - Averaged", flag
+ "Percentage Range - Averaged", flag
),
flag = ifelse(flag == "Less Than" & grepl("%", masked) & grepl("-", masked),
- "Percentage Range - Averaged", flag
+ "Percentage Range - Averaged", flag
)
)
}
-
+
if (percent.ave == FALSE) {
num.range.filter <- c("Numeric Range - Averaged")
}
-
+
if (percent.ave == TRUE) {
num.range.filter <- c("Numeric Range - Averaged", "Percentage Range - Averaged")
}
-
+
# Result Values that are numeric ranges with the format #-# are converted to an average of the two numbers expressed in the range.
if (any(clean.data$flag %in% num.range.filter)) {
numrange <- subset(clean.data, clean.data$flag %in% num.range.filter)
@@ -409,73 +407,76 @@ TADA_ConvertSpecialChars <- function(.data, col, percent.ave = TRUE,
numrange$masked <- as.character(rowMeans(numrange[, c("num1", "num2")], na.rm = TRUE))
numrange <- numrange[, !names(numrange) %in% c("num1", "num2")] %>%
dplyr::mutate(masked = ifelse(flag == "Percentage Range - Average", paste(masked, "%", sep = ""), masked))
-
+
clean.data <- plyr::rbind.fill(notnumrange, numrange)
}
-
+
# In the new TADA column, convert to numeric and remove some specific special
# characters.
clean.data$masked <- suppressWarnings(as.numeric(stringr::str_replace_all(
- clean.data$masked, c("<" = "",
- ">" = "",
- "~" = "",
- "%" = "",
- "\\*" = "",
- "1\\)" = "",
- "\\+" = "")
+ clean.data$masked, c(
+ "<" = "",
+ ">" = "",
+ "~" = "",
+ "%" = "",
+ "\\*" = "",
+ "1\\)" = "",
+ "\\+" = ""
+ )
)))
-
+
# this updates the DataTypes.Flag to "NA - Not Available" if flag is NA
clean.data$flag <- ifelse(
is.na(clean.data$flag),
"NA - Not Available",
clean.data$flag
)
-
+
# remove columns to be replaced
clean.data <- clean.data %>%
dplyr::select(!(tidyselect::any_of(numcol)), !(tidyselect::any_of(flagcol)))
-
+
# Rename to original column name, TADA column name, and flag column name
names(clean.data)[names(clean.data) == "orig"] <- col
names(clean.data)[names(clean.data) == "masked"] <- numcol
names(clean.data)[names(clean.data) == "flag"] <- flagcol
-
+
clean.data <- TADA_OrderCols(clean.data)
} else {
flagcol <- paste0(col, "DataTypes.Flag")
numcol <- col
-
- clean.data = .data
-
+
+ clean.data <- .data
+
# this updates the flagcol to "NA - Not Available" if numcol is NA
clean.data[[flagcol]] <- ifelse(
is.na(clean.data[[numcol]]),
"NA - Not Available",
clean.data[[flagcol]]
)
-
+
# remove columns to be replaced
clean.data <- clean.data %>%
dplyr::select(!(tidyselect::any_of(numcol)), !(tidyselect::any_of(flagcol)))
-
+
# Rename to original column name, TADA column name, and flag column name
names(clean.data)[names(clean.data) == "orig"] <- col
names(clean.data)[names(clean.data) == "masked"] <- numcol
names(clean.data)[names(clean.data) == "flag"] <- flagcol
-
+
clean.data <- TADA_OrderCols(clean.data)
-
}
if (flaggedonly == FALSE) {
if (clean == TRUE) {
clean.data <- clean.data %>%
- dplyr::filter(!(!!rlang::sym(flagcol)) %in% c("NA - Not Available",
- "Text",
- "Non-ASCII Character(s)",
- "Result Value/Unit Cannot Be Estimated From Detection Limit",
- "Coerced to NA"))
+ dplyr::filter(!(!!rlang::sym(flagcol)) %in% c(
+ "NA - Not Available",
+ "Text",
+ "Non-ASCII Character(s)",
+ "Result Value/Unit Cannot Be Estimated From Detection Limit",
+ "Coerced to NA"
+ ))
return(clean.data)
}
@@ -487,11 +488,13 @@ TADA_ConvertSpecialChars <- function(.data, col, percent.ave = TRUE,
if (flaggedonly == TRUE) {
clean.data <- clean.data %>%
- dplyr::filter(!!rlang::sym(flagcol) %in% c("NA - Not Available",
- "Text",
- "Non-ASCII Character(s)",
- "Result Value/Unit Cannot Be Estimated From Detection Limit",
- "Coerced to NA"))
+ dplyr::filter(!!rlang::sym(flagcol) %in% c(
+ "NA - Not Available",
+ "Text",
+ "Non-ASCII Character(s)",
+ "Result Value/Unit Cannot Be Estimated From Detection Limit",
+ "Coerced to NA"
+ ))
}
}
@@ -550,13 +553,13 @@ TADA_ConvertSpecialChars <- function(.data, col, percent.ave = TRUE,
TADA_SubstituteDeprecatedChars <- function(.data) {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
TADA_CheckColumns(.data, expected_cols = c("CharacteristicName"))
if ("TADA.CharacteristicName" %in% colnames(.data)) {
@@ -617,13 +620,13 @@ TADA_SubstituteDeprecatedChars <- function(.data) {
TADA_CreateComparableID <- function(.data) {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
TADA_CheckColumns(.data,
expected_cols = c(
"TADA.CharacteristicName",
@@ -691,37 +694,47 @@ TADA_FormatDelimitedString <- function(delimited_string, delimiter = ",") {
#'
#' @examples
#' \dontrun{
-#' # Example 1: Retrieve a random dataset for a single day
+#' # Example 1: Retrieve a random dataset for a single day
#' # across the entire nation
-#' random_data_national <- TADA_RandomTestingData(number_of_days = 1,
-#' choose_random_state = FALSE)
+#' random_data_national <- TADA_RandomTestingData(
+#' number_of_days = 1,
+#' choose_random_state = FALSE
+#' )
#' print(random_data_national)
#'
-#' # Example 2: Retrieve a random dataset for a 10-day period within
+#' # Example 2: Retrieve a random dataset for a 10-day period within
#' # a randomly selected state
-#' random_data_state <- TADA_RandomTestingData(number_of_days = 10,
-#' choose_random_state = TRUE)
+#' random_data_state <- TADA_RandomTestingData(
+#' number_of_days = 10,
+#' choose_random_state = TRUE
+#' )
#' print(random_data_state)
#'
-#' # Example 3: Retrieve a random dataset for a 5-day period
+#' # Example 3: Retrieve a random dataset for a 5-day period
#' # within a randomly selected state without auto-cleaning
-#' random_data_state_no_clean <- TADA_RandomTestingData(number_of_days = 5,
-#' choose_random_state = TRUE, autoclean = FALSE)
+#' random_data_state_no_clean <- TADA_RandomTestingData(
+#' number_of_days = 5,
+#' choose_random_state = TRUE, autoclean = FALSE
+#' )
#' print(random_data_state_no_clean)
#'
-#' # Example 4: Retrieve a random dataset for a 30-day period
+#' # Example 4: Retrieve a random dataset for a 30-day period
#' # across the entire nation with auto-cleaning
-#' random_data_large_period <- TADA_RandomTestingData(number_of_days = 30,
-#' choose_random_state = FALSE, autoclean = TRUE)
+#' random_data_large_period <- TADA_RandomTestingData(
+#' number_of_days = 30,
+#' choose_random_state = FALSE, autoclean = TRUE
+#' )
#' print(random_data_large_period)
#'
-#' # Example 5: Retrieve a random dataset for a 15-day period
+#' # Example 5: Retrieve a random dataset for a 15-day period
#' # across the entire nation without auto-cleaning
-#' random_data_no_clean <- TADA_RandomTestingData(number_of_days = 15,
-#' choose_random_state = FALSE, autoclean = FALSE)
+#' random_data_no_clean <- TADA_RandomTestingData(
+#' number_of_days = 15,
+#' choose_random_state = FALSE, autoclean = FALSE
+#' )
#' print(random_data_no_clean)
#' }
-TADA_RandomTestingData <- function(number_of_days = 1,
+TADA_RandomTestingData <- function(number_of_days = 1,
choose_random_state = FALSE,
autoclean = TRUE) {
# Internal function to retrieve random data
@@ -730,7 +743,7 @@ TADA_RandomTestingData <- function(number_of_days = 1,
twenty_years_ago <- Sys.Date() - 20 * 365
random_start_date <- twenty_years_ago + sample(20 * 365, 1)
end_date <- random_start_date + ndays
-
+
# Determine if a random state should be selected
if (state_choice) {
load(system.file("extdata", "statecodes_df.Rdata", package = "EPATADA"))
@@ -738,14 +751,14 @@ TADA_RandomTestingData <- function(number_of_days = 1,
} else {
state <- "null"
}
-
+
# Print the selected date range and state code
print(list(
startDate = as.character(random_start_date),
endDate = as.character(end_date),
statecode = state
))
-
+
# Retrieve data with or without auto-cleaning
dat <- TADA_DataRetrieval(
startDate = as.character(random_start_date),
@@ -754,10 +767,10 @@ TADA_RandomTestingData <- function(number_of_days = 1,
applyautoclean = ac,
ask = FALSE
)
-
+
return(dat)
}
-
+
# Internal function to ensure dataset has at least 10 results
verify_random_data <- function() {
repeat {
@@ -766,7 +779,7 @@ TADA_RandomTestingData <- function(number_of_days = 1,
}
return(df)
}
-
+
# Retrieve and return the verified dataset
df <- verify_random_data()
return(df)
@@ -827,13 +840,13 @@ TADA_RandomTestingData <- function(number_of_days = 1,
TADA_AggregateMeasurements <- function(.data, grouping_cols = c("ActivityStartDate", "TADA.MonitoringLocationIdentifier", "TADA.ComparableDataIdentifier", "ResultDetectionConditionText", "ActivityTypeCode"), agg_fun = c("max", "min", "mean"), clean = TRUE) {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
TADA_CheckColumns(.data, grouping_cols)
agg_fun <- match.arg(agg_fun)
@@ -1235,13 +1248,13 @@ TADA_addPoints <- function(map, layerfilepath, layergroup, layername, bbox = NUL
TADA_UniqueCharUnitSpeciation <- function(.data) {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
required_cols <- c(
"TADA.CharacteristicName", "TADA.ResultSampleFractionText",
"TADA.MethodSpeciationName", "TADA.ResultMeasure.MeasureUnitCode",
@@ -1510,9 +1523,9 @@ TADA_CreateCSV <- function(.data) {
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
df_name <- deparse(substitute(.data))
downloads_path <- file.path(Sys.getenv("USERPROFILE"), "Downloads", paste0(df_name, ".csv"))
@@ -1521,3 +1534,96 @@ TADA_CreateCSV <- function(.data) {
cat("File saved to:", gsub("/", "\\\\", downloads_path), "\n")
}
+
+
+#' TADA_RenametoLegacy
+#'
+#' This function renames columns in a dataframe from WQX3.0 (beta) names to WQX2.0 (legacy) names.
+#' Water Quality Portal data are retrieved using USGS dataRetrieval service = "ResultWQX3".
+#' The purpose of this function is to aid in integrating and updating TADA dependencies
+#' developed under WQX2.0 to function with data retrieved using WQX3.0 service.
+#'
+#' TADA_RenametoLegacy function calls on EPA web services to read in the documented
+#' WQX3.0 schema file (schema_outbound_wqx3.0.csv).The file crosswalks WQX3.0 column names
+#' with equivalent WQX2.0 Legacy column names across profiles (e.g., PhysChem, ActivityMetric) where appropriate.
+#' The function uses data.table::setnames() to rename columns in the dataframe
+#' by reference - in this case where there are beta names, rename to legacy names, and skip where there are no matches.
+#'
+#'
+#' @param .data A water quality monitoring dataframe retrieved using dataRetrieval::readWQPdata using WQX3.0 Beta services
+#'
+#' @return A water quality monitoring dataframe with WQX2.0 Legacy column names
+#'
+#' @export
+#'
+#' @examples
+#' DeWitt_wqx3 <- dataRetrieval::readWQPdata(
+#' statecode = "Illinois",
+#' countycode = "DeWitt", characteristicName = "Nitrogen",
+#' service = "ResultWQX3", dataProfile = "fullPhysChem",
+#' ignore_attributes = TRUE
+#' )
+#'
+#' DeWitt_wqx3_withlegacynames <- EPATADA::TADA_RenametoLegacy(DeWitt_wqx3)
+#'
+TADA_RenametoLegacy <- function(.data) {
+ ## READ WQX3.0 column name schema from EPA Water Data WQP Quick Reference Guide
+ # https://www.epa.gov/waterdata/water-quality-portal-quick-reference-guide
+ wqxnames <- readr::read_csv("https://www.epa.gov/system/files/other-files/2025-07/schema_outbound_wqx3.0.csv",
+ show_col_types = FALSE
+ )
+
+ # Process schema crosswalk table to better suit TADA elements and reduce duplicate legacy elements
+ wqxnames_mod <- wqxnames |>
+ dplyr::mutate(WqxV2.FieldName = dplyr::case_when( # 3.0 element ~ change to in 2.0 element
+ FieldName3.0 == "SampleCollectionMethod_Description" ~ "SampleCollectionMethod/MethodDescriptionText",
+ FieldName3.0 == "DataQuality_PrecisionValue" ~ "DataQuality/PrecisionValue",
+ FieldName3.0 == "DataQuality_ConfidenceIntervalValue" ~ "DataQuality/ConfidenceIntervalValue",
+ FieldName3.0 == "DataQuality_UpperConfidenceLimitValue" ~ "DataQuality/UpperConfidenceLimitValue",
+ FieldName3.0 == "DataQuality_LowerConfidenceLimitValue" ~ "DataQuality/LowerConfidenceLimitValue",
+ FieldName3.0 == "ResultAnalyticalMethod_Description" ~ "ResultAnalyticalMethod/MethodDescriptionText",
+ FieldName3.0 == "Location_Latitude" ~ "LatitudeMeasure", # Changing to what is returned in legacy Site profile
+ FieldName3.0 == "Location_Longitude" ~ "LongitudeMeasure", # Changing to what is returned in legacy Site profile
+ FieldName3.0 == "Location_HorzCoordReferenceSystemDatum" ~ "HorizontalCoordinateReferenceSystemDatumName", # Changing to what is returned in legacy Site profile
+ FieldName3.0 == "SamplePrepMethod_Description" ~ NA, # Biological profile
+ FieldName3.0 == "LabSamplePrepMethod_Description" ~ NA, # Biological profile
+ FieldName3.0 == "LabSamplePrepMethod_EndTime" ~ NA, # Biological profile
+ FieldName3.0 == "ProjectAttachment_FileName" ~ NA, # named BinaryObjectFileName
+ FieldName3.0 == "ProjectAttachment_FileType" ~ NA, # named BinaryObjectFileTypeCode
+ FieldName3.0 == "ActivityAttachment_FileName" ~ NA,
+ FieldName3.0 == "ActivityAttachment_FileType" ~ NA,
+ FieldName3.0 == "ResultAttachment_FileName" ~ NA,
+ FieldName3.0 == "ResultAttachment_FileType" ~ NA,
+ TRUE ~ WqxV2.FieldName
+ )) |>
+ # Remove rows without a legacy name in the crosswalk table
+ dplyr::filter(!is.na(WqxV2.FieldName)) |>
+ # Some elements in the crosswalk table have different special characters compared to
+ # elements returned with dataRetrieval
+ # Using stringr to identify special characters replacing "_" with "." and "/" with "."
+ dplyr::mutate(WqxV2.FieldName = stringr::str_replace_all(WqxV2.FieldName, c("_" = ".", "/" = ".")))
+
+ # Make copy of original names from dataRetrieval 3.0 query bc data.table::setnames
+ # will overwrite original dataframe
+ df <- data.table::copy(.data)
+ beta_names_dr <- names(.data) # copy of original elements
+
+ # Create vectors of WQX3.0 and WQX2.0 (Legacy) column names
+ beta_names <- wqxnames_mod$FieldName3.0
+ legacy_names <- wqxnames_mod$WqxV2.FieldName
+
+ rm(WqxV2.FieldName)
+
+ if (length(beta_names) != length(legacy_names)) {
+ stop("`old names` and `new names` must be the same length", call. = FALSE)
+ }
+
+ df <- data.table::setnames(df,
+ old = beta_names,
+ new = legacy_names, skip_absent = TRUE
+ )
+
+ df <- TADA_OrderCols(df)
+
+ return(df)
+}
diff --git a/R/autoClean.R b/R/autoClean.R
index 0c37d60ac..c734e074a 100644
--- a/R/autoClean.R
+++ b/R/autoClean.R
@@ -1,7 +1,7 @@
#' TADA_AutoClean
#'
#' This function performs several cleaning tasks on a TADA dataframe.
-#'
+#'
#' **Column Creation and Capitalization**: Creates new columns with the TADA prefix "TADA." and capitalizes all letters within them for interoperability with USGS data and the WQX validation reference tables, reducing case-sensitivity issues when joining data. Affected columns include:
#' - CharacteristicName
#' - ResultSampleFractionText
@@ -9,7 +9,7 @@
#' - ResultMeasure.MeasureUnitCode
#' - ActivityMediaName
#' - DetectionQuantitationLimitMeasure.MeasureUnitCode
-#'
+#'
#' **Special Character Conversion**: Runs `TADA_ConvertSpecialChars` on the following columns and creates new versions with the TADA prefix:
#' - ResultMeasureValue
#' - DetectionQuantitationLimitMeasure.MeasureValue
@@ -27,31 +27,31 @@
#'
#' **Result Unit Harmonization**: Runs `TADA_ConvertResultUnits` to harmonize
#' result and detection limit units to WQX and TADA target units.
-#' For more details, including how to convert units to user supplied targets,
+#' For more details, including how to convert units to user supplied targets,
#' see `?TADA_ConvertResultUnits` and `?TADA_CreateUnitRef()`.
#'
-#' **Depth Unit Conversion**: Runs `TADA_ConvertDepthUnits` to convert depth
+#' **Depth Unit Conversion**: Runs `TADA_ConvertDepthUnits` to convert depth
#' units to meters on the following columns, adding new columns with the TADA prefix:
#' - ResultDepthHeightMeasure.MeasureValue
#' - ActivityDepthHeightMeasure.MeasureValue
#' - ActivityTopDepthHeightMeasure.MeasureValue
#' - ActivityBottomDepthHeightMeasure.MeasureValue
#'
-#' **Comparable ID Creation**: Runs `TADA_CreateComparableID` to create a
+#' **Comparable ID Creation**: Runs `TADA_CreateComparableID` to create a
#' `TADA.ComparableDataIdentifier` by concatenating:
#' - TADA.CharacteristicName
#' - TADA.ResultSampleFractionText
#' - TADA.MethodSpeciationName
#' - TADA.ResultMeasure.MeasureUnitCode
#'
-#' Original columns are not changed. New columns are appended to the dataframe
+#' Original columns are not changed. New columns are appended to the dataframe
#' with the prefix `TADA`. `TADA_AutoClean` can be run as a standalone function
#' but is primarily used by the `TADA_dataRetrieval` function.
#'
#' @param .data TADA dataframe
#'
#' @return Input dataframe with several added TADA-specific columns, including:
-#'
+#'
#' - TADA.ActivityMediaName (character)
#' - TADA.ResultSampleFractionText (character)
#' - TADA.CharacteristicName (character)
@@ -82,8 +82,8 @@
#' - TADA.MonitoringLocationName (character)
#' - TADA.MonitoringLocationTypeName (character)
#'
-#' Note: The number of TADA-specific depth columns in the returned dataframe
-#' depends on the number of depth columns with one or more results populated
+#' Note: The number of TADA-specific depth columns in the returned dataframe
+#' depends on the number of depth columns with one or more results populated
#' with a numeric value. If all depth columns contain only NA's, no conversion
#' is necessary and no TADA depth columns are created.
#'
@@ -108,8 +108,10 @@
#'
#' # Construct URLs for different profiles
#' station_url <- paste0(baseurl, "/data/Station", filters, dates, type, providers)
-#' result_url <- paste0(baseurl, "/data/Result", filters, dates, type,
-#' "&dataProfile=resultPhysChem", providers)
+#' result_url <- paste0(
+#' baseurl, "/data/Result", filters, dates, type,
+#' "&dataProfile=resultPhysChem", providers
+#' )
#' project_url <- paste0(baseurl, "/data/Project", filters, dates, type, providers)
#'
#' # Use TADA_ReadWQPWebServices to load Station, Project, and Phys-Chem Result profiles
@@ -127,22 +129,22 @@
#' # Run TADA_AutoClean
#' Autocleaned_TADAProfile <- TADA_AutoClean(TADAProfile)
#' }
-#'
+#'
TADA_AutoClean <- function(.data) {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
# need to specify this or throws error when trying to bind rows. Temporary fix for larger
# issue where data structure for all columns should be specified.
cols <- names(.data)
.data <- .data %>% dplyr::mutate_at(cols, as.character)
-
+
# .data required columns
required_cols <- c(
"ActivityMediaName", "ResultMeasureValue", "ResultMeasure.MeasureUnitCode",
@@ -361,17 +363,17 @@ TADA_AutoClean <- function(.data) {
#' # Run flagging functions and remove and suspect rows
#' remove_suspect <- TADA_RunKeyFlagFunctions(Data_6Tribes_5y, clean = TRUE)
#' }
-#'
+#'
TADA_RunKeyFlagFunctions <- function(.data, clean = FALSE) {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
if (clean == TRUE) {
.data <- TADA_FlagResultUnit(.data, clean = "suspect_only")
.data <- TADA_FlagFraction(.data, clean = TRUE)
diff --git a/R/autoFilter.R b/R/autoFilter.R
index 5eab94273..199f49fd9 100644
--- a/R/autoFilter.R
+++ b/R/autoFilter.R
@@ -29,9 +29,9 @@ TADA_FieldCounts <- function(.data, display = c("key", "most", "all"), character
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
# # run required flagging/cleaning functions
# if ("TADA.UseForAnalysis.Flag" %in% colnames(.data)) {
# .data <- .data
@@ -195,9 +195,9 @@ TADA_FieldValuesTable <- function(.data, field = "null", characteristicName = "n
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
if (!field %in% names(.data)) {
stop("Field input does not exist in dataset. Please populate the 'field' argument with a valid field name. Enter ?TADA_FieldValuesTable in console for more information.")
}
@@ -300,13 +300,13 @@ TADA_AnalysisDataFilter <- function(.data,
other = TRUE) {
# check .data is data.frame
TADA_CheckType(.data, "data.frame", "Input object")
-
+
# Check if the input data frame is empty
if (nrow(.data) == 0) {
message("The entered data frame is empty. The function will not run.")
- return(NULL) # Exit the function early
- }
-
+ return(NULL) # Exit the function early
+ }
+
# *Need to add fish tissue to this function once using WQX 3.0 profiles
# import MonitoringLocationTypeNames and TADA.Media.Flags
diff --git a/R/dev/requiredMaintenance.R b/R/dev/requiredMaintenance.R
index 5d3b09b47..43e39f768 100644
--- a/R/dev/requiredMaintenance.R
+++ b/R/dev/requiredMaintenance.R
@@ -186,9 +186,10 @@ TADA_UpdateExampleData <- function() {
TADA.ResultSelectedMultipleOrgs == "Y"
)
# Filter out remaining irrelevant data, NA's and empty cols
- Data_WV <- TADA_ConvertSpecialChars(Data_WV,
- col = "TADA.ResultMeasureValue",
- clean = TRUE)
+ Data_WV <- TADA_ConvertSpecialChars(Data_WV,
+ col = "TADA.ResultMeasureValue",
+ clean = TRUE
+ )
# Remove results with QC issues
# REQUIRED
Data_WV <- TADA_RunKeyFlagFunctions(
@@ -223,6 +224,7 @@ spelling::spell_check_package(
pkg = ".",
vignettes = TRUE
)
+
# run to update spelling word list
spelling::get_wordlist()
spelling::update_wordlist()
@@ -240,7 +242,7 @@ style_pkg()
# Run devtools check and test
devtools::test()
-# devtools::check()
+# devtools::check()
# more robust test for releases (includes broken link check)
devtools::check(manual = FALSE, remote = TRUE, incoming = TRUE)
diff --git a/data/Data_6Tribes_5y.rda b/data/Data_6Tribes_5y.rda
index ef5a4d70a..55418cf7d 100644
Binary files a/data/Data_6Tribes_5y.rda and b/data/Data_6Tribes_5y.rda differ
diff --git a/data/Data_6Tribes_5y_Harmonized.rda b/data/Data_6Tribes_5y_Harmonized.rda
index 0dc708ce0..5a650ad72 100644
Binary files a/data/Data_6Tribes_5y_Harmonized.rda and b/data/Data_6Tribes_5y_Harmonized.rda differ
diff --git a/data/Data_HUC8_02070004_Mod1Output.rda b/data/Data_HUC8_02070004_Mod1Output.rda
index c39ed7df5..d13bd3432 100644
Binary files a/data/Data_HUC8_02070004_Mod1Output.rda and b/data/Data_HUC8_02070004_Mod1Output.rda differ
diff --git a/data/Data_Nutrients_UT.rda b/data/Data_Nutrients_UT.rda
index 9ff5efa54..697a0fae5 100644
Binary files a/data/Data_Nutrients_UT.rda and b/data/Data_Nutrients_UT.rda differ
diff --git a/data/Data_R5_TADAPackageDemo.rda b/data/Data_R5_TADAPackageDemo.rda
index fece7a221..a0d5f0c3c 100644
Binary files a/data/Data_R5_TADAPackageDemo.rda and b/data/Data_R5_TADAPackageDemo.rda differ
diff --git a/inst/WORDLIST b/inst/WORDLIST
index e6dfee8f2..938cc26ee 100644
--- a/inst/WORDLIST
+++ b/inst/WORDLIST
@@ -2,7 +2,8 @@ ANDs
AOI
ATTAINSOrgIDsRef
ATTAINSParameterWQPCharRef
-AUS
+AU's
+AUMLRef
AUs
ActivityBottomDepthHeightMeasure
ActivityCommentText
@@ -11,6 +12,7 @@ ActivityDepthHeightMeasure
ActivityGroup
ActivityMediaName
ActivityMediaSubdivisionName
+ActivityMetric
ActivityRelativeDepthName
ActivityStartDate
ActivityStartDateTime
@@ -26,9 +28,8 @@ Animas
AquiferName
ArcGIS
AssemblageSampledName
+AssessmentUnitIdentifier
AutoClean
-AutoFilter
-Autofilter
BiasValue
BigDataRetrieval
BiologicalIntentName
@@ -64,12 +65,16 @@ ConvertDepthUnits
ConvertResultUnits
ConvertSpecialChars
CountyCode
+CreateATTAINSAUML
+CreateATTAINSAUMLCrosswalk
+CreateAUMLCrosswalk
CreateComparableID
CreatePairRef
CreateParamRef
CreateUnitRef
CreateUseAURef
CreateUseParamRef
+CreateWaterUseRef
Cybertown
DV
DataFrame
@@ -90,6 +95,7 @@ EASP
EASP's
ECHO's
EMEF
+ExpertQuery
FONDULAC
Farmington
FieldCounts
@@ -116,7 +122,8 @@ FlagUseName
FractionAssumptions
FullPhysChem
Geospatial
-GetATTAINS
+GetATTAINSAUMLCrosswalk
+GetATTAINSByAUID
GetCharacteristicRef
GetNutrientSummationRef
GetSynonymRef
@@ -150,6 +157,7 @@ LatitudeMeasure
LocalAqfrName
LongitudeMeasure
MDE
+MDEQ
MakeSpatial
MapServer
MeasureQualiferCode
@@ -168,6 +176,7 @@ MethodQualifierCodes
MethodQualifierTypeName
MethodSpeciation
MethodSpeciationName
+Missoula
MonitoringDataLinkText
MonitoringLocation
MonitoringLocationIdentifier
@@ -218,6 +227,7 @@ ParamRef
ParameterName
ParameterNames
PartB
+PhysChem
Pojoaque
ProjectFileUrl
ProjectName
@@ -225,7 +235,6 @@ ProviderName
ProviderNames
QAPP
QAPPApprovedIndicator
-QAPPAprrovedIndicator
QAPPDocAvailable
QAQC
QAQC'd
@@ -244,6 +253,7 @@ RProj
RStudio
RWQC
Rancherias
+RenametoLegacy
ReplicateSampleID
Repo
ResultAggregation
@@ -269,6 +279,7 @@ ResultValueAboveUpperThreshold
ResultValueAggregation
ResultValueBelowLowerThreshold
ResultValueTypeName
+ResultWQX
ResultWeightBasisText
RetainRequired
Rmd
@@ -305,8 +316,10 @@ TADAModule
TADAPackageDemo
TADAPriorityCharUnitRef
TADAProfile
+TADAProfileClean
TADAShiny
TMDL
+TP
TargetUnit
Tesuque
Thawley
@@ -320,6 +333,7 @@ Uncomment
UncommonAnalyticalMethodID
UniqueHarmonizationRef
UnitCode
+UpdateATTAINSAUMLCrosswalk
UpdateTribalLayers
UseForAnalysis
UseName
@@ -329,6 +343,7 @@ UseParamRef
VCS
ViewATTAINS
WGS
+WQ
WQC
WQP
WQX
@@ -345,7 +360,7 @@ WQXVal
WQXcharValRef
WQXunitRef
WaterSciCon
-WaterTypeCode
+WaterType
Waterbody
WaterbodyReport
WellDepthMeasure
@@ -361,11 +376,11 @@ aoi
applyautoclean
arcgis
asNO
-assessmentunitidentifier
autoassign
autoclean
autocleaned
bBox
+batchupload
bbox
bnd
bottomvalue
@@ -376,6 +391,7 @@ characteristicName
characteristicType
charactersitic
cleanNA
+coli
comid
countrycode
countycode
@@ -429,7 +445,6 @@ hydrography
hydrologic
hydroloom
importWQP
-interoperable
io
lessthan
listNWIS
@@ -439,12 +454,14 @@ manys
mapviewer
maxrecs
mimeType
+mlid
mlt
myfileRef
nd
nhdplus
nhdplusTools
nondetections
+nondetects
nonstandardized
np
nresults
@@ -453,6 +470,7 @@ offsetLibrary
orgs
ousideUSA
outsideUSA
+overdetects
param
paramRef
params
@@ -473,10 +491,10 @@ resultCount
sampleMedia
sd
secchi
+setnames
shp
siteType
siteid
-sitesAURef
sitetype
speciation
speciations
diff --git a/inst/extdata/AKAllotments.dbf b/inst/extdata/AKAllotments.dbf
index 03adaaa07..ce09f7ba4 100644
Binary files a/inst/extdata/AKAllotments.dbf and b/inst/extdata/AKAllotments.dbf differ
diff --git a/inst/extdata/AKVillages.dbf b/inst/extdata/AKVillages.dbf
index c965ddb0b..da8ed7e9a 100644
Binary files a/inst/extdata/AKVillages.dbf and b/inst/extdata/AKVillages.dbf differ
diff --git a/inst/extdata/AmericanIndian.dbf b/inst/extdata/AmericanIndian.dbf
index 9197c8866..d9f636f9d 100644
Binary files a/inst/extdata/AmericanIndian.dbf and b/inst/extdata/AmericanIndian.dbf differ
diff --git a/inst/extdata/CST.csv b/inst/extdata/CST.csv
index 805e92f5b..e6e879974 100644
--- a/inst/extdata/CST.csv
+++ b/inst/extdata/CST.csv
@@ -4,89 +4,89 @@
"AMMONIA-NITROGEN","ammonia","304A","Aquatic Life","varies - see web page","A","S",NA,NA,"[no units]"
"AMMONIA-NITROGEN","ammonia","304A","Aquatic Life","varies - see web page","A","S",NA,NA,"[no units]"
"AMMONIUM","ammonia","304A","Aquatic Life","varies - see web page","A","S",NA,NA,"[no units]"
-NA,"1,2,4,5-tetrachlorobenzene","304A","Human Health","0.03","H",NA,NA,"O","g/l"
-NA,"tetrachloroethylene","304A","Human Health","10","H",NA,NA,"W","g/l"
-NA,"tetrachloroethylene","304A","Human Health","29","H",NA,NA,"O","g/l"
-NA,"thallium","304A","Human Health","0.24","H",NA,NA,"W","g/l"
-NA,"thallium","304A","Human Health","0.47","H",NA,NA,"O","g/l"
-NA,"toluene","304A","Human Health","57","H",NA,NA,"W","g/l"
-NA,"toluene","304A","Human Health","520","H",NA,NA,"O","g/l"
-NA,"toxaphene","304A","Human Health","7.0E-4","H",NA,NA,"W","g/l"
-NA,"toxaphene","304A","Human Health","7.1E-4","H",NA,NA,"O","g/l"
-NA,"trichloroethylene","304A","Human Health","0.6","H",NA,NA,"W","g/l"
-NA,"trichloroethylene","304A","Human Health","7","H",NA,NA,"O","g/l"
-NA,"2,4,5-trichlorophenol","304A","Human Health","300","H",NA,NA,"W","g/l"
-NA,"2,4,5-trichlorophenol","304A","Human Health","600","H",NA,NA,"O","g/l"
-NA,"cyanide","304A","Aquatic Life","5.2","A","F","C",NA,"g/l"
-NA,"cyanide","304A","Aquatic Life","1","A","S","A",NA,"g/l"
-NA,"cyanide","304A","Aquatic Life","1","A","S","C",NA,"g/l"
-NA,"demeton","304A","Aquatic Life","0.1","A","F","C",NA,"g/l"
-NA,"demeton","304A","Aquatic Life","0.1","A","S","C",NA,"g/l"
-NA,"diazinon","304A","Aquatic Life","0.17","A","F","A",NA,"g/l"
-NA,"diazinon","304A","Aquatic Life","0.17","A","F","C",NA,"g/l"
-NA,"diazinon","304A","Aquatic Life","0.82","A","S","A",NA,"g/l"
-NA,"diazinon","304A","Aquatic Life","0.82","A","S","C",NA,"g/l"
-NA,"dieldrin","304A","Aquatic Life","0.24","A","F","A",NA,"g/l"
-NA,"dieldrin","304A","Aquatic Life","0.056","A","F","C",NA,"g/l"
-NA,"dieldrin","304A","Aquatic Life","0.71","A","S","A",NA,"g/l"
-NA,"dieldrin","304A","Aquatic Life","0.0019","A","S","C",NA,"g/l"
-NA,"endrin","304A","Aquatic Life","0.086","A","F","A",NA,"g/l"
-NA,"endrin","304A","Aquatic Life","0.036","A","F","C",NA,"g/l"
-NA,"endrin","304A","Aquatic Life","0.037","A","S","A",NA,"g/l"
-NA,"endrin","304A","Aquatic Life","0.0023","A","S","C",NA,"g/l"
-NA,"gamma-bhc (lindane)","304A","Aquatic Life","0.95","A","F","A",NA,"g/l"
-NA,"gamma-bhc (lindane)","304A","Aquatic Life","0.16","A","S","A",NA,"g/l"
-NA,"gases, total dissolved","304A","Aquatic Life","NARRATIVE STATEMENTSEE DOCUMENTC","A",NA,NA,NA,"g/l"
-NA,"guthion","304A","Aquatic Life","0.01","A","F","C",NA,"g/l"
-NA,"guthion","304A","Aquatic Life","0.01","A","S","C",NA,"g/l"
-"HARDNESS","hardness","304A","Aquatic Life","NARRATIVE STATEMENTSEE DOCUMENT","A",NA,NA,NA,"g/l"
-"HARDNESS, CA, MG","hardness","304A","Aquatic Life","NARRATIVE STATEMENTSEE DOCUMENT","A",NA,NA,NA,"g/l"
-"HARDNESS, CALCIUM","hardness","304A","Aquatic Life","NARRATIVE STATEMENTSEE DOCUMENT","A",NA,NA,NA,"g/l"
-"HARNDESS, CARBONATE","hardness","304A","Aquatic Life","NARRATIVE STATEMENTSEE DOCUMENT","A",NA,NA,NA,"g/l"
-"HARDNESS, MAGNESIUM","hardness","304A","Aquatic Life","NARRATIVE STATEMENTSEE DOCUMENT","A",NA,NA,NA,"g/l"
-"HARDNESS, NON-CARBONATE","hardness","304A","Aquatic Life","NARRATIVE STATEMENTSEE DOCUMENT","A",NA,NA,NA,"g/l"
-"TOTAL HARDNESS","hardness","304A","Aquatic Life","NARRATIVE STATEMENTSEE DOCUMENT","A",NA,NA,NA,"g/l"
-NA,"heptachlor","304A","Aquatic Life","0.52","A","F","A",NA,"g/l"
-NA,"heptachlor","304A","Aquatic Life","0.0038","A","F","C",NA,"g/l"
-NA,"heptachlor","304A","Aquatic Life","0.053","A","S","A",NA,"g/l"
-NA,"heptachlor","304A","Aquatic Life","0.0036","A","S","C",NA,"g/l"
-NA,"heptachlor epoxide","304A","Aquatic Life","0.52","A","F","A",NA,"g/l"
-NA,"heptachlor epoxide","304A","Aquatic Life","0.0038","A","F","C",NA,"g/l"
-NA,"heptachlor epoxide","304A","Aquatic Life","0.053","A","S","A",NA,"g/l"
-NA,"heptachlor epoxide","304A","Aquatic Life","0.0036","A","S","C",NA,"g/l"
-NA,"iron","304A","Aquatic Life","1000","A","F","C",NA,"g/l"
-NA,"bis(2-chloroethyl) ether","304A","Human Health","2.2","H",NA,NA,"O","g/l"
-NA,"bis(2-chloro-1-methylethyl) ether","304A","Human Health","200","H",NA,NA,"W","g/l"
-NA,"bis(2-chloro-1-methylethyl) ether","304A","Human Health","4000","H",NA,NA,"O","g/l"
-NA,"bis(2-ethylhexyl) phthalate","304A","Human Health","0.32","H",NA,NA,"W","g/l"
-NA,"bis(2-ethylhexyl) phthalate","304A","Human Health","0.37","H",NA,NA,"O","g/l"
-NA,"bromoform","304A","Human Health","7.0","H",NA,NA,"W","g/l"
-NA,"bromoform","304A","Human Health","120","H",NA,NA,"O","g/l"
-NA,"butylbenzyl phthalate","304A","Human Health","0.1","H",NA,NA,"W","g/l"
-NA,"butylbenzyl phthalate","304A","Human Health","0.1","H",NA,NA,"O","g/l"
-"CADMIUM","cadmium","304A","Human Health","See note","H",NA,NA,"W","g/l"
-NA,"carbon tetrachloride","304A","Human Health","0.4","H",NA,NA,"W","g/l"
-NA,"carbon tetrachloride","304A","Human Health","5","H",NA,NA,"O","g/l"
-NA,"chlordane","304A","Human Health","3.1E-4","H",NA,NA,"W","g/l"
-NA,"chlordane","304A","Human Health","3.2E-4","H",NA,NA,"O","g/l"
-NA,"chlorobenzene","304A","Human Health","100","H",NA,NA,"W","g/l"
-NA,"chlorobenzene","304A","Human Health","800","H",NA,NA,"O","g/l"
-NA,"chlorodibromomethane","304A","Human Health","0.8","H",NA,NA,"W","g/l"
-NA,"chlorodibromomethane","304A","Human Health","21","H",NA,NA,"O","g/l"
-NA,"chloroform","304A","Human Health","60","H",NA,NA,"W","g/l"
-NA,"chloroform","304A","Human Health","2000","H",NA,NA,"O","g/l"
-NA,"chlorophenoxy herbicide (2,4-d)","304A","Human Health","1300","H",NA,NA,"W","g/l"
+NA,"1,2,4,5-tetrachlorobenzene","304A","Human Health","0.03","H",NA,NA,"O","µg/l"
+NA,"tetrachloroethylene","304A","Human Health","10","H",NA,NA,"W","µg/l"
+NA,"tetrachloroethylene","304A","Human Health","29","H",NA,NA,"O","µg/l"
+NA,"thallium","304A","Human Health","0.24","H",NA,NA,"W","µg/l"
+NA,"thallium","304A","Human Health","0.47","H",NA,NA,"O","µg/l"
+NA,"toluene","304A","Human Health","57","H",NA,NA,"W","µg/l"
+NA,"toluene","304A","Human Health","520","H",NA,NA,"O","µg/l"
+NA,"toxaphene","304A","Human Health","7.0E-4","H",NA,NA,"W","µg/l"
+NA,"toxaphene","304A","Human Health","7.1E-4","H",NA,NA,"O","µg/l"
+NA,"trichloroethylene","304A","Human Health","0.6","H",NA,NA,"W","µg/l"
+NA,"trichloroethylene","304A","Human Health","7","H",NA,NA,"O","µg/l"
+NA,"2,4,5-trichlorophenol","304A","Human Health","300","H",NA,NA,"W","µg/l"
+NA,"2,4,5-trichlorophenol","304A","Human Health","600","H",NA,NA,"O","µg/l"
+NA,"cyanide","304A","Aquatic Life","5.2","A","F","C",NA,"µg/l"
+NA,"cyanide","304A","Aquatic Life","1","A","S","A",NA,"µg/l"
+NA,"cyanide","304A","Aquatic Life","1","A","S","C",NA,"µg/l"
+NA,"demeton","304A","Aquatic Life","0.1","A","F","C",NA,"µg/l"
+NA,"demeton","304A","Aquatic Life","0.1","A","S","C",NA,"µg/l"
+NA,"diazinon","304A","Aquatic Life","0.17","A","F","A",NA,"µg/l"
+NA,"diazinon","304A","Aquatic Life","0.17","A","F","C",NA,"µg/l"
+NA,"diazinon","304A","Aquatic Life","0.82","A","S","A",NA,"µg/l"
+NA,"diazinon","304A","Aquatic Life","0.82","A","S","C",NA,"µg/l"
+NA,"dieldrin","304A","Aquatic Life","0.24","A","F","A",NA,"µg/l"
+NA,"dieldrin","304A","Aquatic Life","0.056","A","F","C",NA,"µg/l"
+NA,"dieldrin","304A","Aquatic Life","0.71","A","S","A",NA,"µg/l"
+NA,"dieldrin","304A","Aquatic Life","0.0019","A","S","C",NA,"µg/l"
+NA,"endrin","304A","Aquatic Life","0.086","A","F","A",NA,"µg/l"
+NA,"endrin","304A","Aquatic Life","0.036","A","F","C",NA,"µg/l"
+NA,"endrin","304A","Aquatic Life","0.037","A","S","A",NA,"µg/l"
+NA,"endrin","304A","Aquatic Life","0.0023","A","S","C",NA,"µg/l"
+NA,"gamma-bhc (lindane)","304A","Aquatic Life","0.95","A","F","A",NA,"µg/l"
+NA,"gamma-bhc (lindane)","304A","Aquatic Life","0.16","A","S","A",NA,"µg/l"
+NA,"gases, total dissolved","304A","Aquatic Life","NARRATIVE STATEMENT—SEE DOCUMENT C","A",NA,NA,NA,"µg/l"
+NA,"guthion","304A","Aquatic Life","0.01","A","F","C",NA,"µg/l"
+NA,"guthion","304A","Aquatic Life","0.01","A","S","C",NA,"µg/l"
+"HARDNESS","hardness","304A","Aquatic Life","NARRATIVE STATEMENT—SEE DOCUMENT","A",NA,NA,NA,"µg/l"
+"HARDNESS, CA, MG","hardness","304A","Aquatic Life","NARRATIVE STATEMENT—SEE DOCUMENT","A",NA,NA,NA,"µg/l"
+"HARDNESS, CALCIUM","hardness","304A","Aquatic Life","NARRATIVE STATEMENT—SEE DOCUMENT","A",NA,NA,NA,"µg/l"
+"HARNDESS, CARBONATE","hardness","304A","Aquatic Life","NARRATIVE STATEMENT—SEE DOCUMENT","A",NA,NA,NA,"µg/l"
+"HARDNESS, MAGNESIUM","hardness","304A","Aquatic Life","NARRATIVE STATEMENT—SEE DOCUMENT","A",NA,NA,NA,"µg/l"
+"HARDNESS, NON-CARBONATE","hardness","304A","Aquatic Life","NARRATIVE STATEMENT—SEE DOCUMENT","A",NA,NA,NA,"µg/l"
+"TOTAL HARDNESS","hardness","304A","Aquatic Life","NARRATIVE STATEMENT—SEE DOCUMENT","A",NA,NA,NA,"µg/l"
+NA,"heptachlor","304A","Aquatic Life","0.52","A","F","A",NA,"µg/l"
+NA,"heptachlor","304A","Aquatic Life","0.0038","A","F","C",NA,"µg/l"
+NA,"heptachlor","304A","Aquatic Life","0.053","A","S","A",NA,"µg/l"
+NA,"heptachlor","304A","Aquatic Life","0.0036","A","S","C",NA,"µg/l"
+NA,"heptachlor epoxide","304A","Aquatic Life","0.52","A","F","A",NA,"µg/l"
+NA,"heptachlor epoxide","304A","Aquatic Life","0.0038","A","F","C",NA,"µg/l"
+NA,"heptachlor epoxide","304A","Aquatic Life","0.053","A","S","A",NA,"µg/l"
+NA,"heptachlor epoxide","304A","Aquatic Life","0.0036","A","S","C",NA,"µg/l"
+NA,"iron","304A","Aquatic Life","1000","A","F","C",NA,"µg/l"
+NA,"bis(2-chloroethyl) ether","304A","Human Health","2.2","H",NA,NA,"O","µg/l"
+NA,"bis(2-chloro-1-methylethyl) ether","304A","Human Health","200","H",NA,NA,"W","µg/l"
+NA,"bis(2-chloro-1-methylethyl) ether","304A","Human Health","4000","H",NA,NA,"O","µg/l"
+NA,"bis(2-ethylhexyl) phthalate","304A","Human Health","0.32","H",NA,NA,"W","µg/l"
+NA,"bis(2-ethylhexyl) phthalate","304A","Human Health","0.37","H",NA,NA,"O","µg/l"
+NA,"bromoform","304A","Human Health","7.0","H",NA,NA,"W","µg/l"
+NA,"bromoform","304A","Human Health","120","H",NA,NA,"O","µg/l"
+NA,"butylbenzyl phthalate","304A","Human Health","0.1","H",NA,NA,"W","µg/l"
+NA,"butylbenzyl phthalate","304A","Human Health","0.1","H",NA,NA,"O","µg/l"
+"CADMIUM","cadmium","304A","Human Health","See note","H",NA,NA,"W","µg/l"
+NA,"carbon tetrachloride","304A","Human Health","0.4","H",NA,NA,"W","µg/l"
+NA,"carbon tetrachloride","304A","Human Health","5","H",NA,NA,"O","µg/l"
+NA,"chlordane","304A","Human Health","3.1E-4","H",NA,NA,"W","µg/l"
+NA,"chlordane","304A","Human Health","3.2E-4","H",NA,NA,"O","µg/l"
+NA,"chlorobenzene","304A","Human Health","100","H",NA,NA,"W","µg/l"
+NA,"chlorobenzene","304A","Human Health","800","H",NA,NA,"O","µg/l"
+NA,"chlorodibromomethane","304A","Human Health","0.8","H",NA,NA,"W","µg/l"
+NA,"chlorodibromomethane","304A","Human Health","21","H",NA,NA,"O","µg/l"
+NA,"chloroform","304A","Human Health","60","H",NA,NA,"W","µg/l"
+NA,"chloroform","304A","Human Health","2000","H",NA,NA,"O","µg/l"
+NA,"chlorophenoxy herbicide (2,4-d)","304A","Human Health","1300","H",NA,NA,"W","µg/l"
"CHROMIUM(III)","chromium (iii)","304A","Human Health","See note","H",NA,NA,"W","total"
"CHROMIUM(VI)","chromium (vi)","304A","Human Health","See note","H",NA,NA,"W","total"
-NA,"chrysene","304A","Human Health","0.12","H",NA,NA,"W","g/l"
-NA,"chrysene","304A","Human Health","0.13","H",NA,NA,"O","g/l"
-"COPPER","copper","304A","Human Health","1300","H",NA,NA,"W","g/l"
-NA,"cyanide","304A","Human Health","4","H",NA,NA,"W","g/l"
-NA,"cyanide","304A","Human Health","400","H",NA,NA,"O","g/l"
-NA,"hexachlorocyclohexane (hch)-technical","304A","Human Health","0.01","H",NA,NA,"O","g/l"
-NA,"hexachlorocyclopentadiene","304A","Human Health","4","H",NA,NA,"W","g/l"
-NA,"hexachlorocyclopentadiene","304A","Human Health","4","H",NA,NA,"O","g/l"
-NA,"alpha-endosulfan","304A","Aquatic Life","0.0087","A","S","C",NA,"g/l"
+NA,"chrysene","304A","Human Health","0.12","H",NA,NA,"W","µg/l"
+NA,"chrysene","304A","Human Health","0.13","H",NA,NA,"O","µg/l"
+"COPPER","copper","304A","Human Health","1300","H",NA,NA,"W","µg/l"
+NA,"cyanide","304A","Human Health","4","H",NA,NA,"W","µg/l"
+NA,"cyanide","304A","Human Health","400","H",NA,NA,"O","µg/l"
+NA,"hexachlorocyclohexane (hch)-technical","304A","Human Health","0.01","H",NA,NA,"O","µg/l"
+NA,"hexachlorocyclopentadiene","304A","Human Health","4","H",NA,NA,"W","µg/l"
+NA,"hexachlorocyclopentadiene","304A","Human Health","4","H",NA,NA,"O","µg/l"
+NA,"alpha-endosulfan","304A","Aquatic Life","0.0087","A","S","C",NA,"µg/l"
NA,"aluminum","304A","Aquatic Life","see criteria calculator","A","F","A",NA,"[no units]"
NA,"aluminum","304A","Aquatic Life","see criteria calculator","A","F","C",NA,"[no units]"
"AMMONIA","ammonia","304A","Aquatic Life","varies - see web page","A","F",NA,NA,"[no units]"
@@ -94,373 +94,373 @@ NA,"aluminum","304A","Aquatic Life","see criteria calculator","A","F","C",NA,"[n
"AMMONIA-NITROGEN","ammonia","304A","Aquatic Life","varies - see web page","A","F",NA,NA,"[no units]"
"AMMONIA-NITROGEN","ammonia","304A","Aquatic Life","varies - see web page","A","F",NA,NA,"[no units]"
"AMMONIUM","ammonia","304A","Aquatic Life","varies - see web page","A","F",NA,NA,"[no units]"
-NA,"arsenic","304A","Aquatic Life","340","A","F","A",NA,"g/l"
-NA,"arsenic","304A","Aquatic Life","150","A","F","C",NA,"g/l"
-NA,"arsenic","304A","Aquatic Life","69","A","S","A",NA,"g/l"
-NA,"arsenic","304A","Aquatic Life","36","A","S","C",NA,"g/l"
-NA,"bacteria","304A","Aquatic Life","FOR PRIMARY RECREATION AND SHELLFISH USESSEE DOCUMENT","A","F","A",NA,"g/l"
-NA,"beta-endosulfan","304A","Aquatic Life","0.22","A","F","A",NA,"g/l"
-NA,"beta-endosulfan","304A","Aquatic Life","0.056","A","F","C",NA,"g/l"
-NA,"beta-endosulfan","304A","Aquatic Life","0.034","A","S","A",NA,"g/l"
-NA,"beta-endosulfan","304A","Aquatic Life","0.0087","A","S","C",NA,"g/l"
-"BORON","boron","304A","Aquatic Life","NARRATIVE STATEMENTSEE DOCUMENT","A",NA,NA,NA,"g/l"
+NA,"arsenic","304A","Aquatic Life","340","A","F","A",NA,"µg/l"
+NA,"arsenic","304A","Aquatic Life","150","A","F","C",NA,"µg/l"
+NA,"arsenic","304A","Aquatic Life","69","A","S","A",NA,"µg/l"
+NA,"arsenic","304A","Aquatic Life","36","A","S","C",NA,"µg/l"
+NA,"bacteria","304A","Aquatic Life","FOR PRIMARY RECREATION AND SHELLFISH USES—SEE DOCUMENT","A","F","A",NA,"µg/l"
+NA,"beta-endosulfan","304A","Aquatic Life","0.22","A","F","A",NA,"µg/l"
+NA,"beta-endosulfan","304A","Aquatic Life","0.056","A","F","C",NA,"µg/l"
+NA,"beta-endosulfan","304A","Aquatic Life","0.034","A","S","A",NA,"µg/l"
+NA,"beta-endosulfan","304A","Aquatic Life","0.0087","A","S","C",NA,"µg/l"
+"BORON","boron","304A","Aquatic Life","NARRATIVE STATEMENT—SEE DOCUMENT","A",NA,NA,NA,"µg/l"
NA,"carbaryl","304A","Aquatic Life","2.1","A","F","A",NA,"no unit name"
NA,"carbaryl","304A","Aquatic Life","2.1","A","F","C",NA,"no unit name"
-NA,"2,4-dimethylphenol","304A","Organoleptic","400","O",NA,NA,NA,"g/l"
-NA,"hexachlorocyclopentadiene","304A","Organoleptic","1","O",NA,NA,NA,"g/l"
-NA,"nitrobenzene","304A","Organoleptic","30","O",NA,NA,NA,"g/l"
-NA,"pentachlorophenol","304A","Organoleptic","30","O",NA,NA,NA,"g/l"
-NA,"phenol","304A","Organoleptic","300","O",NA,NA,NA,"g/l"
-"ZINC","zinc","304A","Organoleptic","5000","O",NA,NA,NA,"g/l"
-NA,"acrolein","304A","Aquatic Life","3","A","F","A",NA,"g/l"
-NA,"acrolein","304A","Aquatic Life","3","A","F","C",NA,"g/l"
+NA,"2,4-dimethylphenol","304A","Organoleptic","400","O",NA,NA,NA,"µg/l"
+NA,"hexachlorocyclopentadiene","304A","Organoleptic","1","O",NA,NA,NA,"µg/l"
+NA,"nitrobenzene","304A","Organoleptic","30","O",NA,NA,NA,"µg/l"
+NA,"pentachlorophenol","304A","Organoleptic","30","O",NA,NA,NA,"µg/l"
+NA,"phenol","304A","Organoleptic","300","O",NA,NA,NA,"µg/l"
+"ZINC","zinc","304A","Organoleptic","5000","O",NA,NA,NA,"µg/l"
+NA,"acrolein","304A","Aquatic Life","3","A","F","A",NA,"µg/l"
+NA,"acrolein","304A","Aquatic Life","3","A","F","C",NA,"µg/l"
NA,"aesthetic qualities","304A","Aquatic Life","Narrative Statement - See Document","A",NA,NA,NA,"no unit name"
-NA,"aldrin","304A","Aquatic Life","3.0","A","F","A",NA,"g/l"
-NA,"aldrin","304A","Aquatic Life","1.3","A","S","A",NA,"g/l"
-NA,"alkalinity","304A","Aquatic Life","20000","A","F","C",NA,"g/l"
-NA,"alpha-endosulfan","304A","Aquatic Life","0.22","A","F","A",NA,"g/l"
-NA,"alpha-endosulfan","304A","Aquatic Life","0.056","A","F","C",NA,"g/l"
-NA,"alpha-endosulfan","304A","Aquatic Life","0.034","A","S","A",NA,"g/l"
-NA,"dichlorobromomethane","304A","Human Health","0.95","H",NA,NA,"W","g/l"
-NA,"dichlorobromomethane","304A","Human Health","27","H",NA,NA,"O","g/l"
-NA,"dieldrin","304A","Human Health","1.2E-6","H",NA,NA,"W","g/l"
-NA,"dieldrin","304A","Human Health","1.2E-6","H",NA,NA,"O","g/l"
-NA,"diethyl phthalate","304A","Human Health","600","H",NA,NA,"W","g/l"
-NA,"diethyl phthalate","304A","Human Health","600","H",NA,NA,"O","g/l"
-NA,"dimethyl phthalate","304A","Human Health","2000","H",NA,NA,"W","g/l"
-NA,"dimethyl phthalate","304A","Human Health","2000","H",NA,NA,"O","g/l"
-"LEAD","lead","304A","Aquatic Life","65","A","F","A",NA,"g/l"
-"LEAD","lead","304A","Aquatic Life","2.5","A","F","C",NA,"g/l"
-"LEAD","lead","304A","Aquatic Life","210","A","S","A",NA,"g/l"
-"LEAD","lead","304A","Aquatic Life","8.1","A","S","C",NA,"g/l"
-NA,"dibenz(a,h)anthracene","304A","Human Health","1.2E-4","H",NA,NA,"W","g/l"
-NA,"dibenz(a,h)anthracene","304A","Human Health","1.3E-4","H",NA,NA,"O","g/l"
-NA,"3-methyl-4-chlorophenol","304A","Human Health","500","H",NA,NA,"W","g/l"
-NA,"3-methyl-4-chlorophenol","304A","Human Health","2000","H",NA,NA,"O","g/l"
-NA,"p,p'-dichlorodiphenyldichloroethane (ddd)","304A","Human Health","1.2E-4","H",NA,NA,"W","g/l"
-NA,"p,p'-dichlorodiphenyldichloroethane (ddd)","304A","Human Health","1.2E-4","H",NA,NA,"O","g/l"
-NA,"p,p'-dichlorodiphenyldichloroethylene (dde)","304A","Human Health","1.8E-5","H",NA,NA,"W","g/l"
-NA,"p,p'-dichlorodiphenyldichloroethylene (dde)","304A","Human Health","1.8E-5","H",NA,NA,"O","g/l"
-NA,"p,p'-dichlorodiphenyltrichloroethane (ddt)","304A","Human Health","3.0E-5","H",NA,NA,"W","g/l"
-NA,"p,p'-dichlorodiphenyltrichloroethane (ddt)","304A","Human Health","3.0E-5","H",NA,NA,"O","g/l"
-NA,"acenaphthene","304A","Organoleptic","20","O",NA,NA,NA,"g/l"
-NA,"color","304A","Organoleptic","See note","O",NA,NA,NA,"g/l"
-NA,"iron","304A","Organoleptic","300","O",NA,NA,NA,"g/l"
-NA,"monochlorobenzene","304A","Organoleptic","20","O",NA,NA,NA,"g/l"
-NA,"tainting substances","304A","Organoleptic","See note","O",NA,NA,NA,"g/l"
-NA,"3-chlorophenol","304A","Organoleptic","0.1","O",NA,NA,NA,"g/l"
-NA,"4-chlorophenol","304A","Organoleptic","0.1","O",NA,NA,NA,"g/l"
-NA,"2,3-dichlorophenol","304A","Organoleptic","0.04","O",NA,NA,NA,"g/l"
-NA,"2,5-dichlorophenol","304A","Organoleptic","0.5","O",NA,NA,NA,"g/l"
-NA,"2,6-dichlorophenol","304A","Organoleptic","0.2","O",NA,NA,NA,"g/l"
-NA,"3,4-dichlorophenol","304A","Organoleptic","0.3","O",NA,NA,NA,"g/l"
-NA,"2,4,5-trichlorophenol","304A","Organoleptic","1","O",NA,NA,NA,"g/l"
-NA,"2,4,6-trichlorophenol","304A","Organoleptic","2","O",NA,NA,NA,"g/l"
-NA,"2,3,4,6-tetrachlorophenol","304A","Organoleptic","1","O",NA,NA,NA,"g/l"
-NA,"2-methyl-4-chlorophenol","304A","Organoleptic","1800","O",NA,NA,NA,"g/l"
-NA,"3-methyl-4-chlorophenol","304A","Organoleptic","3000","O",NA,NA,NA,"g/l"
-NA,"3-methyl-6-chlorophenol","304A","Organoleptic","20","O",NA,NA,NA,"g/l"
-NA,"2-chlorophenol","304A","Organoleptic","0.1","O",NA,NA,NA,"g/l"
-"COPPER","copper","304A","Organoleptic","1000","O",NA,NA,NA,"g/l"
-NA,"2,4-dichlorophenol","304A","Organoleptic","0.3","O",NA,NA,NA,"g/l"
+NA,"aldrin","304A","Aquatic Life","3.0","A","F","A",NA,"µg/l"
+NA,"aldrin","304A","Aquatic Life","1.3","A","S","A",NA,"µg/l"
+NA,"alkalinity","304A","Aquatic Life","20000","A","F","C",NA,"µg/l"
+NA,"alpha-endosulfan","304A","Aquatic Life","0.22","A","F","A",NA,"µg/l"
+NA,"alpha-endosulfan","304A","Aquatic Life","0.056","A","F","C",NA,"µg/l"
+NA,"alpha-endosulfan","304A","Aquatic Life","0.034","A","S","A",NA,"µg/l"
+NA,"dichlorobromomethane","304A","Human Health","0.95","H",NA,NA,"W","µg/l"
+NA,"dichlorobromomethane","304A","Human Health","27","H",NA,NA,"O","µg/l"
+NA,"dieldrin","304A","Human Health","1.2E-6","H",NA,NA,"W","µg/l"
+NA,"dieldrin","304A","Human Health","1.2E-6","H",NA,NA,"O","µg/l"
+NA,"diethyl phthalate","304A","Human Health","600","H",NA,NA,"W","µg/l"
+NA,"diethyl phthalate","304A","Human Health","600","H",NA,NA,"O","µg/l"
+NA,"dimethyl phthalate","304A","Human Health","2000","H",NA,NA,"W","µg/l"
+NA,"dimethyl phthalate","304A","Human Health","2000","H",NA,NA,"O","µg/l"
+"LEAD","lead","304A","Aquatic Life","65","A","F","A",NA,"µg/l"
+"LEAD","lead","304A","Aquatic Life","2.5","A","F","C",NA,"µg/l"
+"LEAD","lead","304A","Aquatic Life","210","A","S","A",NA,"µg/l"
+"LEAD","lead","304A","Aquatic Life","8.1","A","S","C",NA,"µg/l"
+NA,"dibenz(a,h)anthracene","304A","Human Health","1.2E-4","H",NA,NA,"W","µg/l"
+NA,"dibenz(a,h)anthracene","304A","Human Health","1.3E-4","H",NA,NA,"O","µg/l"
+NA,"3-methyl-4-chlorophenol","304A","Human Health","500","H",NA,NA,"W","µg/l"
+NA,"3-methyl-4-chlorophenol","304A","Human Health","2000","H",NA,NA,"O","µg/l"
+NA,"p,p'-dichlorodiphenyldichloroethane (ddd)","304A","Human Health","1.2E-4","H",NA,NA,"W","µg/l"
+NA,"p,p'-dichlorodiphenyldichloroethane (ddd)","304A","Human Health","1.2E-4","H",NA,NA,"O","µg/l"
+NA,"p,p'-dichlorodiphenyldichloroethylene (dde)","304A","Human Health","1.8E-5","H",NA,NA,"W","µg/l"
+NA,"p,p'-dichlorodiphenyldichloroethylene (dde)","304A","Human Health","1.8E-5","H",NA,NA,"O","µg/l"
+NA,"p,p'-dichlorodiphenyltrichloroethane (ddt)","304A","Human Health","3.0E-5","H",NA,NA,"W","µg/l"
+NA,"p,p'-dichlorodiphenyltrichloroethane (ddt)","304A","Human Health","3.0E-5","H",NA,NA,"O","µg/l"
+NA,"acenaphthene","304A","Organoleptic","20","O",NA,NA,NA,"µg/l"
+NA,"color","304A","Organoleptic","See note","O",NA,NA,NA,"µg/l"
+NA,"iron","304A","Organoleptic","300","O",NA,NA,NA,"µg/l"
+NA,"monochlorobenzene","304A","Organoleptic","20","O",NA,NA,NA,"µg/l"
+NA,"tainting substances","304A","Organoleptic","See note","O",NA,NA,NA,"µg/l"
+NA,"3-chlorophenol","304A","Organoleptic","0.1","O",NA,NA,NA,"µg/l"
+NA,"4-chlorophenol","304A","Organoleptic","0.1","O",NA,NA,NA,"µg/l"
+NA,"2,3-dichlorophenol","304A","Organoleptic","0.04","O",NA,NA,NA,"µg/l"
+NA,"2,5-dichlorophenol","304A","Organoleptic","0.5","O",NA,NA,NA,"µg/l"
+NA,"2,6-dichlorophenol","304A","Organoleptic","0.2","O",NA,NA,NA,"µg/l"
+NA,"3,4-dichlorophenol","304A","Organoleptic","0.3","O",NA,NA,NA,"µg/l"
+NA,"2,4,5-trichlorophenol","304A","Organoleptic","1","O",NA,NA,NA,"µg/l"
+NA,"2,4,6-trichlorophenol","304A","Organoleptic","2","O",NA,NA,NA,"µg/l"
+NA,"2,3,4,6-tetrachlorophenol","304A","Organoleptic","1","O",NA,NA,NA,"µg/l"
+NA,"2-methyl-4-chlorophenol","304A","Organoleptic","1800","O",NA,NA,NA,"µg/l"
+NA,"3-methyl-4-chlorophenol","304A","Organoleptic","3000","O",NA,NA,NA,"µg/l"
+NA,"3-methyl-6-chlorophenol","304A","Organoleptic","20","O",NA,NA,NA,"µg/l"
+NA,"2-chlorophenol","304A","Organoleptic","0.1","O",NA,NA,NA,"µg/l"
+"COPPER","copper","304A","Organoleptic","1000","O",NA,NA,NA,"µg/l"
+NA,"2,4-dichlorophenol","304A","Organoleptic","0.3","O",NA,NA,NA,"µg/l"
NA,"carbaryl","304A","Aquatic Life","1.6","A","S","A",NA,"no unit name"
-"CADMIUM","cadmium","304A","Aquatic Life","1.8","A","F","A",NA,"g/l"
-"CADMIUM","cadmium","304A","Aquatic Life","0.72","A","F","C",NA,"g/l"
-"CADMIUM","cadmium","304A","Aquatic Life","33","A","S","A",NA,"g/l"
-"CADMIUM","cadmium","304A","Aquatic Life","7.9","A","S","C",NA,"g/l"
-NA,"chlordane","304A","Aquatic Life","2.4","A","F","A",NA,"g/l"
-NA,"chlordane","304A","Aquatic Life","0.0043","A","F","C",NA,"g/l"
-NA,"chlordane","304A","Aquatic Life","0.09","A","S","A",NA,"g/l"
-NA,"chlordane","304A","Aquatic Life","0.0040","A","S","C",NA,"g/l"
-NA,"chloride","304A","Aquatic Life","860000","A","F","A",NA,"g/l"
-NA,"chloride","304A","Aquatic Life","230000","A","F","C",NA,"g/l"
-NA,"vinyl chloride","304A","Human Health","0.022","H",NA,NA,"W","g/l"
-NA,"vinyl chloride","304A","Human Health","1.6","H",NA,NA,"O","g/l"
-"ZINC","zinc","304A","Human Health","7400","H",NA,NA,"W","g/l"
-"ZINC","zinc","304A","Human Health","26000","H",NA,NA,"O","g/l"
-NA,"1,1,1-trichloroethane","304A","Human Health","10000","H",NA,NA,"W","g/l"
-NA,"1,1,2,2-tetrachloroethane","304A","Human Health","0.2","H",NA,NA,"W","g/l"
-NA,"1,1,2,2-tetrachloroethane","304A","Human Health","3","H",NA,NA,"O","g/l"
-NA,"1,1,2-trichloroethane","304A","Human Health","0.55","H",NA,NA,"W","g/l"
-NA,"1,1,2-trichloroethane","304A","Human Health","8.9","H",NA,NA,"O","g/l"
-NA,"1,1-dichloroethylene","304A","Human Health","300","H",NA,NA,"W","g/l"
-NA,"acenaphthene","304A","Human Health","70","H",NA,NA,"W","g/l"
-NA,"acenaphthene","304A","Human Health","90","H",NA,NA,"O","g/l"
-NA,"acrolein","304A","Human Health","3","H",NA,NA,"W","g/l"
-NA,"acrolein","304A","Human Health","400","H",NA,NA,"O","g/l"
-NA,"acrylonitrile","304A","Human Health","0.061","H",NA,NA,"W","g/l"
-NA,"acrylonitrile","304A","Human Health","7.0","H",NA,NA,"O","g/l"
-NA,"aldrin","304A","Human Health","7.7E-7","H",NA,NA,"W","g/l"
-NA,"aldrin","304A","Human Health","7.7E-7","H",NA,NA,"O","g/l"
-NA,"alpha-hexachlorocyclohexane (hch)","304A","Human Health","3.6E-4","H",NA,NA,"W","g/l"
-NA,"alpha-hexachlorocyclohexane (hch)","304A","Human Health","3.9E-4","H",NA,NA,"O","g/l"
-NA,"alpha-endosulfan","304A","Human Health","20","H",NA,NA,"W","g/l"
-NA,"alpha-endosulfan","304A","Human Health","30","H",NA,NA,"O","g/l"
-NA,"anthracene","304A","Human Health","300","H",NA,NA,"W","g/l"
-NA,"anthracene","304A","Human Health","400","H",NA,NA,"O","g/l"
-NA,"antimony","304A","Human Health","5.6","H",NA,NA,"W","g/l"
-NA,"antimony","304A","Human Health","640","H",NA,NA,"O","g/l"
-NA,"di-n-butyl phthalate","304A","Human Health","20","H",NA,NA,"W","g/l"
-NA,"di-n-butyl phthalate","304A","Human Health","30","H",NA,NA,"O","g/l"
-NA,"dinitrophenols","304A","Human Health","10","H",NA,NA,"W","g/l"
-NA,"dinitrophenols","304A","Human Health","1000","H",NA,NA,"O","g/l"
-NA,"endosulfan sulfate","304A","Human Health","20","H",NA,NA,"W","g/l"
-NA,"endosulfan sulfate","304A","Human Health","40","H",NA,NA,"O","g/l"
-NA,"endrin","304A","Human Health","0.03","H",NA,NA,"W","g/l"
-NA,"endrin","304A","Human Health","0.03","H",NA,NA,"O","g/l"
-NA,"endrin aldehyde","304A","Human Health","1","H",NA,NA,"W","g/l"
-NA,"endrin aldehyde","304A","Human Health","1","H",NA,NA,"O","g/l"
-NA,"bis(chloromethyl) ether","304A","Human Health","1.5E-4","H",NA,NA,"W","g/l"
-NA,"bis(chloromethyl) ether","304A","Human Health","0.017","H",NA,NA,"O","g/l"
-NA,"ethylbenzene","304A","Human Health","68","H",NA,NA,"W","g/l"
-NA,"ethylbenzene","304A","Human Health","130","H",NA,NA,"O","g/l"
-NA,"fluoranthene","304A","Human Health","20","H",NA,NA,"W","g/l"
-NA,"fluoranthene","304A","Human Health","20","H",NA,NA,"O","g/l"
-NA,"fluorene","304A","Human Health","50","H",NA,NA,"W","g/l"
-NA,"fluorene","304A","Human Health","70","H",NA,NA,"O","g/l"
-NA,"gamma-hexachlorocyclohexane (hch) (lindane)","304A","Human Health","4.2","H",NA,NA,"W","g/l"
-NA,"gamma-hexachlorocyclohexane (hch) (lindane)","304A","Human Health","4.4","H",NA,NA,"O","g/l"
-NA,"heptachlor","304A","Human Health","5.9E-6","H",NA,NA,"W","g/l"
-NA,"heptachlor","304A","Human Health","5.9E-6","H",NA,NA,"O","g/l"
-NA,"heptachlor epoxide","304A","Human Health","3.2E-5","H",NA,NA,"W","g/l"
-NA,"heptachlor epoxide","304A","Human Health","3.2E-5","H",NA,NA,"O","g/l"
-NA,"hexachlorobenzene","304A","Human Health","7.9E-5","H",NA,NA,"W","g/l"
-NA,"hexachlorobenzene","304A","Human Health","7.9E-5","H",NA,NA,"O","g/l"
-NA,"hexachlorobutadiene","304A","Human Health","0.01","H",NA,NA,"W","g/l"
-NA,"hexachlorobutadiene","304A","Human Health","0.01","H",NA,NA,"O","g/l"
-NA,"hexachlorocyclohexane (hch)-technical","304A","Human Health","0.0066","H",NA,NA,"W","g/l"
-NA,"pathogen and pathogen indicators","304A","Human Health","See EPA's 2012 Recreational Water Quality Criteria","H",NA,NA,"O","g/l"
-NA,"pentachlorobenzene","304A","Human Health","0.1","H",NA,NA,"W","g/l"
-NA,"pentachlorobenzene","304A","Human Health","0.1","H",NA,NA,"O","g/l"
-NA,"pentachlorophenol","304A","Human Health","0.03","H",NA,NA,"W","g/l"
-NA,"pentachlorophenol","304A","Human Health","0.04","H",NA,NA,"O","g/l"
+"CADMIUM","cadmium","304A","Aquatic Life","1.8","A","F","A",NA,"µg/l"
+"CADMIUM","cadmium","304A","Aquatic Life","0.72","A","F","C",NA,"µg/l"
+"CADMIUM","cadmium","304A","Aquatic Life","33","A","S","A",NA,"µg/l"
+"CADMIUM","cadmium","304A","Aquatic Life","7.9","A","S","C",NA,"µg/l"
+NA,"chlordane","304A","Aquatic Life","2.4","A","F","A",NA,"µg/l"
+NA,"chlordane","304A","Aquatic Life","0.0043","A","F","C",NA,"µg/l"
+NA,"chlordane","304A","Aquatic Life","0.09","A","S","A",NA,"µg/l"
+NA,"chlordane","304A","Aquatic Life","0.0040","A","S","C",NA,"µg/l"
+NA,"chloride","304A","Aquatic Life","860000","A","F","A",NA,"µg/l"
+NA,"chloride","304A","Aquatic Life","230000","A","F","C",NA,"µg/l"
+NA,"vinyl chloride","304A","Human Health","0.022","H",NA,NA,"W","µg/l"
+NA,"vinyl chloride","304A","Human Health","1.6","H",NA,NA,"O","µg/l"
+"ZINC","zinc","304A","Human Health","7400","H",NA,NA,"W","µg/l"
+"ZINC","zinc","304A","Human Health","26000","H",NA,NA,"O","µg/l"
+NA,"1,1,1-trichloroethane","304A","Human Health","10000","H",NA,NA,"W","µg/l"
+NA,"1,1,2,2-tetrachloroethane","304A","Human Health","0.2","H",NA,NA,"W","µg/l"
+NA,"1,1,2,2-tetrachloroethane","304A","Human Health","3","H",NA,NA,"O","µg/l"
+NA,"1,1,2-trichloroethane","304A","Human Health","0.55","H",NA,NA,"W","µg/l"
+NA,"1,1,2-trichloroethane","304A","Human Health","8.9","H",NA,NA,"O","µg/l"
+NA,"1,1-dichloroethylene","304A","Human Health","300","H",NA,NA,"W","µg/l"
+NA,"acenaphthene","304A","Human Health","70","H",NA,NA,"W","µg/l"
+NA,"acenaphthene","304A","Human Health","90","H",NA,NA,"O","µg/l"
+NA,"acrolein","304A","Human Health","3","H",NA,NA,"W","µg/l"
+NA,"acrolein","304A","Human Health","400","H",NA,NA,"O","µg/l"
+NA,"acrylonitrile","304A","Human Health","0.061","H",NA,NA,"W","µg/l"
+NA,"acrylonitrile","304A","Human Health","7.0","H",NA,NA,"O","µg/l"
+NA,"aldrin","304A","Human Health","7.7E-7","H",NA,NA,"W","µg/l"
+NA,"aldrin","304A","Human Health","7.7E-7","H",NA,NA,"O","µg/l"
+NA,"alpha-hexachlorocyclohexane (hch)","304A","Human Health","3.6E-4","H",NA,NA,"W","µg/l"
+NA,"alpha-hexachlorocyclohexane (hch)","304A","Human Health","3.9E-4","H",NA,NA,"O","µg/l"
+NA,"alpha-endosulfan","304A","Human Health","20","H",NA,NA,"W","µg/l"
+NA,"alpha-endosulfan","304A","Human Health","30","H",NA,NA,"O","µg/l"
+NA,"anthracene","304A","Human Health","300","H",NA,NA,"W","µg/l"
+NA,"anthracene","304A","Human Health","400","H",NA,NA,"O","µg/l"
+NA,"antimony","304A","Human Health","5.6","H",NA,NA,"W","µg/l"
+NA,"antimony","304A","Human Health","640","H",NA,NA,"O","µg/l"
+NA,"di-n-butyl phthalate","304A","Human Health","20","H",NA,NA,"W","µg/l"
+NA,"di-n-butyl phthalate","304A","Human Health","30","H",NA,NA,"O","µg/l"
+NA,"dinitrophenols","304A","Human Health","10","H",NA,NA,"W","µg/l"
+NA,"dinitrophenols","304A","Human Health","1000","H",NA,NA,"O","µg/l"
+NA,"endosulfan sulfate","304A","Human Health","20","H",NA,NA,"W","µg/l"
+NA,"endosulfan sulfate","304A","Human Health","40","H",NA,NA,"O","µg/l"
+NA,"endrin","304A","Human Health","0.03","H",NA,NA,"W","µg/l"
+NA,"endrin","304A","Human Health","0.03","H",NA,NA,"O","µg/l"
+NA,"endrin aldehyde","304A","Human Health","1","H",NA,NA,"W","µg/l"
+NA,"endrin aldehyde","304A","Human Health","1","H",NA,NA,"O","µg/l"
+NA,"bis(chloromethyl) ether","304A","Human Health","1.5E-4","H",NA,NA,"W","µg/l"
+NA,"bis(chloromethyl) ether","304A","Human Health","0.017","H",NA,NA,"O","µg/l"
+NA,"ethylbenzene","304A","Human Health","68","H",NA,NA,"W","µg/l"
+NA,"ethylbenzene","304A","Human Health","130","H",NA,NA,"O","µg/l"
+NA,"fluoranthene","304A","Human Health","20","H",NA,NA,"W","µg/l"
+NA,"fluoranthene","304A","Human Health","20","H",NA,NA,"O","µg/l"
+NA,"fluorene","304A","Human Health","50","H",NA,NA,"W","µg/l"
+NA,"fluorene","304A","Human Health","70","H",NA,NA,"O","µg/l"
+NA,"gamma-hexachlorocyclohexane (hch) (lindane)","304A","Human Health","4.2","H",NA,NA,"W","µg/l"
+NA,"gamma-hexachlorocyclohexane (hch) (lindane)","304A","Human Health","4.4","H",NA,NA,"O","µg/l"
+NA,"heptachlor","304A","Human Health","5.9E-6","H",NA,NA,"W","µg/l"
+NA,"heptachlor","304A","Human Health","5.9E-6","H",NA,NA,"O","µg/l"
+NA,"heptachlor epoxide","304A","Human Health","3.2E-5","H",NA,NA,"W","µg/l"
+NA,"heptachlor epoxide","304A","Human Health","3.2E-5","H",NA,NA,"O","µg/l"
+NA,"hexachlorobenzene","304A","Human Health","7.9E-5","H",NA,NA,"W","µg/l"
+NA,"hexachlorobenzene","304A","Human Health","7.9E-5","H",NA,NA,"O","µg/l"
+NA,"hexachlorobutadiene","304A","Human Health","0.01","H",NA,NA,"W","µg/l"
+NA,"hexachlorobutadiene","304A","Human Health","0.01","H",NA,NA,"O","µg/l"
+NA,"hexachlorocyclohexane (hch)-technical","304A","Human Health","0.0066","H",NA,NA,"W","µg/l"
+NA,"pathogen and pathogen indicators","304A","Human Health","See EPA's 2012 Recreational Water Quality Criteria","H",NA,NA,"O","µg/l"
+NA,"pentachlorobenzene","304A","Human Health","0.1","H",NA,NA,"W","µg/l"
+NA,"pentachlorobenzene","304A","Human Health","0.1","H",NA,NA,"O","µg/l"
+NA,"pentachlorophenol","304A","Human Health","0.03","H",NA,NA,"W","µg/l"
+NA,"pentachlorophenol","304A","Human Health","0.04","H",NA,NA,"O","µg/l"
"PH","pH (acidity/alkalinity)","304A","Human Health","5-9","H",NA,NA,"W","no unit name"
-NA,"phenol","304A","Human Health","4000","H",NA,NA,"W","g/l"
-NA,"phenol","304A","Human Health","300000","H",NA,NA,"O","g/l"
-NA,"polychlorinated biphenyls (pcbs)","304A","Human Health","6.4E-5","H",NA,NA,"W","g/l"
-NA,"polychlorinated biphenyls (pcbs)","304A","Human Health","6.4E-5","H",NA,NA,"O","g/l"
-NA,"pyrene","304A","Human Health","20","H",NA,NA,"W","g/l"
-NA,"pyrene","304A","Human Health","30","H",NA,NA,"O","g/l"
-"SELENIUM","selenium","304A","Human Health","170","H",NA,NA,"W","g/l"
-"SELENIUM","selenium","304A","Human Health","4200","H",NA,NA,"O","g/l"
-NA,"solids dissolved and salinity","304A","Human Health","250000","H",NA,NA,"W","g/l"
-NA,"1,2,4,5-tetrachlorobenzene","304A","Human Health","0.03","H",NA,NA,"W","g/l"
-NA,"arsenic","304A","Human Health","0.018","H",NA,NA,"W","g/l"
-NA,"arsenic","304A","Human Health","0.14","H",NA,NA,"O","g/l"
+NA,"phenol","304A","Human Health","4000","H",NA,NA,"W","µg/l"
+NA,"phenol","304A","Human Health","300000","H",NA,NA,"O","µg/l"
+NA,"polychlorinated biphenyls (pcbs)","304A","Human Health","6.4E-5","H",NA,NA,"W","µg/l"
+NA,"polychlorinated biphenyls (pcbs)","304A","Human Health","6.4E-5","H",NA,NA,"O","µg/l"
+NA,"pyrene","304A","Human Health","20","H",NA,NA,"W","µg/l"
+NA,"pyrene","304A","Human Health","30","H",NA,NA,"O","µg/l"
+"SELENIUM","selenium","304A","Human Health","170","H",NA,NA,"W","µg/l"
+"SELENIUM","selenium","304A","Human Health","4200","H",NA,NA,"O","µg/l"
+NA,"solids dissolved and salinity","304A","Human Health","250000","H",NA,NA,"W","µg/l"
+NA,"1,2,4,5-tetrachlorobenzene","304A","Human Health","0.03","H",NA,NA,"W","µg/l"
+NA,"arsenic","304A","Human Health","0.018","H",NA,NA,"W","µg/l"
+NA,"arsenic","304A","Human Health","0.14","H",NA,NA,"O","µg/l"
NA,"asbestos","304A","Human Health","7000000","H",NA,NA,"W","fibers/l"
-NA,"barium","304A","Human Health","1000","H",NA,NA,"W","g/l"
-NA,"chlorine","304A","Aquatic Life","19","A","F","A",NA,"g/l"
-NA,"chlorine","304A","Aquatic Life","11","A","F","C",NA,"g/l"
-NA,"chlorine","304A","Aquatic Life","13","A","S","A",NA,"g/l"
-NA,"chlorine","304A","Aquatic Life","7.5","A","S","C",NA,"g/l"
-NA,"chloropyrifos","304A","Aquatic Life","0.083","A","F","A",NA,"g/l"
-NA,"chloropyrifos","304A","Aquatic Life","0.041","A","F","C",NA,"g/l"
-NA,"chloropyrifos","304A","Aquatic Life","0.011","A","S","A",NA,"g/l"
-NA,"chloropyrifos","304A","Aquatic Life","0.0056","A","S","C",NA,"g/l"
-"CHROMIUM(III)","chromium (iii)","304A","Aquatic Life","570","A","F","A",NA,"g/l"
-"CHROMIUM(III)","chromium (iii)","304A","Aquatic Life","74","A","F","C",NA,"g/l"
-"CHROMIUM(VI)","chromium (vi)","304A","Aquatic Life","16","A","F","A",NA,"g/l"
-"CHROMIUM(VI)","chromium (vi)","304A","Aquatic Life","11","A","F","C",NA,"g/l"
-"CHROMIUM(VI)","chromium (vi)","304A","Aquatic Life","1100","A","S","A",NA,"g/l"
-"CHROMIUM(VI)","chromium (vi)","304A","Aquatic Life","50","A","S","C",NA,"