diff --git a/R/Utilities.R b/R/Utilities.R index 00fc2a2f7..23e2c6172 100644 --- a/R/Utilities.R +++ b/R/Utilities.R @@ -872,6 +872,20 @@ TADA_ConvertSpecialChars <- function( clean.data <- TADA_OrderCols(clean.data) } + # Flag result values that do not have an associated result unit + if ( + col %in% + c("ResultMeasureValue", "TADA.ResultMeasureValue") && + "TADA.ResultMeasure.MeasureUnitCode" %in% names(clean.data) + ) { + clean.data[[flagcol]] <- ifelse( + is.na(clean.data$TADA.ResultMeasure.MeasureUnitCode) | + trimws(clean.data$TADA.ResultMeasure.MeasureUnitCode) == "", + "No unit associated with result value", + clean.data[[flagcol]] + ) + } + if (flaggedonly == FALSE) { if (clean == TRUE) { clean.data <- clean.data |> @@ -886,6 +900,20 @@ TADA_ConvertSpecialChars <- function( ) ) + # Remove records with missing result units when cleaning result values + if ( + col %in% + c("ResultMeasureValue", "TADA.ResultMeasureValue") && + "TADA.ResultMeasure.MeasureUnitCode" %in% names(clean.data) + ) { + clean.data <- clean.data |> + dplyr::filter( + !is.na(TADA.ResultMeasure.MeasureUnitCode), + # trimws incorporates " " into this as well as "" + trimws(TADA.ResultMeasure.MeasureUnitCode) != "" + ) + } + return(clean.data) } @@ -903,6 +931,7 @@ TADA_ConvertSpecialChars <- function( "Text", "Non-ASCII Character(s)", "Result Value/Unit Cannot Be Estimated From Detection Limit", + "No unit associated with result value", "Coerced to NA" ) ) diff --git a/tests/testthat/test-Utilities.R b/tests/testthat/test-Utilities.R index 01f5fe7aa..3a812b70c 100644 --- a/tests/testthat/test-Utilities.R +++ b/tests/testthat/test-Utilities.R @@ -38,6 +38,27 @@ test_that("Column names do not contain the pattern 'TADA.TADA.'", { ) }) +test_that("TADA_ConvertSpecialChars removes missing result units when clean is TRUE", { + testdat <- TADA_RandomTestingData() + + # Ensure the test includes both NA and blank result units + testdat$TADA.ResultMeasure.MeasureUnitCode[1] <- NA_character_ + testdat$TADA.ResultMeasure.MeasureUnitCode[2] <- "" + + result <- TADA_ConvertSpecialChars( + testdat, + col = "TADA.ResultMeasureValue", + clean = TRUE + ) + + expect_true(is.numeric(result$TADA.ResultMeasureValue)) + expect_false(any(is.na(result$TADA.ResultMeasureValue))) + + expect_false(any(is.na(result$TADA.ResultMeasure.MeasureUnitCode))) + + expect_false(any(result$TADA.ResultMeasure.MeasureUnitCode == "")) +}) + test_that("Column names do not contain the pattern 'TADA.TADA.'", { test_TADA.TADA. <- TADA_AutoClean(Data_R5_TADAPackageDemo) # Create a logical vector indicating which columns contain the pattern @@ -50,6 +71,106 @@ test_that("Column names do not contain the pattern 'TADA.TADA.'", { ) }) +test_that("TADA_ConvertSpecialChars removes rows with missing result units when clean = TRUE", { + testdat <- Data_Nutrients_UT[1:4, ] + + testdat$ResultMeasureValue <- c("1.2", "2.3", "3.4", "4.5") + testdat$ResultMeasure.MeasureUnitCode <- c("mg/L", NA_character_, "", "ug/L") + + result <- TADA_ConvertSpecialChars( + testdat, + col = "ResultMeasureValue", + clean = TRUE + ) + + # Rows with NA or blank result units should be removed + expect_equal(nrow(result), 2) + + # Confirm that the correct converted values remain + expect_equal(result$TADA.ResultMeasureValue, c(1.2, 4.5)) + + expect_equal(result$TADA.ResultMeasure.MeasureUnitCode, c("MG/L", "UG/L")) + + # Confirm the output columns have the expected types and values + expect_true(is.numeric(result$TADA.ResultMeasureValue)) + expect_false(any(is.na(result$TADA.ResultMeasureValue))) + + expect_false(any(is.na(result$TADA.ResultMeasure.MeasureUnitCode))) + + expect_false(any(result$TADA.ResultMeasure.MeasureUnitCode == "")) +}) + +test_that("TADA_ConvertSpecialChars flags rows with missing result units when clean = FALSE", { + testdat <- Data_Nutrients_UT[1:5, ] + + testdat$ResultMeasureValue <- c("1.2", "2.3", "3.4", "4.5", "5.6") + testdat$ResultMeasure.MeasureUnitCode <- c( + "mg/L", + NA_character_, + "", + " ", + "ug/L" + ) + + result <- TADA_ConvertSpecialChars( + testdat, + col = "ResultMeasureValue", + clean = FALSE + ) + + # No rows should be removed + expect_equal(nrow(result), 5) + + # Confirm all result values are converted and retained + expect_equal(result$TADA.ResultMeasureValue, c(1.2, 2.3, 3.4, 4.5, 5.6)) + + # Confirm missing, blank, and whitespace-only units receive the new flag + expect_equal( + result$TADA.ResultMeasureValueDataTypes.Flag, + c( + "Numeric", + "No unit associated with result value", + "No unit associated with result value", + "No unit associated with result value", + "Numeric" + ) + ) + + # Confirm result values remain numeric + expect_true(is.numeric(result$TADA.ResultMeasureValue)) + expect_false(any(is.na(result$TADA.ResultMeasureValue))) +}) + +test_that("TADA_ConvertSpecialChars returns missing-unit rows when flaggedonly = TRUE", { + testdat <- Data_Nutrients_UT[1:5, ] + + testdat$ResultMeasureValue <- c("1.2", "2.3", "3.4", "4.5", "5.6") + testdat$ResultMeasure.MeasureUnitCode <- c( + "mg/L", + NA_character_, + "", + " ", + "ug/L" + ) + + result <- TADA_ConvertSpecialChars( + testdat, + col = "ResultMeasureValue", + flaggedonly = TRUE + ) + + # Only rows with missing, blank, or whitespace-only units should remain + expect_equal(nrow(result), 3) + + # Confirm the expected result values are returned + expect_equal(result$TADA.ResultMeasureValue, c(2.3, 3.4, 4.5)) + + # Confirm all returned rows have the missing-unit flag + expect_true(all( + result$TADA.ResultMeasureValueDataTypes.Flag == + "No unit associated with result value" + )) +}) test_that("Only numeric data remains after running TADA_ConvertSpecialChars clean = TRUE", { testdat <- TADA_RandomTestingData(