pharmaverse / admiral

ADaM in R Asset Library
https://pharmaverse.github.io/admiral
Apache License 2.0
222 stars 64 forks source link

Bug: derive_advs_params functions not populating AVALU and derive_param_bsa also not populating PARAM #960

Closed esimms999-gsk closed 2 years ago

esimms999-gsk commented 2 years ago

What happened?

I ran the example code in the Help for each of derive_param_map(), derive_param_bmi() and derive_param_bsa() and noticed that AVALU was not being populated.

For the derive_advs_params.R derivations (MAP, BMI, BSA), the AVALU is NA. Since PARAM for MAP is "Mean Arterial Pressure (mmHg)", I guess the AVALU should be "mmHg" and since the PARAM for BMI is "Body Mass Index (kg/m^2)", I guess the AVALU should be "kg/m^2".

As for BSA, both the PARAM and AVALU are NA. I think the unit for BSA is M^2, but I cannot figure out how that can be since the formula for Mosteller is sqrt[height(cm) * weight(kg) / 3600 ] which should give a unit of ... cm^0.5kg^0.5 ???? This will need some research.

Session Information

> sessionInfo()
R version 3.6.3 (2020-02-29)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252    LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C                           LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices datasets  utils     methods   base     

other attached packages:
[1] dplyr_0.8.5   admiral_0.5.0

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.3       rstudioapi_0.11  magrittr_1.5     tidyselect_1.0.0 R6_2.4.1         rlang_0.4.10     fansi_0.4.1     
 [8] stringr_1.4.0    tools_3.6.3      xfun_0.12        tinytex_0.20     utf8_1.1.4       cli_3.1.1        assertthat_0.2.1
[15] tibble_2.1.3     crayon_1.3.4     purrr_0.3.3      tidyr_0.8.3      vctrs_0.3.8      glue_1.3.1       stringi_1.4.6   
[22] compiler_3.6.3   pillar_1.4.3     lubridate_1.7.4  renv_0.13.0      pkgconfig_2.0.3 

Reproducible Example

Run the example code in the help file for each of derive_param_map, bmi, bsa. For example:

> library(admiral)
> library(dplyr, warn.conflicts = FALSE)
> advs <- tibble::tribble(
+   ~USUBJID,      ~PARAMCD, ~PARAM,                            ~AVAL, ~AVALU,      ~VISIT,
+   "01-701-1015", "PULSE",  "Pulse (beats/min)"              ,  59,   "beats/min", "BASELINE",
+   "01-701-1015", "PULSE",  "Pulse (beats/min)"              ,  61,   "beats/min", "WEEK 2",
+   "01-701-1015", "DIABP",  "Diastolic Blood Pressure (mmHg)",  51,   "mmHg",      "BASELINE",
+   "01-701-1015", "DIABP",  "Diastolic Blood Pressure (mmHg)",  50,   "mmHg",      "WEEK 2",
+   "01-701-1015", "SYSBP",  "Systolic Blood Pressure (mmHg)",  121,   "mmHg",      "BASELINE",
+   "01-701-1015", "SYSBP",  "Systolic Blood Pressure (mmHg)",  121,   "mmHg",      "WEEK 2",
+   "01-701-1028", "PULSE",  "Pulse (beats/min)"              ,  62,   "beats/min", "BASELINE",
+   "01-701-1028", "PULSE",  "Pulse (beats/min)"              ,  77,   "beats/min", "WEEK 2",
+   "01-701-1028", "DIABP",  "Diastolic Blood Pressure (mmHg)",  79,   "mmHg",      "BASELINE",
+   "01-701-1028", "DIABP",  "Diastolic Blood Pressure (mmHg)",  80,   "mmHg",      "WEEK 2",
+   "01-701-1028", "SYSBP",  "Systolic Blood Pressure (mmHg)",  130,   "mmHg",      "BASELINE",
+   "01-701-1028", "SYSBP",  "Systolic Blood Pressure (mmHg)",  132,   "mmHg",      "WEEK 2"
+ )
> # Derive MAP based on diastolic and systolic blood pressure
> advs %>%
+   derive_param_map(
+     by_vars = vars(USUBJID, VISIT),
+     set_values_to = vars(
+       PARAMCD = "MAP",
+       PARAM = "Mean Arterial Pressure (mmHg)"
+     ),
+     get_unit_expr = AVALU
+   ) %>%
+   filter(PARAMCD != "PULSE")
# A tibble: 12 x 6
   USUBJID     PARAMCD PARAM                            AVAL AVALU VISIT   
   <chr>       <chr>   <chr>                           <dbl> <chr> <chr>   
 1 01-701-1015 DIABP   Diastolic Blood Pressure (mmHg)  51   mmHg  BASELINE
 2 01-701-1015 DIABP   Diastolic Blood Pressure (mmHg)  50   mmHg  WEEK 2  
 3 01-701-1015 SYSBP   Systolic Blood Pressure (mmHg)  121   mmHg  BASELINE
 4 01-701-1015 SYSBP   Systolic Blood Pressure (mmHg)  121   mmHg  WEEK 2  
 5 01-701-1028 DIABP   Diastolic Blood Pressure (mmHg)  79   mmHg  BASELINE
 6 01-701-1028 DIABP   Diastolic Blood Pressure (mmHg)  80   mmHg  WEEK 2  
 7 01-701-1028 SYSBP   Systolic Blood Pressure (mmHg)  130   mmHg  BASELINE
 8 01-701-1028 SYSBP   Systolic Blood Pressure (mmHg)  132   mmHg  WEEK 2  
 9 01-701-1015 MAP     Mean Arterial Pressure (mmHg)    74.3 NA    BASELINE
10 01-701-1015 MAP     Mean Arterial Pressure (mmHg)    73.7 NA    WEEK 2  
11 01-701-1028 MAP     Mean Arterial Pressure (mmHg)    96   NA    BASELINE
12 01-701-1028 MAP     Mean Arterial Pressure (mmHg)    97.3 NA    WEEK 2 
thomas-neitmann commented 2 years ago

I don't see the issue. In the call to the derive_param_*() functions you did not specify set_values_to = vars(AVALU = "something") so it's expected that you get NA for that.

If this is confusing we can remove the AVALU column from the example dataset.

bundfussr commented 2 years ago

In the first example (for derive_param_map()) I would add AVALU = "mmHg" to set_values_to because if there is a unit variable in the input data, it should be populated for the new observations.

In the second example I would remove AVALU from the input dataset because it is not used and the output looks inconsistent.

I think the intention of the first example is to show how to call the function if the unit is stored in a separate variable. The second example shows the call for the case that the unit is available in PARAM only.

The same applies to derive_param_bsa() and derive_param_bmi(). For derive_param_bsa() we should populate PARAM for the new observations or remove it from the input dataset.

bms63 commented 2 years ago

Nice job on using the Bug Report!!

So this is more of a documentation issue and less of a bug? Was thinking we should apply the documentation label??

esimms999-gsk commented 2 years ago

I am confused about what the get_unit_expr parameter is supposed to be doing. From the example in the derive_param_bmi Help page:

advs <- tibble::tribble( ~USUBJID, ~PARAMCD, ~PARAM, ~AVAL, ~AVALU, ~AVISIT, "01-701-1015", "HEIGHT", "Height (cm)", 147, "cm", "SCREENING", "01-701-1015", "WEIGHT", "Weight (kg)", 54.0, "kg", "SCREENING", "01-701-1015", "WEIGHT", "Weight (kg)", 54.4, "kg", "BASELINE", "01-701-1015", "WEIGHT", "Weight (kg)", 53.1, "kg", "WEEK 2", "01-701-1028", "HEIGHT", "Height (cm)", 163, "cm", "SCREENING", "01-701-1028", "WEIGHT", "Weight (kg)", 78.5, "kg", "SCREENING", "01-701-1028", "WEIGHT", "Weight (kg)", 80.3, "kg", "BASELINE", "01-701-1028", "WEIGHT", "Weight (kg)", 80.7, "kg", "WEEK 2" )

derive_param_bmi ( advs, by_vars = vars(USUBJID, AVISIT), weight_code = "WEIGHT", height_code = "HEIGHT", set_values_to = vars( PARAMCD = "BMI", PARAM = "Body Mass Index (kg/m^2)" ), get_unit_expr = extract_unit(PARAM) )

A tibble: 10 x 6 USUBJID PARAMCD PARAM AVAL AVALU AVISIT

1 01-701-1015 HEIGHT Height (cm) 147 cm SCREENING 2 01-701-1015 WEIGHT Weight (kg) 54 kg SCREENING 3 01-701-1015 WEIGHT Weight (kg) 54.4 kg BASELINE 4 01-701-1015 WEIGHT Weight (kg) 53.1 kg WEEK 2 5 01-701-1028 HEIGHT Height (cm) 163 cm SCREENING 6 01-701-1028 WEIGHT Weight (kg) 78.5 kg SCREENING 7 01-701-1028 WEIGHT Weight (kg) 80.3 kg BASELINE 8 01-701-1028 WEIGHT Weight (kg) 80.7 kg WEEK 2 9 01-701-1015 BMI Body Mass Index (kg/m^2) 25.0 NA SCREENING 10 01-701-1028 BMI Body Mass Index (kg/m^2) 29.5 NA SCREENING The Help explanation for the get_unit_expr parameter: **get_unit_expr An expression providing the unit of the parameter The result is used to check the units of the input parameters. Permitted Values: A variable of the input dataset or a function call** In this case I think that get_unit_expr is "kg/m^2". But how will this be "used to check the units of the input parameters"?
thomas-neitmann commented 2 years ago

get_unit_expr() is either a constant like "kg" or an expression that extracts the unit from some exisiting variable in the dataset, in the example PARAM. Here it pulls out "kg" from WEIGHT and "cm" for HEIGHT. It is then checked whether these input units match the expected ones.

esimms999-gsk commented 2 years ago

Thanks for explaining the get_unit_expr(), Thomas!

I changed the labels from "bug", "programming" to "ADVS", "documentation". I made use of R 3.6.3 to make the following changes:

In derive_advs_params.R: