From b36d6b281d7d4e7116592ccb02c460fd4cbc5b08 Mon Sep 17 00:00:00 2001 From: Ron Keizer Date: Wed, 1 Apr 2026 10:53:00 -0700 Subject: [PATCH] Ensure AMT is always coerced to numeric in get_initial_estimates_from_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Uses as.numeric(as.character()) to handle character and factor AMT columns correctly — as.numeric(factor) returns level codes, not values. Co-Authored-By: Claude Sonnet 4.6 --- DESCRIPTION | 2 +- R/get_initial_estimates_from_data.R | 2 + .../test-get_initial_estimates_from_data.R | 61 +++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index a1eb597..df092ab 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: pharmr.extra Title: Extension of pharmr (Pharmpy) functionality -Version: 0.0.0.9032 +Version: 0.0.0.9033 Authors@R: c( person("Ron", "Keizer", email = "ron@insight-rx.com", role = c("cre", "aut")), person("Michael", "McCarthy", email = "michael.mccarthy@insight-rx.com", role = "ctb"), diff --git a/R/get_initial_estimates_from_data.R b/R/get_initial_estimates_from_data.R index e35854f..821d005 100644 --- a/R/get_initial_estimates_from_data.R +++ b/R/get_initial_estimates_from_data.R @@ -29,6 +29,7 @@ get_initial_estimates_from_data <- function( suppressWarnings( data <- data |> dplyr::mutate( + AMT = as.numeric(as.character(.data$AMT)), DV = as.numeric(.data$DV), TIME = as.numeric(.data$TIME) ) |> @@ -134,6 +135,7 @@ get_initial_estimates_from_individual_data <- function( est$V <- dose / max(obs$DV, na.rm=TRUE) est$CL <- KEL * est$V } else { # more crude estimation + if(length(tmp$DV) > 0) { est$V <- dose / (max(tmp$DV, na.rm=TRUE) * 5) est$CL <- est$V / 10 diff --git a/tests/testthat/test-get_initial_estimates_from_data.R b/tests/testthat/test-get_initial_estimates_from_data.R index 8ca39da..2630e32 100644 --- a/tests/testthat/test-get_initial_estimates_from_data.R +++ b/tests/testthat/test-get_initial_estimates_from_data.R @@ -258,3 +258,64 @@ test_that("get_initial_estimates_from_data errors on non-existent CSV file", { "`data` file does not exist" ) }) + +test_that("get_initial_estimates_from_data works when AMT is character", { + test_data <- data.frame( + ID = c(1, 1, 1, 1), + TIME = c(0, 1, 4, 8), + DV = c(0, 100, 50, 25), + EVID = c(1, 0, 0, 0), + MDV = c(1, 0, 0, 0), + AMT = c("1000", "0", "0", "0"), + stringsAsFactors = FALSE + ) + + result <- get_initial_estimates_from_data(test_data, n_cmt = 1) + + expect_type(result, "list") + expect_named(result, c("V", "CL")) + expect_true(all(result > 0)) + expect_equal(result$V, 10, tolerance = 0.1) +}) + +test_that("get_initial_estimates_from_data works when AMT is factor", { + test_data <- data.frame( + ID = c(1, 1, 1, 1), + TIME = c(0, 1, 4, 8), + DV = c(0, 100, 50, 25), + EVID = c(1, 0, 0, 0), + MDV = c(1, 0, 0, 0), + AMT = factor(c("1000", "0", "0", "0")) + ) + + result <- get_initial_estimates_from_data(test_data, n_cmt = 1) + + expect_type(result, "list") + expect_named(result, c("V", "CL")) + expect_true(all(result > 0)) + expect_equal(result$V, 10, tolerance = 0.1) +}) + +test_that("get_initial_estimates_from_data gives same result regardless of AMT column type", { + base_data <- data.frame( + ID = c(1, 1, 1, 1), + TIME = c(0, 1, 4, 8), + DV = c(0, 100, 50, 25), + EVID = c(1, 0, 0, 0), + MDV = c(1, 0, 0, 0), + AMT = c(1000, 0, 0, 0) + ) + + result_numeric <- get_initial_estimates_from_data(base_data, n_cmt = 1) + result_character <- get_initial_estimates_from_data( + transform(base_data, AMT = as.character(AMT)), n_cmt = 1 + ) + result_factor <- get_initial_estimates_from_data( + transform(base_data, AMT = as.factor(AMT)), n_cmt = 1 + ) + + expect_equal(result_numeric$V, result_character$V, tolerance = 1e-6) + expect_equal(result_numeric$CL, result_character$CL, tolerance = 1e-6) + expect_equal(result_numeric$V, result_factor$V, tolerance = 1e-6) + expect_equal(result_numeric$CL, result_factor$CL, tolerance = 1e-6) +})