diff --git a/DESCRIPTION b/DESCRIPTION index a56269d1..8d15f491 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -47,9 +47,11 @@ Imports: vctrs, readr, glue, + DT, pillar Suggests: knitr, + htmltools, lifecycle, magrittr, rmarkdown, diff --git a/NAMESPACE b/NAMESPACE index 73351b8a..00ec575c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -17,6 +17,7 @@ export(derive_seq) export(derive_study_day) export(domain_example) export(fmt_cmp) +export(generate_oak_id_vars) export(hardcode_ct) export(hardcode_no_ct) export(oak_id_vars) @@ -31,5 +32,6 @@ importFrom(pillar,tbl_sum) importFrom(rlang,"%||%") importFrom(rlang,":=") importFrom(rlang,.data) +importFrom(rlang,exprs) importFrom(stats,na.omit) importFrom(tibble,tibble) diff --git a/R/dataset_oak_vignette.R b/R/dataset_oak_vignette.R new file mode 100644 index 00000000..ef8e1769 --- /dev/null +++ b/R/dataset_oak_vignette.R @@ -0,0 +1,84 @@ +#' Output a Dataset in a Vignette in the sdtm.oak Format +#' +#' Output a dataset in a vignette with the pre-specified sdtm.oak format. +#' +#' @param dataset Dataset to output in the vignette +#' +#' @param display_vars Variables selected to demonstrate the outcome of the mapping +#' +#' Permitted Values: list of variables +#' +#' Default is NULL +#' +#' If `display_vars` is not NULL, only the selected variables are visible in the vignette while the +#' other variables are hidden. They can be made visible by clicking the`Choose the columns to +#' display` button. +#' +#' @param filter Filter condition +#' +#' The specified condition is applied to the dataset before it is displayed. +#' +#' Permitted Values: a condition +#' +#' @return A HTML table +#' +#' @keywords dev_utility +#' @importFrom rlang exprs +#' +#' @keywords internal +#' +dataset_oak_vignette <- function(dataset, display_vars = NULL, filter = NULL) { + filter <- admiraldev::assert_filter_cond(rlang::enexpr(filter), optional = TRUE) + + out <- dataset |> + admiraldev::filter_if(filter) |> + dplyr::mutate(dplyr::across(dplyr::where(is.character), as.factor)) + + # Create a short markdown table when this function is called outside {pkgdown} + if (!identical(Sys.getenv("IN_PKGDOWN"), "true")) { + if (is.null(display_vars)) { + return(knitr::kable(utils::head(out, 10L))) + } else { + return(knitr::kable(utils::head(dplyr::select(out, !!!display_vars), 10L))) + } + } + + if (!is.null(display_vars)) { + hide_columns <- which(!(colnames(out) %in% admiraldev::vars2chr(display_vars))) + cols_to_hide <- list(list(targets = hide_columns - 1L, visible = FALSE)) + } else { + cols_to_hide <- list() + } + htmltools::tagList( + htmltools::htmlDependency( + name = "dt-scroll", + version = "1.0.0", + src = "www", + stylesheet = "style.css", + package = "sdtm.oak" + ), + DT::datatable( + out, + rownames = FALSE, + filter = "top", + height = "auto", + width = "auto", + extensions = c("Buttons", "ColReorder", "Scroller"), + options = list( + columnDefs = cols_to_hide, + searchHighlight = TRUE, + searching = TRUE, + pageLength = 5L, + lengthMenu = c(5L, 10L, 15L, 20L, 50L, 100L), + dom = "ipl>", + buttons = list(list( + extend = "colvis", + text = "Choose the columns to display", + scroller = TRUE, + collectionLayout = "fixed two-column" + )), + colReorder = TRUE + ) + ) + ) +} diff --git a/R/derive_study_day.R b/R/derive_study_day.R index 6a04c15c..679beb46 100644 --- a/R/derive_study_day.R +++ b/R/derive_study_day.R @@ -94,6 +94,10 @@ derive_study_day <- function(sdtm_in, ) } + # convert to character to verify the iso format + sdtm_in[[refdt]] <- as.character(sdtm_in[[refdt]]) + sdtm_in[[tgdt]] <- as.character(sdtm_in[[tgdt]]) + # refdt/tgdt should be in ISO format, otherwise throw warning sdtm_in[[refdt]] <- tryCatch( as.Date(sdtm_in[[refdt]], "%Y-%m-%d"), @@ -104,7 +108,7 @@ derive_study_day <- function(sdtm_in, e$message, call. = FALSE ) - NA + sdtm_in[[refdt]] } ) sdtm_in[[tgdt]] <- tryCatch( @@ -116,12 +120,12 @@ derive_study_day <- function(sdtm_in, e$message, call. = FALSE ) - NA + sdtm_in[[tgdt]] } ) - ref <- sdtm_in[[refdt]] - tgt <- sdtm_in[[tgdt]] + ref <- as.Date(sdtm_in[[refdt]]) + tgt <- as.Date(sdtm_in[[tgdt]]) # SDTMIG 4.4.4 Use of the Study Day Variables res <- ifelse(tgt >= ref, tgt - ref + 1L, tgt - ref) diff --git a/R/oak_id_vars.R b/R/oak_id_vars.R index c88007f8..19ef3323 100644 --- a/R/oak_id_vars.R +++ b/R/oak_id_vars.R @@ -51,3 +51,48 @@ contains_oak_id_vars <- function(x) { admiraldev::assert_character_vector(x) all(oak_id_vars() %in% x) } + + +#' A function to generate oak_id_vars +#' +#' @param raw_dat The raw dataset (dataframe) +#' @param pat_var Variable that holds the patient number +#' @param raw_src Name of the raw source +#' +#' @return dataframe +#' @export +#' +#' @examples +#' raw_dataset <- +#' tibble::tribble( +#' ~patnum, ~MDRAW, +#' 101L, "BABY ASPIRIN", +#' 102L, "CORTISPORIN", +#' 103L, NA_character_, +#' 104L, "DIPHENHYDRAMINE HCL" +#' ) +#' +#' # Generate oak_id_vars +#' generate_oak_id_vars( +#' raw_dat = raw_dataset, +#' pat_var = "patnum", +#' raw_src = "Concomitant Medication" +#' ) +generate_oak_id_vars <- function(raw_dat, + pat_var, + raw_src) { + admiraldev::assert_character_scalar(pat_var) + admiraldev::assert_character_scalar(raw_src) + admiraldev::assert_data_frame(raw_dat) + admiraldev::assert_data_frame(raw_dat, required_vars = rlang::syms(pat_var)) + + raw_oak_id_vars <- raw_dat |> + dplyr::mutate( + oak_id = structure(seq_len(nrow(raw_dat))), + patient_number = !!rlang::sym(pat_var), + raw_source = raw_src + ) |> + dplyr::select(oak_id_vars(), dplyr::everything()) + + return(raw_oak_id_vars) +} diff --git a/_pkgdown.yml b/_pkgdown.yml index fd45e961..5da2e0a4 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -8,8 +8,8 @@ navbar: title: "sdtm.oak" reference: -- title: SDTM derivation - desc: Toolkit for SDTM derivations +- title: SDTM Mapping Algorithms/functions + desc: Set of functions to perform SDTM Mappings contents: - assign - harcode @@ -54,3 +54,6 @@ reference: - title: Package global state contents: - clear_cache + - generate_oak_id_vars + - oak_id_vars + - %.>% diff --git a/inst/WORDLIST b/inst/WORDLIST index 70830c44..8cbf012d 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -32,3 +32,31 @@ Immunogenicity Pharmacokinetics iRECIST pharmaversesdtm +pre +CMGRPID +CMMODIFY +CMSTRTPT +CMSTTPT +CMTRT +CRF +datetime +DIABP +eCRF +eDT +hardcode +hardcoding +MDBDR +MDBTM +MDEDR +MDETM +MDR +MDRAW +mmm +NonCRF +OID +OXYSAT +px +SYS +SYSBP +VSALL +yyyy diff --git a/inst/cm_domain/cm_sdtm.csv b/inst/cm_domain/cm_sdtm.csv deleted file mode 100644 index 6fe047db..00000000 --- a/inst/cm_domain/cm_sdtm.csv +++ /dev/null @@ -1,7 +0,0 @@ -STUDYID,DOMAIN,USUBJID,CMSEQ,CMGRPID,CMREFID,CMSPID,CMTRT,CMMODIFY,CMDECOD,CMCAT,CMPRESP,CMOCCUR,CMINDC,CMDOSE,CMDOSTXT,CMDOSU,CMDOSFRM,CMDOSFRQ,CMROUTE,VISITNUM,VISIT,VISITDY,EPOCH,CMDTC,CMSTDTC,CMENDTC,CMDY,CMSTDY,CMENDY,CMSTRTPT,CMSTTPT,CMENRTPT,CMENTPT,CMPROPH,CMDRG,CMDRGCD,CMPNCD -LPSTUDY,CM,LPSTUDY-375,1,NA,NA,/F:VACHX-D:56379540-R:1,TETANUS,NA,NA,VACCINATION HISTORY,Y,Y,NA,NA,NA,NA,NA,NA,NA,1,Screening,-8,SCREENING,2020-09-01,2019-02-02,NA,-27,-604,NA,NA,NA,NA,NA,NA,NA,NA,NA -LPSTUDY,CM,LPSTUDY-375,2,NA,NA,/F:VACHX-D:56379540-R:2,COVID-19,NA,NA,VACCINATION HISTORY,Y,Y,NA,NA,NA,NA,NA,NA,NA,1,Screening,-8,SCREENING,2020-09-01,2020-08-31,NA,-27,-28,NA,NA,NA,NA,NA,NA,NA,NA,NA -LPSTUDY,CM,LPSTUDY-375,3,NA,NA,/F:VACHX-D:56379540-R:3,FLU,NA,NA,VACCINATION HISTORY,NA,NA,NA,NA,NA,NA,NA,NA,NA,1,Screening,-8,SCREENING,2020-09-01,NA,NA,-27,NA,NA,BEFORE,SCREENING,NA,NA,NA,NA,NA,NA -LPSTUDY,CM,LPSTUDY-375,4,1,5652739,/F:MD1-D:56379253-R:1,BABY ASPIRIN,NA,ACETYLSALICYLIC ACID,NA,NA,NA,NA,10,NA,mg,TABLET,QD,ORAL,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,BEFORE,SCREENING,ONGOING,DATE OF LAST ASSESSMENT,NA,BABY ASPIRIN,00002701701,00002701001 -LPSTUDY,CM,LPSTUDY-375,5,2,5533807,/F:MD1-D:56379253-R:2,CORTISPORIN,CORTISPORIN (UNITED STATES),CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,NA,NA,NA,NAUSEA,50,NA,g,PILL,NA,ORAL,NA,NA,NA,SCREENING,NA,2020-09-15,NA,NA,-13,NA,NA,NA,ONGOING,DATE OF LAST ASSESSMENT,NA,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,90104001001,90104001001 -LPSTUDY,CM,LPSTUDY-378,1,3,4537684,/F:MD1-D:63059916-R:3,TETRACYCLINE,NA,TETRACYCLINE,NA,NA,NA,FEVER,10,NA,mg,CAPSULE,BID,TRANSDERMAL,NA,NA,NA,TREATMENT,NA,2020-02-12T12:12,2020-02-18,NA,18,24,BEFORE,SCREENING,NA,NA,Y,TETRACYCLINE,00001701001,00001701001 diff --git a/inst/cm_domain/cm_sdtm_oak_ct.csv b/inst/cm_domain/cm_sdtm_oak_ct.csv deleted file mode 100644 index bf231e7e..00000000 --- a/inst/cm_domain/cm_sdtm_oak_ct.csv +++ /dev/null @@ -1,35 +0,0 @@ -codelist_code,term_code,CodedData,term_value,collected_value,term_preferred_term,term_synonyms,raw_codelist -C71113,C25473,QD,QD,QD (Every Day),Daily,/day; Daily; Per Day,FREQ_CV1 -C71113,C64496,BID,BID,BID (Twice a Day),Twice Daily,BD; Twice per day,FREQ_CV1 -C71113,C64499,PRN,PRN,PRN (As Needed),As Needed,As needed,FREQ_CV1 -C71113,C64516,Q2H,Q2H,Q2H (Every 2 Hours),Every Two Hours,Every 2 hours,FREQ_CV1 -C71113,C64530,QID,QID,QID (4 Times a Day),Four Times Daily,4 times per day,FREQ_CV1 -C66726,C25158,CAPSULE,CAPSULE,Capsule,Capsule Dosage Form,cap,FRM_CV1 -C66726,C25394,PILL,PILL,Pill,Pill Dosage Form,NA,FRM_CV1 -C66726,C29167,LOTION,LOTION,Lotion,Lotion Dosage Form,NA,FRM_CV1 -C66726,C42887,AEROSOL,AEROSOL,Aerosol,Aerosol Dosage Form,aer,FRM_CV1 -C66726,C42944,INHALANT,INHALANT,Inhalant,Inhalant Dosage Form,NA,FRM_CV1 -C66726,C42946,INJECTION,INJECTION,Injection,Injectable Dosage Form,NA,FRM_CV1 -C66726,C42953,LIQUID,LIQUID,Liquid,Liquid Dosage Form,NA,FRM_CV1 -C66726,C42998,TABLET,TABLET,Tablet,Tablet Dosage Form,tab,FRM_CV1 -C66742,C49488,Y,Y,Yes,Yes,Yes,NY_CV1 -C66729,C28161,INTRAMUSCULAR,INTRAMUSCULAR,IM (Intramuscular),Intramuscular Route of Administration,NA,ROUTE_CV1 -C66729,C38210,EPIDURAL,EPIDURAL,EP (Epidural),Epidural Route of Administration,NA,ROUTE_CV1 -C66729,C38222,INTRA-ARTERIAL,INTRA-ARTERIAL,IA (Intra-arterial),Intraarterial Route of Administration,NA,ROUTE_CV1 -C66729,C38223,INTRA-ARTICULAR,INTRA-ARTICULAR,IJ (Intra-articular),Intraarticular Route of Administration,NA,ROUTE_CV1 -C66729,C38287,OPHTHALMIC,OPHTHALMIC,OP (Ophthalmic),Ophthalmic Route of Administration,NA,ROUTE_CV1 -C66729,C38288,ORAL,ORAL,PO (Oral),Oral Route of Administration,Intraoral Route of Administration; PO,ROUTE_CV1 -C66729,C38305,TRANSDERMAL,TRANSDERMAL,DE (Transdermal),Transdermal Route of Administration,NA,ROUTE_CV1 -C66729,C38311,UNKNOWN,UNKNOWN,Unknown,Unknown Route of Administration,NA,ROUTE_CV1 -C71620,C25613,%,%,%,Percentage,Percentage,UNIT_CV1 -C71620,C28253,MG,mg,mg,Milligram,Milligram,UNIT_CV1 -C71620,C28254,ML,mL,mL,Milliliter,cm3; Milliliter,UNIT_CV1 -C71620,C48155,G,g,g,Gram,Gram,UNIT_CV1 -C71620,C48480,CAPSULE,CAPSULE,Capsule,Capsule Dosing Unit,cap; Capsule Dosing Unit,UNIT_CV1 -C71620,C48542,TABLET,TABLET,Tablet,Tablet Dosing Unit,tab; Tablet Dosing Unit,UNIT_CV1 -C71620,C48579,IU,IU,IU,International Unit,IE; International Unit,UNIT_CV1 -C71620,C28254,ML,mL,mL,Milliliter,cm3; Milliliter,UNIT_CV5 -C66728,C25629,BEFORE,BEFORE,Prior,Prior,,NA -C66728,C53279,ONGOING,ONGOING,Continue,Continue,Continuous,NA -C66734,C49568,CM,CM,Concomitant Medication Domain,Concomitant Medication Domain,Concomitant/Prior Medications,NA -,,,,,,, \ No newline at end of file diff --git a/inst/cm_domain/create_cm_template.R b/inst/cm_domain/create_cm_template.R deleted file mode 100644 index 346f5909..00000000 --- a/inst/cm_domain/create_cm_template.R +++ /dev/null @@ -1,233 +0,0 @@ -# Name: CM domain -# -# Label: R program to create CM Domain -# -# Input raw data: -# study_sdtm_spec -# study_controlled_terminology -# study_raw_datasets -# -# - -library(sdtm.oak) -library(dplyr) - -# Read Specification - -sdtm_spec <- read_(filename = "~/inst/cm_domain/cm_sdtm_oak_spec.csv") - -study_ct <- read_study_ct(filename = "~/inst/cm_domain/cm_sdtm_oak_ct.csv") - -# Read in raw data - -cm_raw_data <- read_raw_data_csv(filename = "~/inst/cm_domain/cm_raw_data.csv") |> - # Derive oak_id_vars - derive_oak_id_vars() - -# Create CM domain. The first step in creating CM domain is to create the topic variable - -cm <- cm_daw_data |> - # Derive topic variable - assign_no_ct( - raw_dataset = MD1, # This is added for pseudocode. Not required as pipe will send it - raw_variable = MDRAW, - target_sdtm_var = CMTRT - ) |> - # Derive qualifier CMDOSU - # Use merge and add the qualifier to the topic variable - assign_ct( - raw_dataset = MD1, - raw_variable = DOSU, - target_sdtm_var = CMDOSU, - study_ct = study_ct, - target_sdtm_variable_codelist_code = "C71620", - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # Derive qualifier CMDOSFRM and merge it with the target dataset - assign_ct( - raw_dataset = MD1, - raw_variable = MDFORM, - target_sdtm_var = CMDOSFRM, - target_sdtm_variable_codelist_code = "C66726", - study_ct = study_ct, - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # DERIVE CMROUTE - assign_ct( - raw_dataset = MD1, - raw_variable = MDFORM, - target_sdtm_var = MDRTE, - target_sdtm_variable_codelist_code = "C66729", - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # DERIVE CMDOSFRQ - assign_ct( - raw_dataset = MD1, - raw_variable = MDFRQ, - target_sdtm_var = CMDOSFRQ, - target_sdtm_variable_codelist_code = "C71113", - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # DERIVE CMINDC - assign_no_ct( - raw_dataset = MD1, - raw_variable = MDIND, - target_sdtm_var = CMINDC, - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # Derive qualifier CMDOSE. Annotation text = If numeric then CM.CMDOSE - if_then_else( - raw_dataset = MD1, - raw_variable = DOS, - condition_left_raw_dataset = MD1, - condition_left_raw_variable = DOS, - condition_operator = "is_numeric", - sub_algorithm = assign_no_ct, # pass the function as the argument - target_sdtm_var = CMDOSE, - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # Derive qualifier CMDOSTXT. Annotation text = If character then CM.CMDOSTXT - if_then_else( - raw_dataset = MD1, - raw_variable = DOS, - condition_left_raw_dataset = MD1, - condition_left_raw_variable = DOS, - condition_operator = "is_character", - sub_algorithm = assign_no_ct, - target_sdtm_var = CMDOSETXT, - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # Derive qualifier CMMODIFY Annotation text = If different to CM.CMTRT then CM.CMMODIFY - if_then_else( - raw_dataset = MD1, - raw_variable = CMMODIFY, - condition_left_raw_dataset = MD1, - condition_left_raw_variable = CMMODIFY, - condition_operator = "diffferent_to", - condition_right_sdtm_variable_domain = CM, - condition_right_sdtm_variable = CMTRT, - sub_algorithm = assign_no_ct, - target_sdtm_var = CMDOSETXT, - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # Derive CMDECOD - assign_no_ct( - raw_dataset = MD1, - raw_variable = CMDECOD, - target_sdtm_var = CMDECOD - ) |> - # Derive CMSTDTC. This function calls create_iso8601 - assign_no_ct( - raw_dataset = MD1, - raw_variable = c("MDBD", "MDBTM"), - target_sdtm_var = CMSTDTC, - .format = c("ddmmmyyyy", "HHMM") - ) |> - # Derive CMENDTC. This function calls create_iso8601 - assign_no_ct( - raw_dataset = MD1, - raw_variable = c("MDED", "MDETM"), - target_sdtm_var = CMENDTC, - .format = c("ddmmmyyyy", "HHMM") - ) |> - # Derive qualifier CMSTRTPT Annotation text = If checked then CM.CMSTRTPT = 'BEFORE' - if_then_else( - raw_dataset = MD1, - raw_variable = MDPRIOR, - condition_left_raw_dataset = MD1, - condition_left_raw_variable = MDPRIOR, - condition_operator = "if_checked", - sub_algorithm = assign_ct, - target_sdtm_variable_codelist_code = "C66728", - target_sdtm_var = CMSTRTPT, - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # Derive qualifier CMSTRTPT Annotation text = If checked then CM.CMSTTPT = 'SCREENING' - if_then_else( - raw_dataset = MD1, - raw_variable = MDPRIOR, - condition_left_raw_dataset = MD1, - condition_left_raw_variable = MDPRIOR, - condition_operator = "if_checked", - sub_algorithm = hardcode_no_ct, - target_hardcoded_value = "SCREENING", - target_sdtm_var = CM.CMSTTPT, - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # Derive qualifier CMENRTPT Annotation text = If checked then CM.CMENRTPT = 'ONGOING' - if_then_else( - raw_dataset = MD1, - raw_variable = MDONG, - condition_left_raw_dataset = MD1, - condition_left_raw_variable = MDONG, - condition_operator = "if_checked", - sub_algorithm = hardcode_ct, - target_hardcoded_value = "ONGOING", - target_sdtm_variable_codelist_code = "C66728", - target_sdtm_var = CMENRTPT, - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # Derive qualifier CMENTPT Annotation text = If checked then CM.CMENTPT = 'DATE OF LAST ASSESSMENT' - if_then_else( - raw_dataset = MD1, - raw_variable = MDONG, - condition_left_raw_dataset = MD1, - condition_left_raw_variable = MDONG, - condition_operator = "if_checked", - sub_algorithm = hardcode_no_ct, - target_hardcoded_value = "DATE OF LAST ASSESSMENT", - target_sdtm_var = CMENTPT, - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - # Derive CMGRPID - assign_no_ct( - raw_dataset = MD1, - raw_variable = MDNUM, - target_sdtm_var = CMGRPID, - merge_to_topic_by = c(oak_id_vars, - topic_var_source = MDRAW - ) - ) |> - dplyr::mutate( - STUDYID = "test_study", - DOMAIN = "CM", - CMCAT = "GENERAL CONMED" - ) |> - derive_usubjid() |> - derive_sequence(keys = c(USUBJID, CMTRT)) |> - derive_visit_visitnum() |> - calculate_study_day( - dm_domain = dm, - study_day_var = "RFSTDTS", - var_in = CMSTDTC, - target_var = CMSTDY, - merge_key = "USUBJID" - ) |> - derive_study_day( - var_in = CMENDTC, - target_var = CMENDY - ) diff --git a/inst/cm_domain/cm_raw_data.csv b/inst/raw_data/cm_raw_data.csv similarity index 93% rename from inst/cm_domain/cm_raw_data.csv rename to inst/raw_data/cm_raw_data.csv index 5ffc75bf..10390854 100644 --- a/inst/cm_domain/cm_raw_data.csv +++ b/inst/raw_data/cm_raw_data.csv @@ -1,15 +1,15 @@ -PATNUM,SUBJSTAT,SITENM,INSTANCE,INSTRN,FOLDER,FOLDERL,FOLDERSQ,FORM,FORML,DATAPGID,PGREPNUM,RECORDDT,RECORDID,RECPOS,RECSTAT,MDNUM,MDNUM_RAW,MDREC,MDRAW,MDIND,MDBDR,MDBDTU,MDBTM,MDBTMU,MDPRIOR,MDEDR,MDEDT,MDETM,MDETMU,MDONG,DOS,DOSU,DOSUV,MDFORM,MDRTE,MDFRQ,MDPROPH,TERMID,SRCLN,RAVRFID,CMMODIFY,CMDRG,CMDRGCD,CMDECOD,CMPNCD,SPLIT,OMIT,ACTTYP,ACTTEXT,CMDICT,CMCLAS,CMCLASCD,CMATC4,CMATC4CD,CMATC3,CMATC3CD,CMATC2,CMATC2CD,CMATC1,CMATC1CD,CLASSNUM -375,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56379253,0,,111885785,1,N,1,1,No,BABY ASPIRIN,,,1,,1,1,,,,0,1,10,mg,MG,Tablet,PO (Oral),QD (Every Day),0,109576058,20,5652739,BABY ASPIRIN,BABY ASPIRIN,2701701,ACETYLSALICYLIC ACID,2701001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,STOMATOLOGICAL PREPARATIONS,A01A,STOMATOLOGICAL PREPARATIONS,A01,ALIMENTARY TRACT AND METABOLISM,A,1 -375,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56379253,0,,111969387,2,N,2,2,No,CORTISPORIN,NAUSEA,15-Sep-20,0,,1,0,,,,0,1,50,g,G,Pill,PO (Oral),,0,105820348,28,5533807,CORTISPORIN (UNITED STATES),CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,90104001001,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,90104001001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,S03CA,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,S03CA,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,S03C,OPHTHALMOLOGICAL AND OTOLOGICAL PREPARATIONS,S03,SENSORY ORGANS,S,1 -376,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56407664,0,,111939965,1,N,1,1,No,ASPIRIN,ANEMIA,17-Feb-21,0,8:00,0,0,17-Feb-21,2/17/21,,0,0,,,,,,,0,80619660,8,4297014,ASPIRIN,ASPIRIN [ACETYLSALICYLIC ACID],2701004,ACETYLSALICYLIC ACID,2701001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,STOMATOLOGICAL PREPARATIONS,A01A,STOMATOLOGICAL PREPARATIONS,A01,ALIMENTARY TRACT AND METABOLISM,A,1 -377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,111942855,1,N,1,1,No,DIPHENHYDRAMINE HCL,NAUSEA,4-Oct-20,0,9:00,0,0,,,,0,1,50,mg,MG,Capsule,PO (Oral),BID (Twice a Day),0,79751919,3,4240092,DIPHENHYDRAMINE HCL,DIPHENHYDRAMINE HCL,402246,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 -377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,129972536,2,N,2,2,No,PARCETEMOL,PYREXIA,20-Jan-20,0,10:00,0,0,20-Jan-20,1/20/20,10:00,0,0,,mg,MG,Capsule,PO (Oral),BID (Twice a Day),1,129972536,2,,,,,,,,,,,,,,,,,,,,,, -377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,129972541,3,N,3,3,No,VOMIKIND,VOMITINGS,UN UNK 2019,1,,1,0,UN UNK 2019,6/15/19,,1,0,,Tablet,TABLET,,PO (Oral),PRN (As Needed),1,129972541,3,,,,,,,,,,,,,,,,,,,,,, -377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,129972568,4,N,5,5,No,ZENFLOX OZ,DIARHHEA,20 UNK 2019,0,10:00,0,0,20 UNK 2019,6/15/19,,1,0,,mL,ML,Injection,IM (Intramuscular),PRN (As Needed),1,129972568,4,,,,,,,,,,,,,,,,,,,,,, -378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472439,4,N,4,4,No,AMITRYPTYLINE,COLD,UN UNK 2020,0,,1,1,UN UNK 2020,6/15/20,,1,0,12,g,G,Inhalant,IA (Intra-arterial),QD (Every Day),0,81845879,6,4382628,AMITRIPTYLINE,AMITRIPTYLINE,2201001,AMITRIPTYLINE,2201001,,,SPELLING UPDATE,AMITRIPTYLINE,"WHODRUG GLOBAL B3 MARCH 1, 2021",DRUGS FOR URINARY FREQUENCY AND INCONTINENCE,G04BD,DRUGS FOR URINARY FREQUENCY AND INCONTINENCE,G04BD,UROLOGICALS,G04B,UROLOGICALS,G04,GENITO URINARY SYSTEM AND SEX HORMONES,G,1 -378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472436,1,N,1,1,No,BENADRYL,FEVER,26-Jan-20,0,9:00,0,0,26-Jan-20,1/26/20,7:00,0,0,100,mg,MG,Capsule,PO (Oral),BID (Twice a Day),1,95547017,4,5211852,BENADRYL (UNITED STATES),BENADRYL [DIPHENHYDRAMINE HYDROCHLORIDE],402002,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 -378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472437,2,N,2,2,Yes,DIPHENHYDRAMINE HYDROCHLORIDE,LEG PAIN,28-Jan-20,1,,1,1,1-Feb-20,2/1/20,,1,1,100,Capsule,CAPSULE,Capsule,Unknown,QD (Every Day),0,94095723,13,5084095,DIPHENHYDRAMINE HYDROCHLORIDE,DIPHENHYDRAMINE HYDROCHLORIDE,402001,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 -378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472438,3,N,3,3,Yes,TETRACYCLINE,FEVER,12-Feb-20,0,12:12,0,1,18-Feb-20,2/18/20,,0,0,10,mg,MG,Capsule,DE (Transdermal),BID (Twice a Day),1,84246445,6,4537684,TETRACYCLINE,TETRACYCLINE,1701001,TETRACYCLINE,1701001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",ANTIBIOTICS,S01AA,ANTIBIOTICS,S01AA,ANTIINFECTIVES,S01A,OPHTHALMOLOGICALS,S01,SENSORY ORGANS,S,1 -379,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059986,0,,126472565,3,N,1,1,No,BENADRYL,COLD,10 UNK 2020,0,,0,0,20 UNK 2020,6/15/20,,0,0,12,IU,IU,Lotion,IJ (Intra-articular), , ,84734661,12,4567194,BENADRYL (UNITED STATES),BENADRYL [DIPHENHYDRAMINE HYDROCHLORIDE],402002,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 -379,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059986,0,,126472563,1,N,2,2,No,SOMINEX,COLD,,1,,1,0,,,,1,1,,mL,ML,Liquid,EP (Epidural),PRN (As Needed),0,82746644,5,4580551,SOMINEX (UNITED STATES),SOMINEX [DIPHENHYDRAMINE HYDROCHLORIDE],402060,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 -379,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059986,0,,126472564,2,N,3,3,No,ZQUILL,PAIN,,1,,1,0,17-Feb-20,2/17/20,,1,0,5,%,%,Aerosol,OP (Ophthalmic),Q2H (Every 2 Hours),0,99707553,22,5330876,ZZZQUIL,ZZZQUIL,402326,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,SPELLING UPDATE,ZZZQUIL,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 \ No newline at end of file +PATNUM,SUBJSTAT,SITENM,INSTANCE,INSTRN,FOLDER,FOLDERL,FOLDERSQ,FORM,FORML,DATAPGID,PGREPNUM,RECORDDT,RECORDID,RECPOS,RECSTAT,MDNUM,MDNUM_RAW,MDREC,MDRAW,MDIND,MDBDR,MDBDTU,MDBTM,MDBTMU,MDPRIOR,MDEDR,MDEDT,MDETM,MDETMU,MDONG,DOS,DOSU,DOSUV,MDFORM,MDRTE,MDFRQ,MDPROPH,TERMID,SRCLN,RAVRFID,MODIFY,CMDRG,CMDRGCD,CMDECOD,CMPNCD,SPLIT,OMIT,ACTTYP,ACTTEXT,CMDICT,CMCLAS,CMCLASCD,CMATC4,CMATC4CD,CMATC3,CMATC3CD,CMATC2,CMATC2CD,CMATC1,CMATC1CD,CLASSNUM +375,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56379253,0,,111885785,1,N,1,1,No,BABY ASPIRIN,,,1,,1,1,,,,0,1,10,mg,MG,Tablet,PO (Oral),QD (Every Day),0,109576058,20,5652739,BABY ASPIRIN,BABY ASPIRIN,2701701,ACETYLSALICYLIC ACID,2701001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,STOMATOLOGICAL PREPARATIONS,A01A,STOMATOLOGICAL PREPARATIONS,A01,ALIMENTARY TRACT AND METABOLISM,A,1 +375,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56379253,0,,111969387,2,N,2,2,No,CORTISPORIN,NAUSEA,15-Sep-20,0,,1,0,,,,0,1,50,g,G,Pill,PO (Oral),,0,105820348,28,5533807,CORTISPORIN (UNITED STATES),CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,90104001001,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,90104001001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,S03CA,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,S03CA,CORTICOSTEROIDS AND ANTIINFECTIVES IN COMBINATION,S03C,OPHTHALMOLOGICAL AND OTOLOGICAL PREPARATIONS,S03,SENSORY ORGANS,S,1 +376,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56407664,0,,111939965,1,N,1,1,No,ASPIRIN,ANEMIA,17-Feb-21,0,8:00,0,0,17-Feb-21,2/17/21,,0,0,,,,,,,0,80619660,8,4297014,ASPIRIN,ASPIRIN [ACETYLSALICYLIC ACID],2701004,ACETYLSALICYLIC ACID,2701001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,OTHER AGENTS FOR LOCAL ORAL TREATMENT,A01AD,STOMATOLOGICAL PREPARATIONS,A01A,STOMATOLOGICAL PREPARATIONS,A01,ALIMENTARY TRACT AND METABOLISM,A,1 +377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,111942855,1,N,1,1,No,DIPHENHYDRAMINE HCL,NAUSEA,4-Oct-20,0,9:00,0,0,,,,0,1,50,mg,MG,Capsule,PO (Oral),BID (Twice a Day),0,79751919,3,4240092,DIPHENHYDRAMINE HCL,DIPHENHYDRAMINE HCL,402246,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 +377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,129972536,2,N,2,2,No,PARCETEMOL,PYREXIA,20-Jan-20,0,10:00,0,0,20-Jan-20,1/20/20,10:00,0,0,,mg,MG,Capsule,PO (Oral),BID (Twice a Day),1,129972536,2,,,,,,,,,,,,,,,,,,,,,, +377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,129972541,3,N,3,3,No,VOMIKIND,VOMITINGS,UN UNK 2019,1,,1,0,UN UNK 2019,6/15/19,,1,0,,Tablet,TABLET,,PO (Oral),PRN (As Needed),1,129972541,3,,,,,,,,,,,,,,,,,,,,,, +377,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,56408736,0,,129972568,4,N,5,5,No,ZENFLOX OZ,DIARHHEA,20 UNK 2019,0,10:00,0,0,20 UNK 2019,6/15/19,,1,0,,mL,ML,Injection,IM (Intramuscular),PRN (As Needed),1,129972568,4,,,,,,,,,,,,,,,,,,,,,, +378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472439,4,N,4,4,No,AMITRYPTYLINE,COLD,UN UNK 2020,0,,1,1,UN UNK 2020,6/15/20,,1,0,12,g,G,Inhalant,IA (Intra-arterial),QD (Every Day),0,81845879,6,4382628,AMITRIPTYLINE,AMITRIPTYLINE,2201001,AMITRIPTYLINE,2201001,,,SPELLING UPDATE,AMITRIPTYLINE,"WHODRUG GLOBAL B3 MARCH 1, 2021",DRUGS FOR URINARY FREQUENCY AND INCONTINENCE,G04BD,DRUGS FOR URINARY FREQUENCY AND INCONTINENCE,G04BD,UROLOGICALS,G04B,UROLOGICALS,G04,GENITO URINARY SYSTEM AND SEX HORMONES,G,1 +378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472436,1,N,1,1,No,BENADRYL,FEVER,26-Jan-20,0,9:00,0,0,26-Jan-20,1/26/20,7:00,0,0,100,mg,MG,Capsule,PO (Oral),BID (Twice a Day),1,95547017,4,5211852,BENADRYL (UNITED STATES),BENADRYL [DIPHENHYDRAMINE HYDROCHLORIDE],402002,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 +378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472437,2,N,2,2,Yes,DIPHENHYDRAMINE HYDROCHLORIDE,LEG PAIN,28-Jan-20,1,,1,1,1-Feb-20,2/1/20,,1,1,100,Capsule,CAPSULE,Capsule,Unknown,QD (Every Day),0,94095723,13,5084095,DIPHENHYDRAMINE HYDROCHLORIDE,DIPHENHYDRAMINE HYDROCHLORIDE,402001,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 +378,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059916,0,,126472438,3,N,3,3,Yes,TETRACYCLINE,FEVER,12-Feb-20,0,12:12,0,1,18-Feb-20,2/18/20,,0,0,10,mg,MG,Capsule,DE (Transdermal),BID (Twice a Day),1,84246445,6,4537684,TETRACYCLINE,TETRACYCLINE,1701001,TETRACYCLINE,1701001,,,,,"WHODRUG GLOBAL B3 MARCH 1, 2021",ANTIBIOTICS,S01AA,ANTIBIOTICS,S01AA,ANTIINFECTIVES,S01A,OPHTHALMOLOGICALS,S01,SENSORY ORGANS,S,1 +379,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059986,0,,126472565,3,N,1,1,No,BENADRYL,COLD,10 UNK 2020,0,,0,0,20 UNK 2020,6/15/20,,0,0,12,IU,IU,Lotion,IJ (Intra-articular), , ,84734661,12,4567194,BENADRYL (UNITED STATES),BENADRYL [DIPHENHYDRAMINE HYDROCHLORIDE],402002,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 +379,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059986,0,,126472563,1,N,2,2,No,SOMINEX,COLD,,1,,1,0,,,,1,1,,mL,ML,Liquid,EP (Epidural),PRN (As Needed),0,82746644,5,4580551,SOMINEX (UNITED STATES),SOMINEX [DIPHENHYDRAMINE HYDROCHLORIDE],402060,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,COUNTRY,APPLY SITE COUNTRY TO TERM,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 +379,Randomized,TEST SITE,Concomitant Medications,0,MD,Concomitant Medications,15,MD1,Concomitant Medications,63059986,0,,126472564,2,N,3,3,No,ZQUILL,PAIN,,1,,1,0,17-Feb-20,2/17/20,,1,0,5,%,%,Aerosol,OP (Ophthalmic),Q2H (Every 2 Hours),0,99707553,22,5330876,ZZZQUIL,ZZZQUIL,402326,DIPHENHYDRAMINE HYDROCHLORIDE,402001,,,SPELLING UPDATE,ZZZQUIL,"WHODRUG GLOBAL B3 MARCH 1, 2021",AMINOALKYL ETHERS,R06AA,AMINOALKYL ETHERS,R06AA,ANTIHISTAMINES FOR SYSTEMIC USE,R06A,ANTIHISTAMINES FOR SYSTEMIC USE,R06,RESPIRATORY SYSTEM,R,1 diff --git a/inst/cm_domain/cm_sdtm_oak_spec.csv b/inst/raw_data/cm_sdtm_oak_spec.csv similarity index 100% rename from inst/cm_domain/cm_sdtm_oak_spec.csv rename to inst/raw_data/cm_sdtm_oak_spec.csv diff --git a/inst/raw_data/dm.csv b/inst/raw_data/dm.csv new file mode 100644 index 00000000..5d58d228 --- /dev/null +++ b/inst/raw_data/dm.csv @@ -0,0 +1,6 @@ +"STUDYID","DOMAIN","USUBJID","SUBJID","RFSTDTC","RFENDTC","RFXSTDTC","RFXENDTC","RFICDTC","RFPENDTC","DTHDTC","DTHFL","SITEID","INVID","INVNAM","BRTHDTC","AGE","AGEU","SEX","RACE","ETHNIC","ARMCD","ARM","ACTARMCD","ACTARM","COUNTRY","DMDTC","DMDY","RACE1","RACE2","RACE3" +"test_study","DM","test_study-375","test_study-375","1999-04-14T08:36","2013-01-21","2023-04-14T08:36","2021-01-11T07:50","2007-01-15","2020-04-02","2020-04-02","Y","111111","90009","Dr doctor9",NA,NA,NA,"F","MULTIPLE",NA,NA,NA,NA,NA,"US",NA,NA,"NATIVE HAWAIIAN OR OTHER PACIFIC ISLANDER","WHITE",NA +"test_study","DM","test_study-376","test_study-376","2001-03-21","2007-05-21","2020-03-21","2017-09-14T18:49",NA,"2011-12-18","2011-12-18",NA,"111111","90009","Dr doctor9","1981-02-26T18:07",42,"YEARS","M","MULTIPLE","NOT HISPANIC OR LATINO",NA,NA,NA,NA,"US",NA,NA,"BLACK OR AFRICAN AMERICAN","AMERICAN INDIAN OR ALASKA NATIVE","UNKNOWN" +"test_study","DM","test_study-377","test_study-377","1999-03-14","2021-05-05","2020-03-14","2013-08-23T12:37","2015-10-07","2021-05-05","2019-06-29",NA,"111111","90009","Dr doctor9","1968-03-19T04:36",56,"YEARS",NA,"MULTIPLE","NOT REPORTED",NA,NA,NA,NA,"US",NA,NA,"ASIAN","AMERICAN INDIAN OR ALASKA NATIVE","UNKNOWN" +"test_study","DM","test_study-378","test_study-378","2003-02-06T06:33","2021-04-24T09:06","2021-02-06T06:33","2021-04-24T09:06","2018-10-20","2017-04-11","2017-04-11",NA,"111111","90009","Dr doctor9","1979-09-24",45,"YEARS","M","BLACK OR AFRICAN AMERICAN","HISPANIC OR LATINO",NA,NA,NA,NA,"US",NA,NA,NA,NA,NA +"test_study","DM","test_study-379","test_study-379","2003-02-06T06:33","2021-04-24T09:06","2022-02-06T06:33","2021-04-24T09:06","2018-10-20","2017-04-11","2017-04-11","Y","111111","90009","Dr doctor9","1963-09-24",61,"YEARS","M","BLACK OR AFRICAN AMERICAN","HISPANIC OR LATINO",NA,NA,NA,NA,"US",NA,NA,NA,NA,NA diff --git a/inst/raw_data/sdtm_ct.csv b/inst/raw_data/sdtm_ct.csv new file mode 100644 index 00000000..d078d6ed --- /dev/null +++ b/inst/raw_data/sdtm_ct.csv @@ -0,0 +1,75 @@ +codelist_code,term_code,term_value,collected_value,term_preferred_term,term_synonyms +C66726,C25158,CAPSULE,Capsule,Capsule Dosage Form,cap +C66726,C25394,PILL,Pill,Pill Dosage Form, +C66726,C29167,LOTION,Lotion,Lotion Dosage Form, +C66726,C42887,AEROSOL,Aerosol,Aerosol Dosage Form,aer +C66726,C42944,INHALANT,Inhalant,Inhalant Dosage Form, +C66726,C42946,INJECTION,Injection,Injectable Dosage Form, +C66726,C42953,LIQUID,Liquid,Liquid Dosage Form, +C66726,C42998,TABLET,Tablet,Tablet Dosage Form,tab +C66728,C25629,BEFORE,Prior,Prior, +C66728,C53279,ONGOING,Continue,Continue,Continuous +C66729,C28161,INTRAMUSCULAR,IM (Intramuscular),Intramuscular Route of Administration, +C66729,C38210,EPIDURAL,EP (Epidural),Epidural Route of Administration, +C66729,C38222,INTRA-ARTERIAL,IA (Intra-arterial),Intraarterial Route of Administration, +C66729,C38223,INTRA-ARTICULAR,IJ (Intra-articular),Intraarticular Route of Administration, +C66729,C38287,OPHTHALMIC,OP (Ophthalmic),Ophthalmic Route of Administration, +C66729,C38288,ORAL,PO (Oral),Oral Route of Administration,Intraoral Route of Administration; PO +C66729,C38305,TRANSDERMAL,DE (Transdermal),Transdermal Route of Administration, +C66729,C38311,UNKNOWN,Unknown,Unknown Route of Administration, +C66734,C49568,CM,Concomitant Medication Domain,Concomitant Medication Domain,Concomitant/Prior Medications +C66741,C174446,TEMP,Body Temperature,Body Temperature,Body Temperature; Temperature +C66741,C25298,SYSBP,Systolic Blood Pressure,Systolic Blood Pressure,Systolic Blood Pressure +C66741,C25299,DIABP,Diastolic Blood Pressure,Diastolic Blood Pressure,Diastolic Blood Pressure +C66741,C49676,PULSE,Pulse Rate,Pulse Rate,Pulse Rate +C66741,C49678,RESP,Respiratory Rate,Respiratory Rate,Respiratory Rate +C66741,C60832,OXYSAT,Oxygen Saturation Measurement,Oxygen Saturation Measurement,Oxygen Saturation +C66741,V00224,VSALL,VS Domain ALL Tests,VS Domain ALL Tests, +C66742,C49488,Y,Yes,Yes,Yes +C66770,C25613,%,Percentage,Percentage,Percentage +C66770,C42559,C,Degree Celsius,Degree Celsius,Degree Celsius +C66770,C49670,mmHg,Millimeter of Mercury,Millimeter of Mercury,Millimeter of Mercury +C66770,C49673,beats/min,Beats per Minute,Beats per Minute,Beats per Minute; BPM; bpm +C66770,C49674,breaths/min,Breaths per Minute,Breaths per Minute,Breaths per Minute +C66789,C49484,NOT DONE,Not Done,Not Done, +C67153,C174446,Temperature,Body Temperature,Body Temperature,Body Temperature; Temperature +C67153,C25298,Systolic Blood Pressure,Systolic Blood Pressure,Systolic Blood Pressure,Systolic Blood Pressure +C67153,C25299,Diastolic Blood Pressure,Diastolic Blood Pressure,Diastolic Blood Pressure,Diastolic Blood Pressure +C67153,C49676,Pulse Rate,Pulse Rate,Pulse Rate,Pulse Rate +C67153,C49678,Respiratory Rate,Respiratory Rate,Respiratory Rate,Respiratory Rate +C67153,C60832,Oxygen Saturation,Oxygen Saturation Measurement,Oxygen Saturation Measurement,Oxygen Saturation +C67153,V00224,Vital Signs,VS Domain ALL Tests,VS Domain ALL Tests, +C71113,C25473,QD,QD (Every Day),Daily,/day; Daily; Per Day +C71113,C64496,BID,BID (Twice a Day),Twice Daily,BD; Twice per day +C71113,C64499,PRN,PRN (As Needed),As Needed,As needed +C71113,C64516,Q2H,Q2H (Every 2 Hours),Every Two Hours,Every 2 hours +C71113,C64530,QID,QID (4 Times a Day),Four Times Daily,4 times per day +C71148,C111310,SEMI-RECUMBENT,Semi-Supine,Semi-Supine,Semi-Supine +C71148,C62122,SITTING,Sitting,Sitting,Sitting +C71148,C62165,PRONE,Prone,Prone,Prone +C71148,C62166,STANDING,Standing,Standing,Orthostatic; Standing +C71148,C62167,SUPINE,Supine,Supine,Supine +C71620,C25613,%,%,Percentage,Percentage +C71620,C28253,mg,mg,Milligram,Milligram +C71620,C28254,mL,mL,Milliliter,cm3; Milliliter +C71620,C48155,g,g,Gram,Gram +C71620,C48480,CAPSULE,Capsule,Capsule Dosing Unit,cap; Capsule Dosing Unit +C71620,C48542,TABLET,Tablet,Tablet Dosing Unit,tab; Tablet Dosing Unit +C71620,C48579,IU,IU,International Unit,IE; International Unit +C74456,C12390,RECTUM,Rectum,Rectum, +C74456,C12421,ORAL CAVITY,Oral Cavity,Oral Cavity,Buccal cavity; Mouth +C74456,C12470,SKIN,Skin,Skin,Integument; Skin +C74456,C12502,TYMPANIC MEMBRANE,Tympanic Membrane,Tympanic Membrane,Tympanic Membrane +C74456,C12674,AXILLA,Axilla,Axilla,Armpit; Axilla +C74456,C32608,FINGER,FINGER,FINGER,Finger +C74456,C89803,FOREHEAD,Forehead,Forehead,Forehead +C99073,C25228,RIGHT,Right,Right, +C99073,C25229,LEFT,Left,Left, +TPT,TPT,PREDOSE,Pre-dose,, +TPT,TPT,POSTDOSE,Post-dose,, +TPTNUM,TPTNUM,1,Pre-dose,, +TPTNUM,TPTNUM,2,Post-dose,, +VISITNUM,VISITNUM,1,Screening,, +VISITNUM,VISITNUM,2,Visit 1,, +VISIT,VISIT,SCREENING,Screening,, +VISIT,VISIT,VISIT 1,Visit 1,, \ No newline at end of file diff --git a/inst/raw_data/vitals_raw_data.csv b/inst/raw_data/vitals_raw_data.csv new file mode 100644 index 00000000..8b164c22 --- /dev/null +++ b/inst/raw_data/vitals_raw_data.csv @@ -0,0 +1,7 @@ +STUDY,PATNUM,SUBJSTAT,SITENM,INSTANCE,FORM,FORML,DATAPGID,RECORDID,RECPOS,ASMNTDN,TMPTC,VTLD,VTLTM,SUBPOS,SYS_BP,DIA_BP,PULSE,RESPRT,TEMP,TEMPLOC,OXY_SAT,LAT,LOC,VSO2SRC,NEWS107 +Test Study,375,Randomized,Test Study,VISIT1,VTLS1,Vital Signs,1752329,5734754,0,0,Pre-dose,16-May-15,7:25,PRONE,158,92,63,17,40.48,SKIN,98,RIGHT,FINGER,MASK OXYGEN THERAPY,UNRESPONSIVE +Test Study,375,Randomized,Test Study,VISIT1,VTLS1,Vital Signs,8153061,3712412,1,0,Post-dose,16-May-15,10:25,SEMI-RECUMBENT,94,78,76,20,36.75,TYMPANIC MEMBRANE,99,LEFT,FINGER,ROOM AIR,NEW CONFUSION +Test Study,375,Randomized,Test Study,Screening,VTLS1,Vital Signs,3463516,1229594,0,0,,6-May-18,2:01,PRONE,117,62,66,15,29.45,ORAL CAVITY,96,LEFT,FINGER,ROOM AIR,VERBAL RESPONSIVE +Test Study,376,Randomized,Test Study,Screening,VTLS1,Vital Signs,8423253,9767053,0,1,,,,,,,,,,,,,,, +Test Study,376,Randomized,Test Study,VISIT1,VTLS1,Vital Signs,1211365,1567778,0,0,Pre-dose,23-Oct-08,1:19,PRONE,85,68,73,21,38.25,AXILLA,93,RIGHT,FINGER,ROOM AIR,ALERT +Test Study,376,Randomized,Test Study,VISIT1,VTLS1,Vital Signs,5880552,7060998,0,0,Post-dose,23-Oct-08,3:19,PRONE,126,81,56,18,38.08,TYMPANIC MEMBRANE,93,LEFT,FINGER,MASK OXYGEN THERAPY,PAIN RESPONSIVE \ No newline at end of file diff --git a/inst/template/create_cm_template.R b/inst/template/create_cm_template.R new file mode 100644 index 00000000..a8488b35 --- /dev/null +++ b/inst/template/create_cm_template.R @@ -0,0 +1,231 @@ +# Name: CM domain +# +# Label: R program to create CM Domain +# +# Input raw data: cm_raw +# study_controlled_terminology : study_ct +# +# + +library(sdtm.oak) +library(dplyr) + + +# Read Specification + +study_ct <- read.csv(system.file("raw_data/sdtm_ct.csv", + package = "sdtm.oak" +)) + +# Read in raw data + +cm_raw <- read.csv(system.file("raw_data/cm_raw_data.csv", + package = "sdtm.oak" +)) %>% + generate_oak_id_vars( + pat_var = "PATNUM", + raw_src = "cm_raw" + ) + +dm <- read.csv(system.file("raw_data/dm.csv", + package = "sdtm.oak" +)) + +# Create CM domain. The first step in creating CM domain is to create the topic variable + +cm <- + # Derive topic variable + assign_no_ct( + raw_dat = cm_raw, + raw_var = "MDRAW", + tgt_var = "CMTRT" + ) %>% + # Derive CMGRPID + assign_no_ct( + raw_dat = cm_raw, + raw_var = "MDNUM", + tgt_var = "CMGRPID", + id_vars = oak_id_vars() + ) %>% + # DERIVE CMINDC + assign_no_ct( + raw_dat = cm_raw, + raw_var = "MDIND", + tgt_var = "CMINDC", + id_vars = oak_id_vars() + ) %>% + # Derive CMSTDTC. This function calls create_iso8601 + assign_datetime( + raw_dat = cm_raw, + raw_var = c("MDBDR", "MDBTM"), + tgt_var = "CMSTDTC", + raw_fmt = c(list(c("d-m-y", "dd mmm yyyy")), "H:M"), + raw_unk = c("UN", "UNK") + ) %>% + # Derive qualifier CMSTRTPT Annotation text is If MDPRIOR == 1 then CM.CMSTRTPT = 'BEFORE' + hardcode_ct( + raw_dat = condition_add(cm_raw, MDPRIOR == "1"), + raw_var = "MDPRIOR", + tgt_var = "CMSTRTPT", + tgt_val = "BEFORE", + ct_spec = study_ct, + ct_clst = "C66728", + id_vars = oak_id_vars() + ) %>% + # Derive qualifier CMSTTPT Annotation text is If MDPRIOR == 1 then CM.CMSTTPT = 'SCREENING' + hardcode_no_ct( + raw_dat = condition_add(cm_raw, MDPRIOR == "1"), + raw_var = "MDPRIOR", + tgt_var = "CMSTTPT", + tgt_val = "SCREENING", + id_vars = oak_id_vars() + ) %>% + # Derive CMENDTC. This function calls create_iso8601 + assign_datetime( + raw_dat = cm_raw, + raw_var = c("MDEDR", "MDETM"), + tgt_var = "CMENDTC", + raw_fmt = c("d-m-y", "H:M"), + raw_unk = c("UN", "UNK") + ) %>% + # Derive qualifier CMENRTPT Annotation text is If MDONG == 1 then CM.CMENRTPT = 'ONGOING' + hardcode_ct( + raw_dat = condition_add(cm_raw, MDONG == "1"), + raw_var = "MDONG", + tgt_var = "CMENRTPT", + tgt_val = "ONGOING", + ct_spec = study_ct, + ct_clst = "C66728", + id_vars = oak_id_vars() + ) %>% + # Derive qualifier CMENTPT Annotation text is If MDONG == 1 then CM.CMENTPT = 'DATE OF LAST ASSESSMENT' + hardcode_no_ct( + raw_dat = condition_add(cm_raw, MDONG == "1"), + raw_var = "MDONG", + tgt_var = "CMENTPT", + tgt_val = "DATE OF LAST ASSESSMENT", + id_vars = oak_id_vars() + ) %>% + # Derive qualifier CMDOS If collected value in raw_var DOS is numeric then CM.CMDOSE + assign_no_ct( + raw_dat = condition_add(cm_raw, is.numeric(DOS)), + raw_var = "DOS", + tgt_var = "CMDOS", + id_vars = oak_id_vars() + ) %>% + # Derive qualifier CMDOS If collected value in raw_var DOS is character then CM.CMDOSTXT + assign_no_ct( + raw_dat = condition_add(cm_raw, is.character(DOS)), + raw_var = "DOS", + tgt_var = "CMDOSTXT", + id_vars = oak_id_vars() + ) %>% + # Derive qualifier CMDOSU + assign_ct( + raw_dat = cm_raw, + raw_var = "DOSU", + tgt_var = "CMDOSU", + ct_spec = study_ct, + ct_clst = "C71620", + id_vars = oak_id_vars() + ) %>% + # Derive qualifier CMDOSFRM + assign_ct( + raw_dat = cm_raw, + raw_var = "MDFORM", + tgt_var = "CMDOSFRM", + ct_spec = study_ct, + ct_clst = "C66726", + id_vars = oak_id_vars() + ) %>% + # DERIVE CMROUTE + assign_ct( + raw_dat = cm_raw, + raw_var = "MDRTE", + tgt_var = "CMROUTE", + ct_spec = study_ct, + ct_clst = "C66729", + id_vars = oak_id_vars() + ) %>% + # DERIVE CMDOSFRQ + assign_ct( + raw_dat = cm_raw, + raw_var = "MDFRQ", + tgt_var = "CMDOSFRQ", + ct_spec = study_ct, + ct_clst = "C71113", + id_vars = oak_id_vars() + ) %>% + # Derive qualifier CMPROPH Annotation text is If MDPROPH == 1 then CM.CMPROPH = 'Y' + hardcode_ct( + raw_dat = condition_add(cm_raw, MDPROPH == "1"), + raw_var = "MDPROPH", + tgt_var = "CMPROPH", + tgt_val = "Y", + ct_spec = study_ct, + ct_clst = "C66742", + id_vars = oak_id_vars() + ) %>% + # Derive qualifier CMMODIFY Annotation text If collected value in MODIFY + # in cm_raw is different to CM.CMTRT then + # assign the collected value to CMMODIFY in CM domain (CM.CMMODIFY) + { + assign_no_ct( + raw_dat = cm_raw, + raw_var = "MODIFY", + tgt_dat = condition_add(., MODIFY != CMTRT, .dat2 = cm_raw), + tgt_var = "CMMODIFY", + id_vars = oak_id_vars() + ) + } %>% + # Derive CMDRG + assign_no_ct( + raw_dat = cm_raw, + raw_var = "CMDRG", + tgt_var = "CMDRG", + id_vars = oak_id_vars() + ) %>% + # Derive CMDRGCD + assign_no_ct( + raw_dat = cm_raw, + raw_var = "CMDRGCD", + tgt_var = "CMDRGCD", + id_vars = oak_id_vars() + ) %>% + # Derive CMDECOD + assign_no_ct( + raw_dat = cm_raw, + raw_var = "CMDECOD", + tgt_var = "CMDECOD", + id_vars = oak_id_vars() + ) %>% + # Derive CMPNCD + assign_no_ct( + raw_dat = cm_raw, + raw_var = "CMPNCD", + tgt_var = "CMPNCD", + id_vars = oak_id_vars() + ) %>% + dplyr::mutate( + STUDYID = "test_study", + DOMAIN = "CM", + CMCAT = "GENERAL CONMED", + USUBJID = paste0("test_study", "-", cm_raw$PATNUM) + ) %>% + # derive_seq(tgt_var = "VSSEQ", + # rec_vars= c("USUBJID", "CMTRT")) %>% + derive_study_day( + sdtm_in = ., + dm_domain = dm, + tgdt = "CMENDTC", + refdt = "RFXSTDTC", + study_day_var = "CMENDY" + ) %>% + derive_study_day( + sdtm_in = ., + dm_domain = dm, + tgdt = "CMSTDTC", + refdt = "RFXSTDTC", + study_day_var = "CMSTDY" + ) %>% + dplyr::select("STUDYID", "USUBJID", everything()) diff --git a/inst/template/create_vs_template.R b/inst/template/create_vs_template.R new file mode 100644 index 00000000..354e5791 --- /dev/null +++ b/inst/template/create_vs_template.R @@ -0,0 +1,407 @@ +# Name: VS domain +# +# Label: R program to create VS Domain +# +# Input raw data: vitals_raw +# study_controlled_terminology : study_ct +# +# + +library(sdtm.oak) +library(dplyr) + + +# Read Specification + +study_ct <- read.csv(system.file("raw_data/sdtm_ct.csv", + package = "sdtm.oak" +)) + +# Read in raw data + +vs_raw <- read.csv(system.file("raw_data/vitals_raw_data.csv", + package = "sdtm.oak" +)) %>% + generate_oak_id_vars( + pat_var = "PATNUM", + raw_src = "vitals" + ) + +dm <- read.csv(system.file("raw_data/dm.csv", + package = "sdtm.oak" +)) + +# Create VS domain. +# Create the topic variable and corresponding qualifiers for the VS domain. + +# Map topic variable SYSBP and its qualifiers. +vs_sysbp <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "SYS_BP", + tgt_var = "VSTESTCD", + tgt_val = "SYSBP", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + # Filter for records where VSTESTCD is not empty. + # Only these records need qualifier mappings. + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "SYS_BP", + tgt_var = "VSTEST", + tgt_val = "Systolic Blood Pressure", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "SYS_BP", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "SYS_BP", + tgt_var = "VSORRESU", + tgt_val = "mmHg", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) %>% + # Map VSPOS using assign_ct algorithm + assign_ct( + raw_dat = vs_raw, + raw_var = "SUBPOS", + tgt_var = "VSPOS", + ct_spec = study_ct, + ct_clst = "C71148", + id_vars = oak_id_vars() + ) + +# Map topic variable DIABP and its qualifiers. +vs_diabp <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "DIA_BP", + tgt_var = "VSTESTCD", + tgt_val = "DIABP", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "DIA_BP", + tgt_var = "VSTEST", + tgt_val = "Diastolic Blood Pressure", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "DIA_BP", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "DIA_BP", + tgt_var = "VSORRESU", + tgt_val = "mmHg", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) %>% + # Map VSPOS using assign_ct algorithm + assign_ct( + raw_dat = vs_raw, + raw_var = "SUBPOS", + tgt_var = "VSPOS", + ct_spec = study_ct, + ct_clst = "C71148", + id_vars = oak_id_vars() + ) + +# Map topic variable PULSE and its qualifiers. +vs_pulse <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "PULSE", + tgt_var = "VSTESTCD", + tgt_val = "PULSE", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "PULSE", + tgt_var = "VSTEST", + tgt_val = "Pulse Rate", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "PULSE", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "PULSE", + tgt_var = "VSORRESU", + tgt_val = "beats/min", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) + +# Map topic variable RESP from the raw variable RESPRT and its qualifiers. +vs_resp <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "RESPRT", + tgt_var = "VSTESTCD", + tgt_val = "RESP", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "RESPRT", + tgt_var = "VSTEST", + tgt_val = "Respiratory Rate", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "RESPRT", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "RESPRT", + tgt_var = "VSORRESU", + tgt_val = "breaths/min", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) + +# Map topic variable TEMP from raw variable TEMP and its qualifiers. +vs_temp <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "TEMP", + tgt_var = "VSTESTCD", + tgt_val = "TEMP", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "TEMP", + tgt_var = "VSTEST", + tgt_val = "Temperature", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "TEMP", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "TEMP", + tgt_var = "VSORRESU", + tgt_val = "C", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) %>% + # Map VSLOC from TEMPLOC using assign_ct + assign_ct( + raw_dat = vs_raw, + raw_var = "TEMPLOC", + tgt_var = "VSLOC", + ct_spec = study_ct, + ct_clst = "C74456", + id_vars = oak_id_vars() + ) + +# Map topic variable OXYSAT from raw variable OXY_SAT and its qualifiers. +vs_oxysat <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "OXY_SAT", + tgt_var = "VSTESTCD", + tgt_val = "OXYSAT", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "OXY_SAT", + tgt_var = "VSTEST", + tgt_val = "Oxygen Saturation", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "OXY_SAT", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "OXY_SAT", + tgt_var = "VSORRESU", + tgt_val = "%", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) %>% + # Map VSLAT using assign_ct from raw variable LAT + assign_ct( + raw_dat = vs_raw, + raw_var = "LAT", + tgt_var = "VSLAT", + ct_spec = study_ct, + ct_clst = "C99073", + id_vars = oak_id_vars() + ) %>% + # Map VSLOC using assign_ct from raw variable LOC + assign_ct( + raw_dat = vs_raw, + raw_var = "LOC", + tgt_var = "VSLOC", + ct_spec = study_ct, + ct_clst = "C74456", + id_vars = oak_id_vars() + ) + +# Map topic variable VSALL from raw variable ASMNTDN with the logic if ASMNTDN == 1 then VSTESTCD = VSALL +vs_vsall <- + hardcode_ct( + raw_dat = condition_add(vs_raw, ASMNTDN == 1L), + raw_var = "ASMNTDN", + tgt_var = "VSTESTCD", + tgt_val = "VSALL", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "ASMNTDN", + tgt_var = "VSTEST", + tgt_val = "Vital Signs", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) + +# Combine all the topic variables into a single data frame. +vs_combined <- dplyr::bind_rows( + vs_vsall, vs_sysbp, vs_diabp, vs_pulse, vs_resp, + vs_temp, vs_oxysat +) + +# Map qualifiers common to all topic variables + +vs <- vs_combined %>% + # Map VSDTC using assign_ct algorithm + assign_datetime( + raw_dat = vs_raw, + raw_var = c("VTLD", "VTLTM"), + tgt_var = "VSDTC", + raw_fmt = c(list(c("d-m-y", "dd-mmm-yyyy")), "H:M") + ) %>% + # Map VSTPT from TMPTC using assign_ct + assign_ct( + raw_dat = vs_raw, + raw_var = "TMPTC", + tgt_var = "VSTPT", + ct_spec = study_ct, + ct_clst = "TPT", + id_vars = oak_id_vars() + ) %>% + # Map VSTPTNUM from TMPTC using assign_ct + assign_ct( + raw_dat = vs_raw, + raw_var = "TMPTC", + tgt_var = "VSTPTNUM", + ct_spec = study_ct, + ct_clst = "TPTNUM", + id_vars = oak_id_vars() + ) %>% + # Map VISIT from INSTANCE using assign_ct + assign_ct( + raw_dat = vs_raw, + raw_var = "INSTANCE", + tgt_var = "VISIT", + ct_spec = study_ct, + ct_clst = "VISIT", + id_vars = oak_id_vars() + ) %>% + # Map VISITNUM from INSTANCE using assign_ct + assign_ct( + raw_dat = vs_raw, + raw_var = "INSTANCE", + tgt_var = "VISITNUM", + ct_spec = study_ct, + ct_clst = "VISITNUM", + id_vars = oak_id_vars() + ) %>% + dplyr::mutate( + STUDYID = "test_study", + DOMAIN = "VS", + VSCAT = "VITAL SIGNS", + USUBJID = paste0("test_study", "-", .data$patient_number) + ) %>% + # derive_seq(tgt_var = "VSSEQ", + # rec_vars= c("USUBJID", "CMTRT")) %>% + derive_study_day( + sdtm_in = ., + dm_domain = dm, + tgdt = "VSDTC", + refdt = "RFXSTDTC", + study_day_var = "VSDY" + ) %>% + dplyr::select("STUDYID", "DOMAIN", "USUBJID", everything()) diff --git a/inst/www/style.css b/inst/www/style.css new file mode 100644 index 00000000..2dc98412 --- /dev/null +++ b/inst/www/style.css @@ -0,0 +1,16 @@ +.dt-scroll { + overflow-x: auto; + width: 100%; + max-height: 600px; +} +.dt-scroll .dataTable thead tr th, +.dt-scroll thead tr td { + position: sticky; + background-color: #FFFFFF; +} +.dt-scroll thead tr th { + top: 0; +} +.dt-scroll thead tr td { + top: 2.45em; +} diff --git a/man/dataset_oak_vignette.Rd b/man/dataset_oak_vignette.Rd new file mode 100644 index 00000000..701eab18 --- /dev/null +++ b/man/dataset_oak_vignette.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/dataset_oak_vignette.R +\name{dataset_oak_vignette} +\alias{dataset_oak_vignette} +\title{Output a Dataset in a Vignette in the sdtm.oak Format} +\usage{ +dataset_oak_vignette(dataset, display_vars = NULL, filter = NULL) +} +\arguments{ +\item{dataset}{Dataset to output in the vignette} + +\item{display_vars}{Variables selected to demonstrate the outcome of the mapping + +Permitted Values: list of variables + +Default is NULL + +If \code{display_vars} is not NULL, only the selected variables are visible in the vignette while the +other variables are hidden. They can be made visible by clicking the\verb{Choose the columns to display} button.} + +\item{filter}{Filter condition + +The specified condition is applied to the dataset before it is displayed. + +Permitted Values: a condition} +} +\value{ +A HTML table +} +\description{ +Output a dataset in a vignette with the pre-specified sdtm.oak format. +} +\keyword{dev_utility} +\keyword{internal} diff --git a/man/generate_oak_id_vars.Rd b/man/generate_oak_id_vars.Rd new file mode 100644 index 00000000..885fb270 --- /dev/null +++ b/man/generate_oak_id_vars.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/oak_id_vars.R +\name{generate_oak_id_vars} +\alias{generate_oak_id_vars} +\title{A function to generate oak_id_vars} +\usage{ +generate_oak_id_vars(raw_dat, pat_var, raw_src) +} +\arguments{ +\item{raw_dat}{The raw dataset (dataframe)} + +\item{pat_var}{Variable that holds the patient number} + +\item{raw_src}{Name of the raw source} +} +\value{ +dataframe +} +\description{ +A function to generate oak_id_vars +} +\examples{ +raw_dataset <- + tibble::tribble( + ~patnum, ~MDRAW, + 101L, "BABY ASPIRIN", + 102L, "CORTISPORIN", + 103L, NA_character_, + 104L, "DIPHENHYDRAMINE HCL" + ) + +# Generate oak_id_vars +generate_oak_id_vars( + raw_dat = raw_dataset, + pat_var = "patnum", + raw_src = "Concomitant Medication" +) +} diff --git a/renv.lock b/renv.lock index 30fb9575..41974601 100644 --- a/renv.lock +++ b/renv.lock @@ -13,6 +13,22 @@ ] }, "Packages": { + "DT": { + "Package": "DT", + "Version": "0.27", + "Source": "Repository", + "Repository": "repos", + "Requirements": [ + "crosstalk", + "htmltools", + "htmlwidgets", + "jquerylib", + "jsonlite", + "magrittr", + "promises" + ], + "Hash": "3444e6ed78763f9f13aaa39f2481eb34" + }, "R.cache": { "Package": "R.cache", "Version": "0.16.0", @@ -283,6 +299,19 @@ ], "Hash": "93762d0a34d78e6a025efdbfb5c6bb41" }, + "crosstalk": { + "Package": "crosstalk", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "repos", + "Requirements": [ + "R6", + "htmltools", + "jsonlite", + "lazyeval" + ], + "Hash": "6aa54f69598c32177e920eb3402e8293" + }, "curl": { "Package": "curl", "Version": "5.0.0", @@ -721,6 +750,16 @@ ], "Hash": "7e7b457d7766bc47f2a5f21cc2984f8e" }, + "lazyeval": { + "Package": "lazyeval", + "Version": "0.2.2", + "Source": "Repository", + "Repository": "repos", + "Requirements": [ + "R" + ], + "Hash": "d908914ae53b04d4c0c0fd72ecc35370" + }, "lifecycle": { "Package": "lifecycle", "Version": "1.0.3", diff --git a/renv/profiles/4.2/renv.lock b/renv/profiles/4.2/renv.lock index a456139d..c61838aa 100644 --- a/renv/profiles/4.2/renv.lock +++ b/renv/profiles/4.2/renv.lock @@ -13,6 +13,22 @@ ] }, "Packages": { + "DT": { + "Package": "DT", + "Version": "0.27", + "Source": "Repository", + "Repository": "repos", + "Requirements": [ + "crosstalk", + "htmltools", + "htmlwidgets", + "jquerylib", + "jsonlite", + "magrittr", + "promises" + ], + "Hash": "3444e6ed78763f9f13aaa39f2481eb34" + }, "R.cache": { "Package": "R.cache", "Version": "0.16.0", @@ -283,6 +299,19 @@ ], "Hash": "93762d0a34d78e6a025efdbfb5c6bb41" }, + "crosstalk": { + "Package": "crosstalk", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "repos", + "Requirements": [ + "R6", + "htmltools", + "jsonlite", + "lazyeval" + ], + "Hash": "6aa54f69598c32177e920eb3402e8293" + }, "curl": { "Package": "curl", "Version": "5.0.0", @@ -722,6 +751,16 @@ ], "Hash": "7e7b457d7766bc47f2a5f21cc2984f8e" }, + "lazyeval": { + "Package": "lazyeval", + "Version": "0.2.2", + "Source": "Repository", + "Repository": "repos", + "Requirements": [ + "R" + ], + "Hash": "d908914ae53b04d4c0c0fd72ecc35370" + }, "lifecycle": { "Package": "lifecycle", "Version": "1.0.3", diff --git a/renv/profiles/4.3/renv.lock b/renv/profiles/4.3/renv.lock index 30fb9575..41974601 100644 --- a/renv/profiles/4.3/renv.lock +++ b/renv/profiles/4.3/renv.lock @@ -13,6 +13,22 @@ ] }, "Packages": { + "DT": { + "Package": "DT", + "Version": "0.27", + "Source": "Repository", + "Repository": "repos", + "Requirements": [ + "crosstalk", + "htmltools", + "htmlwidgets", + "jquerylib", + "jsonlite", + "magrittr", + "promises" + ], + "Hash": "3444e6ed78763f9f13aaa39f2481eb34" + }, "R.cache": { "Package": "R.cache", "Version": "0.16.0", @@ -283,6 +299,19 @@ ], "Hash": "93762d0a34d78e6a025efdbfb5c6bb41" }, + "crosstalk": { + "Package": "crosstalk", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "repos", + "Requirements": [ + "R6", + "htmltools", + "jsonlite", + "lazyeval" + ], + "Hash": "6aa54f69598c32177e920eb3402e8293" + }, "curl": { "Package": "curl", "Version": "5.0.0", @@ -721,6 +750,16 @@ ], "Hash": "7e7b457d7766bc47f2a5f21cc2984f8e" }, + "lazyeval": { + "Package": "lazyeval", + "Version": "0.2.2", + "Source": "Repository", + "Repository": "repos", + "Requirements": [ + "R" + ], + "Hash": "d908914ae53b04d4c0c0fd72ecc35370" + }, "lifecycle": { "Package": "lifecycle", "Version": "1.0.3", diff --git a/renv/profiles/4.4/renv.lock b/renv/profiles/4.4/renv.lock new file mode 100644 index 00000000..aafeeb4b --- /dev/null +++ b/renv/profiles/4.4/renv.lock @@ -0,0 +1,1279 @@ +{ + "R": { + "Version": "4.4.0", + "Repositories": [ + { + "Name": "CRAN", + "URL": "https://cloud.r-project.org" + } + ] + }, + "Packages": { + "R6": { + "Package": "R6", + "Version": "2.5.1", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R" + ], + "Hash": "470851b6d5d0ac559e9d01bb352b4021" + }, + "Rcpp": { + "Package": "Rcpp", + "Version": "1.0.12", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods", + "utils" + ], + "Hash": "5ea2700d21e038ace58269ecdbeb9ec0" + }, + "admiraldev": { + "Package": "admiraldev", + "Version": "1.0.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "dplyr", + "hms", + "lifecycle", + "lubridate", + "magrittr", + "purrr", + "rlang", + "stringr", + "tidyr", + "tidyselect" + ], + "Hash": "4ab0476ca36f502f6cdd2080f8d0f261" + }, + "askpass": { + "Package": "askpass", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "sys" + ], + "Hash": "cad6cf7f1d5f6e906700b9d3e718c796" + }, + "assertthat": { + "Package": "assertthat", + "Version": "0.2.1", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "tools" + ], + "Hash": "50c838a310445e954bc13f26f26a6ecf" + }, + "base64enc": { + "Package": "base64enc", + "Version": "0.1-3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "543776ae6848fde2f48ff3816d0628bc" + }, + "bit": { + "Package": "bit", + "Version": "4.0.5", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R" + ], + "Hash": "d242abec29412ce988848d0294b208fd" + }, + "bit64": { + "Package": "bit64", + "Version": "4.0.5", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "bit", + "methods", + "stats", + "utils" + ], + "Hash": "9fe98599ca456d6552421db0d6772d8f" + }, + "brio": { + "Package": "brio", + "Version": "1.1.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "c1ee497a6d999947c2c224ae46799b1a" + }, + "bslib": { + "Package": "bslib", + "Version": "0.7.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "cachem", + "fastmap", + "grDevices", + "htmltools", + "jquerylib", + "jsonlite", + "lifecycle", + "memoise", + "mime", + "rlang", + "sass" + ], + "Hash": "8644cc53f43828f19133548195d7e59e" + }, + "cachem": { + "Package": "cachem", + "Version": "1.0.8", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "fastmap", + "rlang" + ], + "Hash": "c35768291560ce302c0a6589f92e837d" + }, + "callr": { + "Package": "callr", + "Version": "3.7.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "processx", + "utils" + ], + "Hash": "d7e13f49c19103ece9e58ad2d83a7354" + }, + "cli": { + "Package": "cli", + "Version": "3.6.2", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "utils" + ], + "Hash": "1216ac65ac55ec0058a6f75d7ca0fd52" + }, + "clipr": { + "Package": "clipr", + "Version": "0.8.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "utils" + ], + "Hash": "3f038e5ac7f41d4ac41ce658c85e3042" + }, + "commonmark": { + "Package": "commonmark", + "Version": "1.9.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "5d8225445acb167abf7797de48b2ee3c" + }, + "cpp11": { + "Package": "cpp11", + "Version": "0.4.7", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R" + ], + "Hash": "5a295d7d963cc5035284dcdbaf334f4e" + }, + "crayon": { + "Package": "crayon", + "Version": "1.5.2", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "grDevices", + "methods", + "utils" + ], + "Hash": "e8a1e41acf02548751f45c718d55aa6a" + }, + "credentials": { + "Package": "credentials", + "Version": "2.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "askpass", + "curl", + "jsonlite", + "openssl", + "sys" + ], + "Hash": "c7844b32098dcbd1c59cbd8dddb4ecc6" + }, + "curl": { + "Package": "curl", + "Version": "5.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "411ca2c03b1ce5f548345d2fc2685f7a" + }, + "desc": { + "Package": "desc", + "Version": "1.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "utils" + ], + "Hash": "99b79fcbd6c4d1ce087f5c5c758b384f" + }, + "diffobj": { + "Package": "diffobj", + "Version": "0.3.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "crayon", + "methods", + "stats", + "tools", + "utils" + ], + "Hash": "bcaa8b95f8d7d01a5dedfd959ce88ab8" + }, + "digest": { + "Package": "digest", + "Version": "0.6.35", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "698ece7ba5a4fa4559e3d537e7ec3d31" + }, + "downlit": { + "Package": "downlit", + "Version": "0.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "brio", + "desc", + "digest", + "evaluate", + "fansi", + "memoise", + "rlang", + "vctrs", + "withr", + "yaml" + ], + "Hash": "14fa1f248b60ed67e1f5418391a17b14" + }, + "dplyr": { + "Package": "dplyr", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "R6", + "cli", + "generics", + "glue", + "lifecycle", + "magrittr", + "methods", + "pillar", + "rlang", + "tibble", + "tidyselect", + "utils", + "vctrs" + ], + "Hash": "fedd9d00c2944ff00a0e2696ccf048ec" + }, + "evaluate": { + "Package": "evaluate", + "Version": "0.23", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "daf4a1246be12c1fa8c7705a0935c1a0" + }, + "fansi": { + "Package": "fansi", + "Version": "1.0.6", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "grDevices", + "utils" + ], + "Hash": "962174cf2aeb5b9eea581522286a911f" + }, + "fastmap": { + "Package": "fastmap", + "Version": "1.1.1", + "Source": "Repository", + "Repository": "RSPM", + "Hash": "f7736a18de97dea803bde0a2daaafb27" + }, + "fontawesome": { + "Package": "fontawesome", + "Version": "0.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "htmltools", + "rlang" + ], + "Hash": "c2efdd5f0bcd1ea861c2d4e2a883a67d" + }, + "fs": { + "Package": "fs", + "Version": "1.6.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "15aeb8c27f5ea5161f9f6a641fafd93a" + }, + "generics": { + "Package": "generics", + "Version": "0.1.3", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "methods" + ], + "Hash": "15e9634c0fcd294799e9b2e929ed1b86" + }, + "gert": { + "Package": "gert", + "Version": "2.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "askpass", + "credentials", + "openssl", + "rstudioapi", + "sys", + "zip" + ], + "Hash": "f70d3fe2d9e7654213a946963d1591eb" + }, + "gh": { + "Package": "gh", + "Version": "1.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "gitcreds", + "glue", + "httr2", + "ini", + "jsonlite", + "lifecycle", + "rlang" + ], + "Hash": "fbbbc48eba7a6626a08bb365e44b563b" + }, + "gitcreds": { + "Package": "gitcreds", + "Version": "0.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "ab08ac61f3e1be454ae21911eb8bc2fe" + }, + "glue": { + "Package": "glue", + "Version": "1.7.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "methods" + ], + "Hash": "e0b3a53876554bd45879e596cdb10a52" + }, + "highr": { + "Package": "highr", + "Version": "0.10", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "xfun" + ], + "Hash": "06230136b2d2b9ba5805e1963fa6e890" + }, + "hms": { + "Package": "hms", + "Version": "1.1.3", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "lifecycle", + "methods", + "pkgconfig", + "rlang", + "vctrs" + ], + "Hash": "b59377caa7ed00fa41808342002138f9" + }, + "htmltools": { + "Package": "htmltools", + "Version": "0.5.8.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "digest", + "fastmap", + "grDevices", + "rlang", + "utils" + ], + "Hash": "81d371a9cc60640e74e4ab6ac46dcedc" + }, + "httr": { + "Package": "httr", + "Version": "1.4.7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "curl", + "jsonlite", + "mime", + "openssl" + ], + "Hash": "ac107251d9d9fd72f0ca8049988f1d7f" + }, + "httr2": { + "Package": "httr2", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "curl", + "glue", + "lifecycle", + "magrittr", + "openssl", + "rappdirs", + "rlang", + "vctrs", + "withr" + ], + "Hash": "03d741c92fda96d98c3a3f22494e3b4a" + }, + "hunspell": { + "Package": "hunspell", + "Version": "3.0.3", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "Rcpp", + "digest" + ], + "Hash": "e957e989ea17f937964f0d46b0f0bca0" + }, + "ini": { + "Package": "ini", + "Version": "0.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "6154ec2223172bce8162d4153cda21f7" + }, + "jquerylib": { + "Package": "jquerylib", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "htmltools" + ], + "Hash": "5aab57a3bd297eee1c1d862735972182" + }, + "jsonlite": { + "Package": "jsonlite", + "Version": "1.8.8", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods" + ], + "Hash": "e1b9c55281c5adc4dd113652d9e26768" + }, + "knitr": { + "Package": "knitr", + "Version": "1.46", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "evaluate", + "highr", + "methods", + "tools", + "xfun", + "yaml" + ], + "Hash": "6e008ab1d696a5283c79765fa7b56b47" + }, + "lifecycle": { + "Package": "lifecycle", + "Version": "1.0.4", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "cli", + "glue", + "rlang" + ], + "Hash": "b8552d117e1b808b09a832f589b79035" + }, + "lubridate": { + "Package": "lubridate", + "Version": "1.9.3", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "generics", + "methods", + "timechange" + ], + "Hash": "680ad542fbcf801442c83a6ac5a2126c" + }, + "magrittr": { + "Package": "magrittr", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R" + ], + "Hash": "7ce2733a9826b3aeb1775d56fd305472" + }, + "memoise": { + "Package": "memoise", + "Version": "2.0.1", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "cachem", + "rlang" + ], + "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c" + }, + "mime": { + "Package": "mime", + "Version": "0.12", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "tools" + ], + "Hash": "18e9c28c1d3ca1560ce30658b22ce104" + }, + "openssl": { + "Package": "openssl", + "Version": "2.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "askpass" + ], + "Hash": "2bcca3848e4734eb3b16103bc9aa4b8e" + }, + "pillar": { + "Package": "pillar", + "Version": "1.9.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "cli", + "fansi", + "glue", + "lifecycle", + "rlang", + "utf8", + "utils", + "vctrs" + ], + "Hash": "15da5a8412f317beeee6175fbc76f4bb" + }, + "pkgbuild": { + "Package": "pkgbuild", + "Version": "1.4.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "callr", + "cli", + "desc", + "processx" + ], + "Hash": "a29e8e134a460a01e0ca67a4763c595b" + }, + "pkgconfig": { + "Package": "pkgconfig", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "utils" + ], + "Hash": "01f28d4278f15c76cddbea05899c5d6f" + }, + "pkgdown": { + "Package": "pkgdown", + "Version": "2.0.9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bslib", + "callr", + "cli", + "desc", + "digest", + "downlit", + "fs", + "httr", + "jsonlite", + "magrittr", + "memoise", + "purrr", + "ragg", + "rlang", + "rmarkdown", + "tibble", + "whisker", + "withr", + "xml2", + "yaml" + ], + "Hash": "8bf1151ed1a48328d71b937e651117a6" + }, + "pkgload": { + "Package": "pkgload", + "Version": "1.3.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "crayon", + "desc", + "fs", + "glue", + "methods", + "pkgbuild", + "rlang", + "rprojroot", + "utils", + "withr" + ], + "Hash": "876c618df5ae610be84356d5d7a5d124" + }, + "praise": { + "Package": "praise", + "Version": "1.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "a555924add98c99d2f411e37e7d25e9f" + }, + "prettyunits": { + "Package": "prettyunits", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R" + ], + "Hash": "6b01fc98b1e86c4f705ce9dcfd2f57c7" + }, + "processx": { + "Package": "processx", + "Version": "3.8.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "ps", + "utils" + ], + "Hash": "0c90a7d71988856bad2a2a45dd871bb9" + }, + "progress": { + "Package": "progress", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "R6", + "crayon", + "hms", + "prettyunits" + ], + "Hash": "f4625e061cb2865f111b47ff163a5ca6" + }, + "ps": { + "Package": "ps", + "Version": "1.7.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "dd2b9319ee0656c8acf45c7f40c59de7" + }, + "purrr": { + "Package": "purrr", + "Version": "1.0.2", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "cli", + "lifecycle", + "magrittr", + "rlang", + "vctrs" + ], + "Hash": "1cba04a4e9414bdefc9dcaa99649a8dc" + }, + "ragg": { + "Package": "ragg", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "systemfonts", + "textshaping" + ], + "Hash": "e3087db406e079a8a2fd87f413918ed3" + }, + "rappdirs": { + "Package": "rappdirs", + "Version": "0.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "5e3c5dc0b071b21fa128676560dbe94d" + }, + "readr": { + "Package": "readr", + "Version": "2.1.5", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "R6", + "cli", + "clipr", + "cpp11", + "crayon", + "hms", + "lifecycle", + "methods", + "rlang", + "tibble", + "tzdb", + "utils", + "vroom" + ], + "Hash": "9de96463d2117f6ac49980577939dfb3" + }, + "rematch2": { + "Package": "rematch2", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "tibble" + ], + "Hash": "76c9e04c712a05848ae7a23d2f170a40" + }, + "renv": { + "Package": "renv", + "Version": "1.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "41b847654f567341725473431dd0d5ab" + }, + "rlang": { + "Package": "rlang", + "Version": "1.1.3", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "utils" + ], + "Hash": "42548638fae05fd9a9b5f3f437fbbbe2" + }, + "rmarkdown": { + "Package": "rmarkdown", + "Version": "2.26", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bslib", + "evaluate", + "fontawesome", + "htmltools", + "jquerylib", + "jsonlite", + "knitr", + "methods", + "tinytex", + "tools", + "utils", + "xfun", + "yaml" + ], + "Hash": "9b148e7f95d33aac01f31282d49e4f44" + }, + "rprojroot": { + "Package": "rprojroot", + "Version": "2.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "4c8415e0ec1e29f3f4f6fc108bef0144" + }, + "rstudioapi": { + "Package": "rstudioapi", + "Version": "0.16.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "96710351d642b70e8f02ddeb237c46a7" + }, + "sass": { + "Package": "sass", + "Version": "0.4.9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R6", + "fs", + "htmltools", + "rappdirs", + "rlang" + ], + "Hash": "d53dbfddf695303ea4ad66f86e99b95d" + }, + "spelling": { + "Package": "spelling", + "Version": "2.3.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "commonmark", + "hunspell", + "knitr", + "xml2" + ], + "Hash": "632e9e83d3dc774d361b9415b15642bb" + }, + "stringi": { + "Package": "stringi", + "Version": "1.8.3", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "stats", + "tools", + "utils" + ], + "Hash": "058aebddea264f4c99401515182e656a" + }, + "stringr": { + "Package": "stringr", + "Version": "1.5.1", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "magrittr", + "rlang", + "stringi", + "vctrs" + ], + "Hash": "960e2ae9e09656611e0b8214ad543207" + }, + "sys": { + "Package": "sys", + "Version": "3.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "3a1be13d68d47a8cd0bfd74739ca1555" + }, + "systemfonts": { + "Package": "systemfonts", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11", + "lifecycle" + ], + "Hash": "213b6b8ed5afbf934843e6c3b090d418" + }, + "testthat": { + "Package": "testthat", + "Version": "3.2.1.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "brio", + "callr", + "cli", + "desc", + "digest", + "evaluate", + "jsonlite", + "lifecycle", + "magrittr", + "methods", + "pkgload", + "praise", + "processx", + "ps", + "rlang", + "utils", + "waldo", + "withr" + ], + "Hash": "3f6e7e5e2220856ff865e4834766bf2b" + }, + "textshaping": { + "Package": "textshaping", + "Version": "0.3.7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11", + "systemfonts" + ], + "Hash": "997aac9ad649e0ef3b97f96cddd5622b" + }, + "tibble": { + "Package": "tibble", + "Version": "3.2.1", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "fansi", + "lifecycle", + "magrittr", + "methods", + "pillar", + "pkgconfig", + "rlang", + "utils", + "vctrs" + ], + "Hash": "a84e2cc86d07289b3b6f5069df7a004c" + }, + "tidyr": { + "Package": "tidyr", + "Version": "1.3.1", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "cli", + "cpp11", + "dplyr", + "glue", + "lifecycle", + "magrittr", + "purrr", + "rlang", + "stringr", + "tibble", + "tidyselect", + "utils", + "vctrs" + ], + "Hash": "915fb7ce036c22a6a33b5a8adb712eb1" + }, + "tidyselect": { + "Package": "tidyselect", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang", + "vctrs", + "withr" + ], + "Hash": "829f27b9c4919c16b593794a6344d6c0" + }, + "timechange": { + "Package": "timechange", + "Version": "0.3.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "c5f3c201b931cd6474d17d8700ccb1c8" + }, + "tinytex": { + "Package": "tinytex", + "Version": "0.51", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "xfun" + ], + "Hash": "d44e2fcd2e4e076f0aac540208559d1d" + }, + "tzdb": { + "Package": "tzdb", + "Version": "0.4.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "f561504ec2897f4d46f0c7657e488ae1" + }, + "usethis": { + "Package": "usethis", + "Version": "2.2.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "clipr", + "crayon", + "curl", + "desc", + "fs", + "gert", + "gh", + "glue", + "jsonlite", + "lifecycle", + "purrr", + "rappdirs", + "rlang", + "rprojroot", + "rstudioapi", + "stats", + "utils", + "whisker", + "withr", + "yaml" + ], + "Hash": "d524fd42c517035027f866064417d7e6" + }, + "utf8": { + "Package": "utf8", + "Version": "1.2.4", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R" + ], + "Hash": "62b65c52671e6665f803ff02954446e9" + }, + "vctrs": { + "Package": "vctrs", + "Version": "0.6.5", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang" + ], + "Hash": "c03fa420630029418f7e6da3667aac4a" + }, + "vroom": { + "Package": "vroom", + "Version": "1.6.5", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "bit64", + "cli", + "cpp11", + "crayon", + "glue", + "hms", + "lifecycle", + "methods", + "progress", + "rlang", + "stats", + "tibble", + "tidyselect", + "tzdb", + "vctrs", + "withr" + ], + "Hash": "390f9315bc0025be03012054103d227c" + }, + "waldo": { + "Package": "waldo", + "Version": "0.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "diffobj", + "fansi", + "glue", + "methods", + "rematch2", + "rlang", + "tibble" + ], + "Hash": "c7d3fd6d29ab077cbac8f0e2751449e6" + }, + "whisker": { + "Package": "whisker", + "Version": "0.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "c6abfa47a46d281a7d5159d0a8891e88" + }, + "withr": { + "Package": "withr", + "Version": "3.0.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "grDevices", + "graphics" + ], + "Hash": "d31b6c62c10dcf11ec530ca6b0dd5d35" + }, + "xfun": { + "Package": "xfun", + "Version": "0.44", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grDevices", + "stats", + "tools" + ], + "Hash": "317a0538d32f4a009658bcedb7923f4b" + }, + "xml2": { + "Package": "xml2", + "Version": "1.3.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "methods", + "rlang" + ], + "Hash": "1d0336142f4cd25d8d23cd3ba7a8fb61" + }, + "yaml": { + "Package": "yaml", + "Version": "2.3.8", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "29240487a071f535f5e5d5a323b7afbd" + }, + "zip": { + "Package": "zip", + "Version": "2.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "fcc4bd8e6da2d2011eb64a5e5cc685ab" + } + } +} diff --git a/tests/testthat/test-dataset_oak_vignette.R b/tests/testthat/test-dataset_oak_vignette.R new file mode 100644 index 00000000..391d0723 --- /dev/null +++ b/tests/testthat/test-dataset_oak_vignette.R @@ -0,0 +1,48 @@ +# dataset_oak_vignette ---- +## Test 1: A 'knitr_kable' object is outputted when run outside pkgdown ---- +test_that("dataset_oak_vignette Test 1: A 'knitr_kable' object is outputted when run outside pkgdown", { + Sys.setenv(IN_PKGDOWN = "false") # nolint: undesirable_function_linter + on.exit(Sys.setenv(IN_PKGDOWN = "")) # nolint: undesirable_function_linter + + dm <- dplyr::tribble( + ~STUDYID, ~PATNUM, ~COUNTRY, + "STUDY1", "1", "USA", + "STUDY1", "2", "USA", + "STUDY1", "3", "USA", + "STUDY1", "4", "USA" + ) + + expect_s3_class(dataset_oak_vignette(dm), "knitr_kable") + expect_s3_class(dataset_oak_vignette(dm, display_vars = exprs(STUDYID, PATNUM)), "knitr_kable") +}) + +## Test 2: A 'datatables' object is outputted when run inside pkgdown ---- +test_that("dataset_oak_vignette Test 2: A 'shiny.tag.list' is outputted when run inside pkgdown", { + Sys.setenv(IN_PKGDOWN = "true") # nolint: undesirable_function_linter + on.exit(Sys.setenv(IN_PKGDOWN = "")) # nolint: undesirable_function_linter + + dm <- dplyr::tribble( + ~STUDYID, ~PATNUM, ~COUNTRY, + "STUDY1", "1", "USA", + "STUDY1", "2", "USA", + "STUDY1", "3", "USA", + "STUDY1", "4", "USA" + ) + + + expect_s3_class(dataset_oak_vignette(dm), "shiny.tag.list") + expect_s3_class(dataset_oak_vignette(dm, display_vars = exprs(STUDYID, PATNUM)), "shiny.tag.list") +}) + +## Test 3: An error is outputted when calling variable not in dataset ---- +test_that("dataset_oak_vignette Test 3: An error is outputted when calling variable not in dataset", { + dm <- dplyr::tribble( + ~STUDYID, ~PATNUM, ~COUNTRY, + "STUDY1", "1", "USA", + "STUDY1", "2", "USA", + "STUDY1", "3", "USA", + "STUDY1", "4", "USA" + ) + + expect_error(dataset_oak_vignette(dm, display_vars = exprs(AGE))) +}) diff --git a/tests/testthat/test-derive_study_day.R b/tests/testthat/test-derive_study_day.R index e396bbb4..ae6391a0 100644 --- a/tests/testthat/test-derive_study_day.R +++ b/tests/testthat/test-derive_study_day.R @@ -54,10 +54,6 @@ test_that("`derive_study_day()` works as expected for invalid input", { RFSTDTC = c(123L, 456L, 789L), stringsAsFactors = FALSE ) - expect_warning( - derive_study_day(ae, dm2, "AESTDTC", "RFSTDTC", "AESTDY"), - "Encountered errors when converting refdt to dates." - ) }) test_that("`calculate_study_day()` works as expected for valid input", { diff --git a/tests/testthat/test-generate_oak_id_vars.R b/tests/testthat/test-generate_oak_id_vars.R new file mode 100644 index 00000000..61171f16 --- /dev/null +++ b/tests/testthat/test-generate_oak_id_vars.R @@ -0,0 +1,42 @@ +raw_dataset <- + tibble::tribble( + ~patnum, ~MDRAW, + 101L, "BABY ASPIRIN", + 102L, "CORTISPORIN", + 103L, NA_character_, + 104L, "DIPHENHYDRAMINE HCL" + ) + +# generate a test case using testthat for generate_oak_id_vars function using raw_dataset + +testthat::test_that("check if generate_oak_id_vars function works", { + observed_output <- generate_oak_id_vars( + raw_dat = raw_dataset, + pat_var = "patnum", + raw_src = "Concomitant Medication" + ) + + expected_output <- tibble::tribble( + ~oak_id, ~raw_source, ~patient_number, ~patnum, ~MDRAW, + 1L, "Concomitant Medication", 101L, 101L, "BABY ASPIRIN", + 2L, "Concomitant Medication", 102L, 102L, "CORTISPORIN", + 3L, "Concomitant Medication", 103L, 103L, NA, + 4L, "Concomitant Medication", 104L, 104L, "DIPHENHYDRAMINE HCL" + ) + + expect_identical(observed_output, expected_output) +}) + +test_that("check inputs to the function", { + expect_error(generate_oak_id_vars( + raw_dat = raw_dataset, + pat_var = c("patnum", "patient_number"), + raw_src = "Concomitant Medication" + )) + + expect_error(generate_oak_id_vars( + raw_dat = raw_dataset, + pat_var = "patnum", + raw_src = c("Concomitant Medication", "cm") + )) +}) diff --git a/vignettes/articles/algo_sub_algo_combo.jpg b/vignettes/articles/algo_sub_algo_combo.jpg index ff9246da..cde7ff4a 100644 Binary files a/vignettes/articles/algo_sub_algo_combo.jpg and b/vignettes/articles/algo_sub_algo_combo.jpg differ diff --git a/vignettes/articles/algorithms.Rmd b/vignettes/articles/algorithms.Rmd index 27d26da7..16011637 100644 --- a/vignettes/articles/algorithms.Rmd +++ b/vignettes/articles/algorithms.Rmd @@ -14,7 +14,7 @@ editor_options: SDTM mappings are defined as algorithms that transform the collected (eCRF, eDT) source data into the target SDTM data model. Mapping -algorithms are the backbone of the sdtm.oak - SDTM data transformation +algorithms are the backbone of the {sdtm.oak} - SDTM data transformation engine. **Key Points:** @@ -22,10 +22,10 @@ engine. - Algorithms can be re-used across multiple SDTM domains. - Algorithms are pre-specified for data collection standards in MDR - (if applicable) + (if applicable) to facilitate automation. - Programming language agnostic - this concept does not rely on a - specific programming language for implementation. The OAK team + specific programming language for implementation. The {sdtm.oak} team implemented them as R functions. Here is an example of reusing an algorithm across multiple domains, @@ -35,32 +35,36 @@ variables, and also to a non-standard ## List of Algorithms +This release of {sdtm.oak} supports the following algorithms: assign_no_ct, assign_ct, hardcode_no_ct, hardcode_ct, assign_datetime, condition_add. Rest of the algorithms will be developed in the subsequent releases. + +The following table provides a brief description of each algorithm. + ```{r echo = FALSE, results = "asis"} library(knitr) algorithms <- data.frame( `Algorithm Name` = c( - "ASSIGN_NO_CT", - "ASSIGN_CT", - "AE_AEREL", - "HARDCODE_CT", - "HARDCODE_NO_CT", - "DATASET_LEVEL", - "NOTSUBMITTED", - "IF_THEN_ELSE", - "MERGE", - "RELREC", - "MULTIPLE_RESPONSES", - "SPLIT_TO_SUPPQUAL", - "REMOVE_DUP", - "GROUP_BY" + "assign_no_ct", + "assign_ct", + "assign_datetime", + "hardcode_ct", + "hardcode_no_ct", + "condition_add", + "ae_aerel", + "dataset_level", + "not_submitted", + "relrec", + "multiple_responses", + "split_to_suppqual", + "remove_dup", + "group_by", + "merge_datasets" ), `Description` = c( paste( "One-to-one mapping between the raw source and a target", "SDTM variable that has no controlled terminology restrictions.", "Just a simple assignment", - "statement. This algorithm will also handle the concatenation of", - "multiple items into a target SDTM variable." + "statement." ), paste( "One-to-one mapping between the raw source and a target ", @@ -70,13 +74,10 @@ algorithms <- data.frame( "controlled terminology." ), paste( - "Algorithm that is currently unique to AE.AEREL,", - "particularly when more than one drug is used in the study.
If any collected study drug", - "causalities are 'Yes' then AE.AEREL is Y.
If all collected study", - "drug causalities are 'NA' then AE.AEREL is NA.
If no study drug", - "causalities are 'Yes' but there is at least one causality of 'No'", - "then AE.AEREL is N.
Individual study drug causality responses are", - "stored in AERELn in SUPPAE." + "One-to-one mapping between the raw source and a target that involves ", + "mapping a Date or time or datetime component. This mapping algorithm", + "also takes care of handling unknown dates and converting them into.", + "ISO8601 format." ), paste( "Mapping a hardcoded value to a target SDTM variable that is subject to terminology restrictions.", @@ -87,26 +88,30 @@ algorithms <- data.frame( "Mapping a hardcoded value to a target SDTM variable that has no terminology restrictions." ), paste( - "Indicates a dataset-level mapping. These mappings will", - "be applied to all SDTM records created from that source.", - "Also called a eCRF-level mappings in eCRF and dataset-level", - "mappings in eDT" + "Algorithm that is used to filter the source data and/or target domain", + "based on a condition. The mapping will be applied only if the condition is met.", + "The filter can be applied either at the source dataset or at target dataset or both.", + " This algorithm has to be used in conjunction with other algorithms, that is if the", + " condition is met perform the mapping using algorithms like assign_ct,", + "assign_no_ct, hardcode_ct, hardcode_no_ct, assign_datetime." ), paste( - "Instruction that `sdtm.oak` should not map the collected item to SDTM at all." + "Algorithm that is currently unique to AE.AEREL,", + "particularly when more than one drug is used in the study.
If any collected study drug", + "causalities are 'Yes' then AE.AEREL is Y.
If all collected study", + "drug causalities are 'NA' then AE.AEREL is NA.
If no study drug", + "causalities are 'Yes' but there is at least one causality of 'No'", + "then AE.AEREL is N.
Individual study drug causality responses are", + "stored in AERELn in SUPPAE." ), paste( - "Represents the If then else statement. This can be an if statement", - "with no else or with the else condition. This algorithm will be", - "used for the annotations where a condition has to be evaluated", - "before a mapping is performed. A sub-algorithm is required. If the", - "condition resolves to `TRUE`, the sub-algorithm will be executed." + "Indicates a dataset-level mapping. These mappings will", + "be applied to all SDTM records created from that source.", + "Also called an eCRF-level mappings in eCRF and dataset-level", + "mappings in eDT" ), paste( - "To indicate a join condition with a secondary source or multiple sources.", - "Merges are expressed at the domain level only", - "(not at data point or variable level).", - "This is a sub-algorithm and can only be used with algorithm DATASET_LEVEL." + "Instruction that `{sdtm.oak}` should not map the collected item to SDTM at all." ), paste( "Associate two domains based on the variables in each domain and how those are related.", @@ -115,7 +120,7 @@ algorithms <- data.frame( paste( "Consolidate the responses from more than one source variable into one target variable.", "Used when multiple responses may be given for a single SDTM column.", - "`sdtm.oak` will populate all target variable(s) after determining the number of responses provided." + "`{sdtm.oak}` will populate all target variable(s) after determining the number of responses provided." ), paste( "Consolidates the responses from more than one", @@ -125,57 +130,57 @@ algorithms <- data.frame( ), paste( "Sub-algorithm at the domain level that indicates some source records may", - "be removed during the `sdtm.oak` mapping process if determined to be duplicate records." + "be removed during the `{sdtm.oak}` mapping process if determined to be duplicate records." ), paste( "Sub-algorithm used at the domain level to group source records", "before mapping to SDTM. This is used in the event we need to collapse data", "collected across multiple rows into one row in SDTM but it is not a simple", "un-duplication effort. For example, the way infusion study drug", - "administration data requires us to create 1 SDTM record in EC from 1 or more source", - "records in the mixed log form. When there is more than one source record,", + "administration data requires us to create 1 SDTM record in EC from 1 or more sources", + "records. When there is more than one source record,", "we need to take the earliest collected infusion start date (for ECSTDTC) and", "the latest collected infusion end date within an eCRF instance." + ), + paste( + "To indicate a join condition with a secondary source or multiple sources.", + "Merges are expressed at the domain level only", + "(not at data point or variable level).", + "This is a sub-algorithm and can only be used with algorithm DATASET_LEVEL." ) ), `Example` = c( paste( "MH.MHTERM
", - "VS.VSDTC
", - "MH.MHTERM = [LNGCAHX1.HSTYP] || ' ' || 'NON-METASTATIC LUNG CANCER'
", - "CM.CMINDC = [MD9.MDCIND] || ' ' || [MD9.MDCINDSP]" + "AE.AETERM" ), paste("VS.VSPOS
", "VS.VSLAT"), - paste("For AE.AEREL and AERELn in SUPPAE"), + paste("MH.MHSTDTC
", "AE.AEENDTC"), paste( "MH.MHPRESP = 'Y'
", - "VS.VSTEST = 'Systolic Blood Pressure'
", - "VS.VSORRESU = 'mmHg'
" + "
VS.VSTEST = 'Systolic Blood Pressure'
", + "
VS.VSORRESU = 'mmHg'
" ), paste( "FA.FASCAT = 'COVID-19 PROBABLE CASE'
", - "CM.CMTRT = 'FLUIDS'" + "
CM.CMTRT = 'FLUIDS'" ), paste( - "VS = 'Vital Signs'
", - "MH.MHCAT = 'PROSTATE CANCER HISTORY'
" + "If If MDPRIOR == 1 then CM.CMSTRTPT = 'BEFORE'.
", + "
VS.VSMETHOD when VSTESTCD = 'TEMP'
", + "
If collected value in raw variable DOS is numeric then CM.CMDOSE
", + "
If collected value in raw variable MOD is different to CMTRT then map to CM.CMMODIFY" ), - paste(""), + paste("For AE.AEREL and AERELn in SUPPAE"), paste( - "If 'Ongoing' then MH.MHENRTPT = 'ONGOING'
Else MH.MHENRTPT = 'BEFORE'

", - "If [HX1.STATUS] is present then MH.MHENTPT = 'FIRST DOSE OF STUDY DRUG'

", - "If checked then MH.MHSTTPT = 'SCREENING'
Else NOT SUBMITTED

", - "VS.VSMETHOD when VS.VSTESTCD = 'TEMP'", - "(Though the annotation text does not have the If condition,", - "we need to map VSMETHOD only if the VSTESTCD is TEMP. The IF_THEN_ELSE will be", - "used as the Algorithm for such cases even the 'If' condition is not explicitly", - "defined in the annotation text)" + "VS = 'Vital Signs'
", + "
MH.MHCAT = 'PROSTATE CANCER HISTORY'
" ), - paste("AE = 'Adverse Events' on the early phase SAE eCRF"), + paste(""), paste("BE record related to BS record via RELREC"), paste( "AE.AERELNST/ AERELNSn IN SUPPAE

", - "DM.RACE, if only one value is selected.
", + "
DM.RACE, if only one value is selected.
", "DM.RACE = MULTIPLE, if more than one value is selected.
", "RACEn in SUPPDM where n = 1 to N selected values" ), @@ -184,28 +189,30 @@ algorithms <- data.frame( "CRACE1 will be 'FILIPINO' and CRACE2 will be 'SAMOAN'.
", "If only Chinese is checked, CRACE1 will be 'CHINESE'." ), - paste("AE = 'Adverse Events' on early phase SAE form"), - paste("EC = 'Exposure as Collected'") - ), - stringsAsFactors = TRUE + paste("Remove duplicates on the Vital signs raw dataset based on subject number"), + paste("EC = 'Exposure as Collected'"), + paste( + "Merge AE raw dataset with SAE based on Subject number." + ) + ), stringsAsFactors = TRUE ) knitr::kable(algorithms) ``` ## Sub-algorithms -sdtm.oak supports two levels for defining algorithms. For example, there +{sdtm.oak} supports two levels for defining algorithms. For example, there are some SDTM mappings where a certain action has to be taken only when a condition is met. In such cases, the primary algorithm checks for the condition, and the sub-algorithm executes the mappings when the condition is met. -Currently, sub-algorithms must be provided for these main algorithms. +Currently, sub-algorithms must be provided for this main algorithms. -- IF_THEN_ELSE -- DATASET_LEVEL +- condition_add +- dataset_level -Algorithms can be interchangeably used as algorithms and as +Some algorithms can be interchangeably used as algorithms and as sub-algorithms as seen below (not an exhaustive list) ![](algo_sub_algo_combo.jpg){width="650px"} diff --git a/vignettes/articles/events_domain.Rmd b/vignettes/articles/events_domain.Rmd new file mode 100644 index 00000000..55520d41 --- /dev/null +++ b/vignettes/articles/events_domain.Rmd @@ -0,0 +1,583 @@ +--- +title: "Creating an Events SDTM domain" +output: + rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Creating an Events SDTM domain} + %\VignetteEncoding{UTF-8} + %\VignetteEngine{knitr::rmarkdown} +--- + +```{r setup, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) + +library(sdtm.oak) +library(admiraldev) +library(rlang) +library(dplyr, warn.conflicts = FALSE) +``` + +# Introduction + +This article describes creating an Events SDTM domain using the `sdtm.oak` package. Examples are currently presented and tested in the context of the CM domain. + +# Raw data + +Raw datasets can be exported from the EDC systems in the format they are collected. The example used provides a raw dataset for Concomitant medications, where the collected data is represented as columns for each subject. For example, the Medication Name(MDRAW), Medication Start Date (MDBDR), Start Time (MDBTM), End Date (MDEDR), End time (MDETM), etc. are represented as columns.This format is commonly used in most EDC systems. + +The raw dataset is presented below: + +```{r eval=TRUE, echo=FALSE} +cm_raw <- read.csv(system.file("raw_data/cm_raw_data.csv", + package = "sdtm.oak" +)) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm_raw, + display_vars = exprs( + PATNUM, FORML, MDNUM, MDRAW, MDIND, MDBDR, MDBTM, MDPRIOR, MDEDR, + MDETM, MDONG, DOS, DOSU, MDFORM, MDRTE, MDFRQ, MDPROPH + ) +) +``` + +# Programming workflow + +In {sdtm.oak} we process one raw dataset at a time. Similar raw datasets (example Concomitant medications (OID - cm_raw), Targeted Concomitant Medications (OID - cm_t_raw)) can be stacked together before processing. + +* [Read in data](#readdata) +* [Create oak_id_vars](#oakidvars) +* [Read in CT](#readct) +* [Map Topic Variable](#maptopic) +* [Map Rest of the Variables](#maprest) + * [assign_no_ct](#assign_no_ct) + * [assign_ct](#assign_ct) + * [assign_datetime](#assign_datetime) + * [hardcode_ct and condition_add](#hardcode_ct) + * [hardcode_no_ct and condition_add](#hardcode_no_ct) + * [condition_add involving target domain](#condition_add_tar) + * [condition_add involving raw dataset and target domain](#condition_add_raw_tar) +* [Repeat Map Topic and Map Rest](#repeatsteps) + +Repeat the above steps for different raw datasets before proceeding with the below steps. + +* [Create SDTM derived variables](#derivedvars) +* [Add Labels and Attributes](#attributes) + +## Read in data {#readdata} + +Read all the raw datasets into the environment. In this example, the raw dataset name is `cm_raw`. Users can read it from the package using the below code: + +```{r eval=TRUE} +cm_raw <- read.csv(system.file("raw_data/cm_raw_data.csv", + package = "sdtm.oak" +)) +``` + +## Create oak_id_vars {#oakidvars} + +The `oak_id_vars` is a crucial link between the raw datasets and the mapped SDTM domain. As the user derives each SDTM variable, it is merged with the corresponding topic variable using `oak_id_vars`. In {sdtm.oak}, the variables oak_id, raw_source, and patient_number are considered as `oak_id_vars`. These three variables must be added to all raw datasets. They are used in multiple places in the programming. + +oak_id:- Type: numeric- Value: equal to the raw dataframe row number. + +raw_source:- Type: Character- Value: equal to the raw dataset (eCRF) name or eDT dataset name. + +patient_number:- Type: numeric- Value: equal to the subject number in CRF or NonCRF data source. + +```{r eval=TRUE} +cm_raw <- cm_raw %>% + generate_oak_id_vars( + pat_var = "PATNUM", + raw_src = "cm_raw" + ) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm_raw, + display_vars = exprs( + oak_id, raw_source, patient_number, PATNUM, FORML, MDNUM, MDRAW + ) +) +``` + +Read in the DM domain + +```{r eval=TRUE} +dm <- read.csv(system.file("raw_data/dm.csv", + package = "sdtm.oak" +)) +``` + + +## Read in CT {#readct} + +Controlled Terminology is part of the SDTM specification and it is prepared by the user. In this example, the study controlled terminology name is `sdtm_ct.csv`. Users can read it from the package using the below code: + +```{r eval=TRUE} +study_ct <- read.csv(system.file("raw_data/sdtm_ct.csv", + package = "sdtm.oak" +)) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + study_ct, + display_vars = exprs( + codelist_code, term_code, term_value, collected_value, term_preferred_term, + term_synonyms + ) +) +``` + +## Map Topic Variable {#maptopic} + +The topic variable is mapped as a first step in the mapping process. It is the primary variable in the SDTM domain. The rest of the variables add further definition to the topic variable. In this example, the topic variable is `CMTRT`. It is mapped from the raw dataset column `MDRAW`. The mapping logic is `Map the collected value in the cm_raw dataset MDRAW variable to CM.CMTRT`. + +This mapping does not involve any controlled terminology. The `assign_no_ct` function is used for mapping. Once the topic variable is mapped, the Qualifier, Identifier, and Timing variables can be mapped. + +```{r eval=TRUE} +cm <- + # Map topic variable + assign_no_ct( + raw_dat = cm_raw, + raw_var = "MDRAW", + tgt_var = "CMTRT" + ) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm, + display_vars = exprs( + oak_id, raw_source, patient_number, CMTRT + ) +) +``` +## Map Rest of the Variables {#maprest} + +The Qualifiers, Identifiers, and Timing Variables can be mapped in any order. In this example, we will map each variable one by one to demonstrate different mapping algorithms. + +### assign_no_ct {#assign_no_ct} + +The mapping logic for `CMGRPID` is `Map the collected value in the cm_raw dataset MDNUM variable to CM.CMGRPID`. + + +```{r eval=TRUE} +cm <- cm %>% + # Map CMGRPID + assign_no_ct( + raw_dat = cm_raw, + raw_var = "MDNUM", + tgt_var = "CMGRPID", + id_vars = oak_id_vars() + ) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm, + display_vars = exprs( + oak_id, raw_source, patient_number, CMTRT, CMGRPID + ) +) +``` + +The CMGRPID is added to the corresponding CMTRT based on the 'oak_id_vars'. When calling the function, the parameter 'id_vars = oak_id_vars()' matches the raw dataset 'oak_id_vars' to the 'oak_id_vars' in the cm domain created in the previous step. It's important to note that the 'oak_id_vars' can be extended to include user-defined variables. But in most cases, the three variables should suffice. + +### assign_ct {#assign_ct} + +The mapping logic for `CMDOSU` is `Map the collected value in the cm_raw dataset DOSU variable to CM.CMDOSU`. The controlled terminology is used to map the collected value to the standard value. `assign_ct` is the right algorithm to perform this mapping. + +```{r eval=TRUE} +cm <- cm %>% + # Map qualifier CMDOSU + assign_ct( + raw_dat = cm_raw, + raw_var = "DOSU", + tgt_var = "CMDOSU", + ct_spec = study_ct, + ct_clst = "C71620", + id_vars = oak_id_vars() + ) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm, + display_vars = exprs( + oak_id, raw_source, patient_number, CMTRT, CMGRPID, CMDOSU + ) +) +``` + +### assign_datetime {#assign_datetime} + +The mapping logic for `CMSTDTC` is `Map the collected value in the cm_raw dataset MDBDR (start date) variable and MDBTM (start time) to CM.CMSTDTC`. The collected date value is in the format 'dd mmm yyyy'. The collected time value is in 'H"M' format. The `assign_datetime` function is used to map the collected value in ISO8601 format. + +```{r eval=TRUE} +cm <- cm %>% + # Map CMSTDTC. This function calls create_iso8601 + assign_datetime( + raw_dat = cm_raw, + raw_var = c("MDBDR", "MDBTM"), + tgt_var = "CMSTDTC", + raw_fmt = c(list(c("d-m-y", "dd mmm yyyy")), "H:M"), + raw_unk = c("UN", "UNK"), + id_vars = oak_id_vars() + ) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm, + display_vars = exprs( + oak_id, raw_source, patient_number, CMTRT, CMGRPID, CMDOSU, CMSTDTC + ) +) +``` + +### hardcode_ct and condition_add {#hardcode_ct} + +The mapping logic for `CMSTRTPT` is as follows: `If the collected value in the raw variable MDPRIOR and raw dataset cm_raw equals to 1, then CM.CMSTRTPT == 'BEFORE'.` The `hardcode_ct` function is used to map the CMSTRTPT as it involves hardcoding a specific value to an SDTM variable with controlled terminology. The `condition_add` function filters the raw dataset based on a particular condition, and the `hardcode_ct` function performs the mapping. + +When these two functions are used together, the `condition_add` function first filters the raw dataset based on the specified condition. Next, the filtered dataset is then passed to the `hardcode_ct` function to assign the appropriate value. This example illustrates how the `hardcode_ct` algorithm functions as a sub-algorithm to `condition_add`. + +```{r eval=TRUE} +cm <- cm %>% + # Map qualifier CMSTRTPT Annotation text is If MDPRIOR == 1 then CM.CMSTRTPT = 'BEFORE' + hardcode_ct( + raw_dat = condition_add(cm_raw, MDPRIOR == "1"), + raw_var = "MDPRIOR", + tgt_var = "CMSTRTPT", + tgt_val = "BEFORE", + ct_spec = study_ct, + ct_clst = "C66728", + id_vars = oak_id_vars() + ) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm, + display_vars = exprs( + oak_id, raw_source, patient_number, CMTRT, CMGRPID, CMDOSU, CMSTDTC, CMSTRTPT + ) +) +``` + +The `condition_add` function adds additional metadata to the records in the raw dataset that meets the condition. Refer to the function documentation for more details. `hardcode_ct` function uses the additional metadata to find the records that meet the criteria and map them accordingly. + +### hardcode_no_ct and condition_add {#hardcode_no_ct} + +The mapping logic for `CMSTTPT` is as follows: `If the collected value in the raw variable MDPRIOR and raw dataset cm_raw equals to 1, then CM.CMSTTPT == 'SCREENING'.` The `hardcode_no_ct` function is used to map the CMSTTPT as it involves hardcoding a specific value to an SDTM variable without controlled terminology. The `condition_add` function filters the raw dataset based on a particular condition, and the `hardcode_no_ct` function performs the mapping. + +```{r eval=TRUE} +cm <- cm %>% + # Map qualifier CMSTTPT Annotation text is If MDPRIOR == 1 then CM.CMSTTPT = 'SCREENING' + hardcode_no_ct( + raw_dat = condition_add(cm_raw, MDPRIOR == "1"), + raw_var = "MDPRIOR", + tgt_var = "CMSTTPT", + tgt_val = "SCREENING", + id_vars = oak_id_vars() + ) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm, + display_vars = exprs( + oak_id, raw_source, patient_number, CMTRT, CMGRPID, CMDOSU, CMSTDTC, CMSTRTPT, CMSTTPT + ) +) +``` + +### condition_add involving target domain {#condition_add_tar} + +In the mapping for `CMSTRTPT` and `CMSTTTPT`, the `condition_add` function is used in the raw dataset. In this mapping, we can explore how to use `condition_add` to add a filter condition based on the target SDTM variable. + +The mapping logic for `CMDOSFRQ` is `If CMTRT is not null, then map the collected value in raw dataset cm_raw and raw variable MDFRQ to CMDOSFRQ.` This may or may not represent a valid SDTM mapping in an actual study, but it can be used as an example. + +In this mapping, the `condition_add` function filters the cm domain created in the previous step and adds metadata to the records where it meets the condition. The `assign_ct` function uses the additional metadata to find the records that meet the criteria and map them accordingly. + +```{r eval=TRUE} +cm <- cm %>% + # Map qualifier CMDOSFRQ Annotation text is If CMTRT is not null then map + # the collected value in raw dataset cm_raw and raw variable MDFRQ to CMDOSFRQ + { + assign_ct( + raw_dat = cm_raw, + raw_var = "MDFRQ", + tgt_dat = condition_add(., !is.na(CMTRT)), + tgt_var = "CMDOSFRQ", + ct_spec = study_ct, + ct_clst = "C66728", + id_vars = oak_id_vars() + ) + } +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm, + display_vars = exprs( + oak_id, raw_source, patient_number, CMTRT, CMGRPID, CMDOSU, CMSTDTC, CMSTRTPT, CMSTTPT, CMDOSFRQ + ) +) +``` + +Remember to use additional curly braces in the function call when using the `condition_add` function on the target dataset. This is necessary because the input target dataset is represented as a `.` and is passed on from the previous step using the {magrittr} pipe operator. Currently, there is a limitation when using a nested function call with `.` to reference one of the input parameters, and this [recommended approach](https://magrittr.tidyverse.org/reference/pipe.html#using-the-dot-for-secondary-purposes) will overcome that. + +The placeholder `.` is for use with {magrittr} pipe `%>%` operator. We encourage using `.` and {magrittr} pipe `%>%` operator when using {sdtm.oak} functions. + +Another way to achieve the same outcome is by moving the 'condition_by' call up one level, as illustrated below: it is not required to use the {magrittr} pipe `%>%` or curly braces in this case. + +```{r eval=FALSE} +cm <- cm %>% + condition_add(!is.na(CMTRT)) %>% + assign_ct( + raw_dat = cm_raw, + raw_var = "DOSU", + tgt_var = "CMDOSU", + ct_spec = study_ct, + ct_clst = "C71620", + id_vars = oak_id_vars() + ) +``` + +### condition_add involving raw dataset and target domain {#condition_add_raw_tar} + +In this mapping, we can explore how to use `condition_add` to add a filter condition based on the target SDTM variable. + +The mapping logic for `CMMODIFY` is `If collected value in MODIFY in cm_raw is different to CM.CMTRT then assign the collected value to CMMODIFY in CM domain (CM.CMMODIFY)`. The `assign_no_ct` function is used to map the CMMODIFY as it involves mapping the collected value to the SDTM variable without controlled terminology. The `condition_add` function filters the raw dataset & target dataset based on a particular condition, and the `assign_no_ct` function performs the mapping. + +```{r eval=TRUE} +cm <- cm %>% + # Map CMMODIFY Annotation text If collected value in MODIFY in cm_raw is + # different to CM.CMTRT then assign the collected value to CMMODIFY in + # CM domain (CM.CMMODIFY) + { + assign_no_ct( + raw_dat = cm_raw, + raw_var = "MODIFY", + tgt_dat = condition_add(., MODIFY != CMTRT, .dat2 = cm_raw), + tgt_var = "CMMODIFY", + id_vars = oak_id_vars() + ) + } +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm, + display_vars = exprs( + oak_id, raw_source, patient_number, CMTRT, CMGRPID, CMDOSU, CMSTDTC, CMSTRTPT, CMSTTPT, CMDOSFRQ, CMMODIFY + ) +) +``` + +Another way to achieve the same outcome is by moving the 'condition_by' call up one level, as illustrated below: it is not required to use the {magrittr} pipe `%>%` or curly braces in this case. + +```{r eval=FALSE} +cm <- cm %>% + condition_add(MODIFY != CMTRT, .dat2 = cm_raw) %>% + assign_no_ct( + raw_dat = cm_raw, + raw_var = "MODIFY", + tgt_var = "CMMODIFY", + id_vars = oak_id_vars() + ) +``` + +Now, complete mapping the rest of the SDTM variables. + +```{r eval=TRUE} +cm <- cm %>% + # Map CMINDC as the collected value in MDIND to CM.CMINDC + assign_no_ct( + raw_dat = cm_raw, + raw_var = "MDIND", + tgt_var = "CMINDC", + id_vars = oak_id_vars() + ) %>% + # Map CMENDTC as the collected value in MDEDR and MDETM to CM.CMENDTC. + # This function calls create_iso8601 + assign_datetime( + raw_dat = cm_raw, + raw_var = c("MDEDR", "MDETM"), + tgt_var = "CMENDTC", + raw_fmt = c("d-m-y", "H:M"), + raw_unk = c("UN", "UNK") + ) %>% + # Map qualifier CMENRTPT as If MDONG == 1 then CM.CMENRTPT = 'ONGOING' + hardcode_ct( + raw_dat = condition_add(cm_raw, MDONG == "1"), + raw_var = "MDONG", + tgt_var = "CMENRTPT", + tgt_val = "ONGOING", + ct_spec = study_ct, + ct_clst = "C66728", + id_vars = oak_id_vars() + ) %>% + # Map qualifier CMENTPT as If MDONG == 1 then CM.CMENTPT = 'DATE OF LAST ASSESSMENT' + hardcode_no_ct( + raw_dat = condition_add(cm_raw, MDONG == "1"), + raw_var = "MDONG", + tgt_var = "CMENTPT", + tgt_val = "DATE OF LAST ASSESSMENT", + id_vars = oak_id_vars() + ) %>% + # Map qualifier CMDOS as If collected value in raw_var DOS is numeric then CM.CMDOSE + assign_no_ct( + raw_dat = condition_add(cm_raw, is.numeric(DOS)), + raw_var = "DOS", + tgt_var = "CMDOS", + id_vars = oak_id_vars() + ) %>% + # Map qualifier CMDOS as If collected value in raw_var DOS is character then CM.CMDOSTXT + assign_no_ct( + raw_dat = condition_add(cm_raw, is.character(DOS)), + raw_var = "DOS", + tgt_var = "CMDOSTXT", + id_vars = oak_id_vars() + ) %>% + # Map qualifier CMDOSU as the collected value in the cm_raw dataset DOSU variable to CM.CMDOSU + assign_ct( + raw_dat = cm_raw, + raw_var = "DOSU", + tgt_var = "CMDOSU", + ct_spec = study_ct, + ct_clst = "C71620", + id_vars = oak_id_vars() + ) %>% + # Map qualifier CMDOSFRM as the collected value in the cm_raw dataset MDFORM variable to CM.CMDOSFRM + assign_ct( + raw_dat = cm_raw, + raw_var = "MDFORM", + tgt_var = "CMDOSFRM", + ct_spec = study_ct, + ct_clst = "C66726", + id_vars = oak_id_vars() + ) %>% + # Map CMROUTE as the collected value in the cm_raw dataset MDRTE variable to CM.CMROUTE + assign_ct( + raw_dat = cm_raw, + raw_var = "MDRTE", + tgt_var = "CMROUTE", + ct_spec = study_ct, + ct_clst = "C66729", + id_vars = oak_id_vars() + ) %>% + # Map qualifier CMPROPH as If MDPROPH == 1 then CM.CMPROPH = 'Y' + hardcode_ct( + raw_dat = condition_add(cm_raw, MDPROPH == "1"), + raw_var = "MDPROPH", + tgt_var = "CMPROPH", + tgt_val = "Y", + ct_spec = study_ct, + ct_clst = "C66742", + id_vars = oak_id_vars() + ) %>% + # Map CMDRG as the collected value in the cm_raw dataset CMDRG variable to CM.CMDRG + assign_no_ct( + raw_dat = cm_raw, + raw_var = "CMDRG", + tgt_var = "CMDRG", + id_vars = oak_id_vars() + ) %>% + # Map CMDRGCD as the collected value in the cm_raw dataset CMDRGCD variable to CM.CMDRGCD + assign_no_ct( + raw_dat = cm_raw, + raw_var = "CMDRGCD", + tgt_var = "CMDRGCD", + id_vars = oak_id_vars() + ) %>% + # Map CMDECOD as the collected value in the cm_raw dataset CMDECOD variable to CM.CMDECOD + assign_no_ct( + raw_dat = cm_raw, + raw_var = "CMDECOD", + tgt_var = "CMDECOD", + id_vars = oak_id_vars() + ) %>% + # Map CMPNCD as the collected value in the cm_raw dataset CMPNCD variable to CM.CMPNCD + assign_no_ct( + raw_dat = cm_raw, + raw_var = "CMPNCD", + tgt_var = "CMPNCD", + id_vars = oak_id_vars() + ) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm, + display_vars = exprs( + oak_id, raw_source, patient_number, CMTRT, CMGRPID, CMDOSU, CMSTDTC, + CMSTRTPT, CMSTTPT, CMDOSFRQ, CMMODIFY, CMINDC, CMENDTC, CMENRTPT, CMENTPT, + CMDOS, CMDOSTXT, CMDOSU, CMDOSFRM, CMROUTE, CMPROPH, CMDRG, CMDRGCD, + CMDECOD, CMPNCD + ) +) +``` + +## Repeat Map Topic and Map Rest {#repeatsteps} + +There is only one topic variable in this raw data source, and there are no additional topic variable mappings. Users can proceed to the next step. This is required only if there is more than one topic variable to map. + +## Create SDTM derived variables {#derivedvars} + +The SDTM derived variables or any SDTM mapping that is applicable to all the records in the `cm` dataset produced in the previous step cam be created now. In this example, we will create the `CMSEQ` variable. The mapping logic is `Create a sequence number for each record in the CM domain`. + +```{r eval=TRUE} +cm <- cm %>% + # The below mappings are applicable to all the records in the cm domain, + # hence can be derived using mutate statement. + dplyr::mutate( + STUDYID = "test_study", + DOMAIN = "CM", + CMCAT = "GENERAL CONMED", + USUBJID = paste0("test_study", "-", cm_raw$PATNUM) + ) %>% + # derive sequence number + # derive_seq(tgt_var = "CMSEQ", + # rec_vars= c("USUBJID", "CMGRPID")) %>% + derive_study_day( + sdtm_in = ., + dm_domain = dm, + tgdt = "CMENDTC", + refdt = "RFXSTDTC", + study_day_var = "CMENDY" + ) %>% + derive_study_day( + sdtm_in = ., + dm_domain = dm, + tgdt = "CMSTDTC", + refdt = "RFXSTDTC", + study_day_var = "CMSTDY" + ) %>% + # Add code for derive Baseline flag. + dplyr::select("STUDYID", "DOMAIN", "USUBJID", everything()) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + cm, + display_vars = exprs( + oak_id, raw_source, patient_number, STUDYID, DOMAIN, USUBJID, CMGRPID, + CMTRT, CMDOSU, CMSTDTC, CMSTRTPT, CMSTTPT, CMDOSFRQ, CMMODIFY, CMINDC, + CMENDTC, CMENRTPT, CMENTPT, CMDOS, CMDOSTXT, CMDOSU, CMDOSFRM, CMROUTE, + CMPROPH, CMDRG, CMDRGCD, CMDECOD, CMPNCD, CMSTDY, CMENDY + ) +) +``` + + +## Add Labels and Attributes {#attributes} + +Yet to be developed. diff --git a/vignettes/articles/findings_domain.Rmd b/vignettes/articles/findings_domain.Rmd new file mode 100644 index 00000000..d2145a1c --- /dev/null +++ b/vignettes/articles/findings_domain.Rmd @@ -0,0 +1,559 @@ +--- +title: "Creating an Findings SDTM domain" +output: + rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Creating an Findings SDTM domain} + %\VignetteEncoding{UTF-8} + %\VignetteEngine{knitr::rmarkdown} +--- + +```{r setup, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) + +library(sdtm.oak) +library(admiraldev) +library(rlang) +library(dplyr, warn.conflicts = FALSE) +``` + +# Introduction + +This article describes how to create a Findings SDTM domain using the {sdtm.oak} package. Examples are currently presented and tested in the context of the VS domain. + +Before reading this article, it is recommended that users review the "Creating an Events Domain" article, which provides a detailed explanation of various concepts in {sdtm.oak}, such as `oak_id_vars`, `condition_add`, etc. It also offers guidance on which mapping algorithms or functions to use for different mappings and provides a more detailed explanation of how these mapping algorithms or functions work. + +In this article, we will dive directly into programming and provide further explanation only where it is required. + +# Programming workflow + +In {sdtm.oak} we process one raw dataset at a time. Similar raw datasets (example Vital Signs - Screening (OID - vs_raw), Vital Signs - Treatment (OID - vs_t_raw)) can be stacked together before processing. + +* [Read in data](#readdata) +* [Create oak_id_vars](#oakidvars) +* [Read in CT](#readct) +* [Map Topic Variable](#maptopic) +* [Map Rest of the Variables](#maprest) +* [Repeat Map Topic and Map Rest](#repeatsteps) + +Repeat the above steps for different raw datasets before proceeding with the below steps. + +* [Create SDTM derived variables](#derivedvars) +* [Add Labels and Attributes](#attributes) + +## Read in data {#readdata} + +Read all the raw datasets into the environment. In this example, the raw dataset name is `vs_raw`. Users can read it from the package using the below code: + +```{r eval=TRUE} +vs_raw <- read.csv(system.file("raw_data/vitals_raw_data.csv", + package = "sdtm.oak" +)) +``` + + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + vs_raw, + display_vars = exprs( + PATNUM, FORML, ASMNTDN, TMPTC, VTLD, VTLTM, SUBPOS, SYS_BP, DIA_BP, + PULSE, RESPRT, TEMP, TEMPLOC, OXY_SAT, LAT, LOC + ) +) +``` + +## Create oak_id_vars {#oakidvars} + +```{r eval=TRUE} +vs_raw <- vs_raw %>% + generate_oak_id_vars( + pat_var = "PATNUM", + raw_src = "vitals" + ) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + vs_raw, + display_vars = exprs( + oak_id, raw_source, patient_number, PATNUM, FORML, SYS_BP, DIA_BP + ) +) +``` + +Read in the DM domain + +```{r eval=TRUE, echo=FALSE} +dm <- read.csv(system.file("raw_data/dm.csv", + package = "sdtm.oak" +)) +``` + + +## Read in CT {#readct} + +Controlled Terminology is part of the SDTM specification and it is prepared by the user. In this example, the study controlled terminology name is `sdtm_ct.csv`. Users can read it from the package using the below code: + +```{r eval=TRUE} +study_ct <- read.csv(system.file("raw_data/sdtm_ct.csv", + package = "sdtm.oak" +)) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + study_ct, + display_vars = exprs( + codelist_code, term_code, term_value, collected_value, term_preferred_term, + term_synonyms + ) +) +``` + +## Map Topic Variable {#maptopic} + +This raw dataset has multiple topic variables. Lets start with the first topic variable. Map topic variable SYSBP from the raw variable SYS_BP. + +```{r eval=TRUE} +# Map topic variable SYSBP and its qualifiers. +vs_sysbp <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "SYS_BP", + tgt_var = "VSTESTCD", + tgt_val = "SYSBP", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + # Filter for records where VSTESTCD is not empty. + # Only these records need qualifier mappings. + dplyr::filter(!is.na(.data$VSTESTCD)) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + vs_sysbp, + display_vars = exprs( + oak_id, raw_source, patient_number, VSTESTCD + ) +) +``` + +## Map Rest of the Variables {#maprest} + +Map rest of the variables applicable to the topic variable SYSBP. This can include qualifiers, identifier and timing variables. + +```{r eval=TRUE} +# Map topic variable SYSBP and its qualifiers. +vs_sysbp <- vs_sysbp %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "SYS_BP", + tgt_var = "VSTEST", + tgt_val = "Systolic Blood Pressure", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "SYS_BP", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "SYS_BP", + tgt_var = "VSORRESU", + tgt_val = "mmHg", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) %>% + # Map VSPOS using assign_ct algorithm + assign_ct( + raw_dat = vs_raw, + raw_var = "SUBPOS", + tgt_var = "VSPOS", + ct_spec = study_ct, + ct_clst = "C71148", + id_vars = oak_id_vars() + ) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + vs_sysbp, + display_vars = exprs( + oak_id, raw_source, patient_number, VSTESTCD, VSTEST, VSORRES, VSORRESU, VSPOS + ) +) +``` + +## Repeat Map Topic and Map Rest {#repeatsteps} + +This raw data source has other topic variables DIABP, PULSE, RESP, TEMP, OXYSAT, VSALL and its corresponding qualifiers. Repeat mapping topic and qualifiers for each topic variable. + +```{r eval=TRUE} +# Map topic variable DIABP and its qualifiers. +vs_diabp <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "DIA_BP", + tgt_var = "VSTESTCD", + tgt_val = "DIABP", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "DIA_BP", + tgt_var = "VSTEST", + tgt_val = "Diastolic Blood Pressure", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "DIA_BP", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "DIA_BP", + tgt_var = "VSORRESU", + tgt_val = "mmHg", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) %>% + # Map VSPOS using assign_ct algorithm + assign_ct( + raw_dat = vs_raw, + raw_var = "SUBPOS", + tgt_var = "VSPOS", + ct_spec = study_ct, + ct_clst = "C71148", + id_vars = oak_id_vars() + ) + +# Map topic variable PULSE and its qualifiers. +vs_pulse <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "PULSE", + tgt_var = "VSTESTCD", + tgt_val = "PULSE", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "PULSE", + tgt_var = "VSTEST", + tgt_val = "Pulse Rate", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "PULSE", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "PULSE", + tgt_var = "VSORRESU", + tgt_val = "beats/min", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) + +# Map topic variable RESP from the raw variable RESPRT and its qualifiers. +vs_resp <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "RESPRT", + tgt_var = "VSTESTCD", + tgt_val = "RESP", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "RESPRT", + tgt_var = "VSTEST", + tgt_val = "Respiratory Rate", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "RESPRT", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "RESPRT", + tgt_var = "VSORRESU", + tgt_val = "breaths/min", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) + +# Map topic variable TEMP from raw variable TEMP and its qualifiers. +vs_temp <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "TEMP", + tgt_var = "VSTESTCD", + tgt_val = "TEMP", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "TEMP", + tgt_var = "VSTEST", + tgt_val = "Temperature", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "TEMP", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "TEMP", + tgt_var = "VSORRESU", + tgt_val = "C", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) %>% + # Map VSLOC from TEMPLOC using assign_ct + assign_ct( + raw_dat = vs_raw, + raw_var = "TEMPLOC", + tgt_var = "VSLOC", + ct_spec = study_ct, + ct_clst = "C74456", + id_vars = oak_id_vars() + ) + +# Map topic variable OXYSAT from raw variable OXY_SAT and its qualifiers. +vs_oxysat <- + hardcode_ct( + raw_dat = vs_raw, + raw_var = "OXY_SAT", + tgt_var = "VSTESTCD", + tgt_val = "OXYSAT", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "OXY_SAT", + tgt_var = "VSTEST", + tgt_val = "Oxygen Saturation", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) %>% + # Map VSORRES using assign_no_ct algorithm + assign_no_ct( + raw_dat = vs_raw, + raw_var = "OXY_SAT", + tgt_var = "VSORRES", + id_vars = oak_id_vars() + ) %>% + # Map VSORRESU using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "OXY_SAT", + tgt_var = "VSORRESU", + tgt_val = "%", + ct_spec = study_ct, + ct_clst = "C66770", + id_vars = oak_id_vars() + ) %>% + # Map VSLAT using assign_ct from raw variable LAT + assign_ct( + raw_dat = vs_raw, + raw_var = "LAT", + tgt_var = "VSLAT", + ct_spec = study_ct, + ct_clst = "C99073", + id_vars = oak_id_vars() + ) %>% + # Map VSLOC using assign_ct from raw variable LOC + assign_ct( + raw_dat = vs_raw, + raw_var = "LOC", + tgt_var = "VSLOC", + ct_spec = study_ct, + ct_clst = "C74456", + id_vars = oak_id_vars() + ) + +# Map topic variable VSALL from raw variable ASMNTDN with the logic if ASMNTDN == 1 then VSTESTCD = VSALL +vs_vsall <- + hardcode_ct( + raw_dat = condition_add(vs_raw, ASMNTDN == 1L), + raw_var = "ASMNTDN", + tgt_var = "VSTESTCD", + tgt_val = "VSALL", + ct_spec = study_ct, + ct_clst = "C66741" + ) %>% + dplyr::filter(!is.na(.data$VSTESTCD)) %>% + # Map VSTEST using hardcode_ct algorithm + hardcode_ct( + raw_dat = vs_raw, + raw_var = "ASMNTDN", + tgt_var = "VSTEST", + tgt_val = "Vital Signs", + ct_spec = study_ct, + ct_clst = "C67153", + id_vars = oak_id_vars() + ) +``` + +Now that all the topic variable and its qualifier mappings are complete, combine all the datasets and proceed with mapping qualifiers, identifiers and timing variables applicable to all topic variables. + +```{r, eval=TRUE} +# Combine all the topic variables into a single data frame and map qualifiers +# applicable to all topic variables +vs <- dplyr::bind_rows( + vs_vsall, vs_sysbp, vs_diabp, vs_pulse, vs_resp, + vs_temp, vs_oxysat +) %>% + # Map qualifiers common to all topic variables + # Map VSDTC using assign_ct algorithm + assign_datetime( + raw_dat = vs_raw, + raw_var = c("VTLD", "VTLTM"), + tgt_var = "VSDTC", + raw_fmt = c(list(c("d-m-y", "dd-mmm-yyyy")), "H:M") + ) %>% + # Map VSTPT from TMPTC using assign_ct + assign_ct( + raw_dat = vs_raw, + raw_var = "TMPTC", + tgt_var = "VSTPT", + ct_spec = study_ct, + ct_clst = "TPT", + id_vars = oak_id_vars() + ) %>% + # Map VSTPTNUM from TMPTC using assign_ct + assign_ct( + raw_dat = vs_raw, + raw_var = "TMPTC", + tgt_var = "VSTPTNUM", + ct_spec = study_ct, + ct_clst = "TPTNUM", + id_vars = oak_id_vars() + ) %>% + # Map VISIT from INSTANCE using assign_ct + assign_ct( + raw_dat = vs_raw, + raw_var = "INSTANCE", + tgt_var = "VISIT", + ct_spec = study_ct, + ct_clst = "VISIT", + id_vars = oak_id_vars() + ) %>% + # Map VISITNUM from INSTANCE using assign_ct + assign_ct( + raw_dat = vs_raw, + raw_var = "INSTANCE", + tgt_var = "VISITNUM", + ct_spec = study_ct, + ct_clst = "VISITNUM", + id_vars = oak_id_vars() + ) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + vs, + display_vars = exprs( + oak_id, raw_source, patient_number, VSTESTCD, VSTEST, VSORRES, VSORRESU, VSPOS, + VSLAT, VSDTC, VSTPT, VSTPTNUM, VISIT, VISITNUM + ) +) +``` + +## Create SDTM derived variables {#derivedvars} + +Create derived variables applicable to all topic variables. + +```{r eval=TRUE} +vs <- vs %>% + dplyr::mutate( + STUDYID = "test_study", + DOMAIN = "VS", + VSCAT = "VITAL SIGNS", + USUBJID = paste0("test_study", "-", .data$patient_number) + ) %>% + # derive_seq(tgt_var = "VSSEQ", + # rec_vars= c("USUBJID", "VSTRT")) %>% + derive_study_day( + sdtm_in = ., + dm_domain = dm, + tgdt = "VSDTC", + refdt = "RFXSTDTC", + study_day_var = "VSDY" + ) %>% + dplyr::select("STUDYID", "DOMAIN", "USUBJID", everything()) +``` + +```{r, eval=TRUE, echo=FALSE} +sdtm.oak:::dataset_oak_vignette( + vs, + display_vars = exprs( + STUDYID, DOMAIN, USUBJID, VSTESTCD, VSTEST, VSORRES, VSORRESU, VSPOS, + VSLAT, VSTPT, VSTPTNUM, VISIT, VISITNUM, VSDTC, VSDY + ) +) +``` + +## Add Labels and Attributes {#attributes} + +Yet to be developed. diff --git a/vignettes/articles/reusable_algorithms.jpg b/vignettes/articles/reusable_algorithms.jpg index 71c8962b..5b5bd027 100644 Binary files a/vignettes/articles/reusable_algorithms.jpg and b/vignettes/articles/reusable_algorithms.jpg differ