Create a shift table ready to be used with tabulator().

The function is transforming a dataset representing some 'Laboratory Tests Results' structured as CDISC clinical trial data sets format to a dataset representing the shift table.

Shift tables are tables used in clinical trial analysis. They show the progression of change from the baseline, with the progression often being along time; the number of subjects is displayed in different range (e.g. low, normal, or high) at baseline and at selected time points or intervals.

shift_table(
  x,
  cn_visit = "VISIT",
  cn_visit_num = "VISITNUM",
  cn_grade = "LBNRIND",
  cn_usubjid = "USUBJID",
  cn_lab_cat = NA_character_,
  cn_is_baseline = "LBBLFL",
  baseline_identifier = "Y",
  cn_treatment = NA_character_,
  grade_levels = c("LOW", "NORMAL", "HIGH"),
  grade_labels = c("Low", "Normal", "High")
)

Arguments

x

Laboratory Tests Results data frame.

cn_visit

column name containing visit names, default to "VISIT".

cn_visit_num

column name containing visit numbers, default to "VISITNUM".

cn_grade

column name containing reference range indicators, default to "LBNRIND".

cn_usubjid

column name containing unique subject inditifiers, default to "USUBJID".

cn_lab_cat

column name containing lab tests or examination names, default to "LBTEST".

cn_is_baseline

column name containing baseline flags, default to "LBBLFL".

baseline_identifier

baseline flag value to use for baseline identification. Its default is "Y".

cn_treatment

column name containing treatment names, default to NA.

grade_levels

levels to use for reference range indicators

grade_labels

labels to use for reference range indicators

Value

the shift table as a data.frame. Additionnal elements are provided in attributes:

  • "VISIT_N": count of unique subject id per visits, labs and eventually treatments. This element is supposed to be used as value for argument hidden_data of function tabulator().

  • "FUN_VISIT": a utility function to easily turn visit column as a factor column. It should be applied after the shift table creation.

  • "FUN_GRADE": a utility function to easily turn grade column as a factor column. It adds "MISSING/Missing" and "SUM/Sum" at the end of the set of values specified in arguments grade_levels and grade_labels. It should be applied after the shift table creation.

Examples

library(data.table)
library(flextable)

# data simulation ----
USUBJID <- sprintf("01-ABC-%04.0f", 1:200)
VISITS <- c("SCREENING 1", "WEEK 2", "MONTH 3")
LBTEST <- c("Albumin", "Sodium")

VISITNUM <- seq_along(VISITS)
LBBLFL <- rep(NA_character_, length(VISITNUM))
LBBLFL[1] <- "Y"

VISIT <- data.frame(VISIT = VISITS, VISITNUM = VISITNUM,
  LBBLFL = LBBLFL, stringsAsFactors = FALSE)
labdata <- expand.grid(USUBJID = USUBJID,  LBTEST = LBTEST,
                    VISITNUM = VISITNUM,
                    stringsAsFactors = FALSE)
setDT(labdata)

labdata <- merge(labdata, VISIT, by = "VISITNUM")

subject_elts <- unique(labdata[, .SD, .SDcols = "USUBJID"])
subject_elts <- unique(subject_elts)
subject_elts[, c("TREAT") := list(
  sample(x = c("Treatment", "Placebo"), size = .N, replace = TRUE))]
#>          USUBJID     TREAT
#>   1: 01-ABC-0001   Placebo
#>   2: 01-ABC-0002   Placebo
#>   3: 01-ABC-0003   Placebo
#>   4: 01-ABC-0004 Treatment
#>   5: 01-ABC-0005   Placebo
#>  ---                      
#> 196: 01-ABC-0196 Treatment
#> 197: 01-ABC-0197 Treatment
#> 198: 01-ABC-0198 Treatment
#> 199: 01-ABC-0199   Placebo
#> 200: 01-ABC-0200 Treatment
subject_elts[, c("TREAT"):= list(
  factor(.SD$TREAT, levels = c("Treatment", "Placebo")))]
#>          USUBJID     TREAT
#>   1: 01-ABC-0001   Placebo
#>   2: 01-ABC-0002   Placebo
#>   3: 01-ABC-0003   Placebo
#>   4: 01-ABC-0004 Treatment
#>   5: 01-ABC-0005   Placebo
#>  ---                      
#> 196: 01-ABC-0196 Treatment
#> 197: 01-ABC-0197 Treatment
#> 198: 01-ABC-0198 Treatment
#> 199: 01-ABC-0199   Placebo
#> 200: 01-ABC-0200 Treatment
setDF(subject_elts)
labdata <- merge(labdata, subject_elts,
  by = "USUBJID", all.x = TRUE, all.y = FALSE)
labdata[, c("LBNRIND"):= list(
  sample(x = c("LOW", "NORMAL", "HIGH"), size = .N,
         replace = TRUE, prob = c(.03, .9, .07)))]
#>           USUBJID VISITNUM  LBTEST       VISIT LBBLFL     TREAT LBNRIND
#>    1: 01-ABC-0001        1 Albumin SCREENING 1      Y   Placebo  NORMAL
#>    2: 01-ABC-0001        1  Sodium SCREENING 1      Y   Placebo  NORMAL
#>    3: 01-ABC-0001        2 Albumin      WEEK 2   <NA>   Placebo  NORMAL
#>    4: 01-ABC-0001        2  Sodium      WEEK 2   <NA>   Placebo    HIGH
#>    5: 01-ABC-0001        3 Albumin     MONTH 3   <NA>   Placebo  NORMAL
#>   ---                                                                  
#> 1196: 01-ABC-0200        1  Sodium SCREENING 1      Y Treatment  NORMAL
#> 1197: 01-ABC-0200        2 Albumin      WEEK 2   <NA> Treatment  NORMAL
#> 1198: 01-ABC-0200        2  Sodium      WEEK 2   <NA> Treatment  NORMAL
#> 1199: 01-ABC-0200        3 Albumin     MONTH 3   <NA> Treatment  NORMAL
#> 1200: 01-ABC-0200        3  Sodium     MONTH 3   <NA> Treatment  NORMAL

setDF(labdata)




# shift table calculation ----

SHIFT_TABLE <- shift_table(
  x = labdata, cn_visit = "VISIT",
  cn_grade = "LBNRIND",
  cn_usubjid = "USUBJID",
  cn_lab_cat = "LBTEST",
  cn_treatment = "TREAT",
  cn_is_baseline = "LBBLFL",
  baseline_identifier = "Y",
  grade_levels = c("LOW", "NORMAL", "HIGH"))

# get attrs for post treatment ----
SHIFT_TABLE_VISIT <- attr(SHIFT_TABLE, "VISIT_N")
visit_as_factor <- attr(SHIFT_TABLE, "FUN_VISIT")
range_as_factor <- attr(SHIFT_TABLE, "FUN_GRADE")

# post treatments ----
SHIFT_TABLE$VISIT = visit_as_factor(SHIFT_TABLE$VISIT)
SHIFT_TABLE$BASELINE = range_as_factor(SHIFT_TABLE$BASELINE)
SHIFT_TABLE$LBNRIND = range_as_factor(SHIFT_TABLE$LBNRIND)

SHIFT_TABLE_VISIT$VISIT = visit_as_factor(SHIFT_TABLE_VISIT$VISIT)

# tabulator ----

my_format <- function(z) {
  formatC(z * 100, digits = 1, format = "f",
          flag = "0", width = 4)
}

tab <- tabulator(
  x = SHIFT_TABLE,
  hidden_data = SHIFT_TABLE_VISIT,
  row_compose = list(
    VISIT = as_paragraph(VISIT, "\n(N=", N_VISIT, ")")
  ),
  rows = c("LBTEST", "VISIT", "BASELINE"),
  columns = c("TREAT", "LBNRIND"),
  `n` = as_paragraph(N),
  `%` = as_paragraph(as_chunk(PCT, formatter = my_format))
)

# as_flextable ----

ft_1 <- as_flextable(
  x = tab, separate_with = "VISIT",
  label_rows = c(LBTEST = "Lab Test", VISIT = "Visit",
                 BASELINE = "Reference Range Indicator"))

ft_1
#> a flextable object.
#> col_keys: `LBTEST`, `VISIT`, `BASELINE`, `dummy1`, `@Treatment@Low@n`, `@Treatment@Low@%`, `dummy2`, `@Treatment@Normal@n`, `@Treatment@Normal@%`, `dummy3`, `@Treatment@High@n`, `@Treatment@High@%`, `dummy4`, `@Treatment@Missing@n`, `@Treatment@Missing@%`, `dummy5`, `@Placebo@Low@n`, `@Placebo@Low@%`, `dummy6`, `@Placebo@Normal@n`, `@Placebo@Normal@%`, `dummy7`, `@Placebo@High@n`, `@Placebo@High@%`, `dummy8`, `@Placebo@Missing@n`, `@Placebo@Missing@%` 
#> header has 3 row(s) 
#> body has 40 row(s) 
#> original dataset sample: 
#>     LBTEST  VISIT BASELINE N@Treatment@Low N@Treatment@Normal N@Treatment@High
#> 11 Albumin WEEK 2      Low               0                  3                0
#> 12 Albumin WEEK 2      Low               0                  3                0
#> 13 Albumin WEEK 2   Normal               5                 75                5
#> 14 Albumin WEEK 2   Normal               5                 75                5
#> 15 Albumin WEEK 2     High               0                  5                1
#>    N@Treatment@Missing N@Placebo@Low N@Placebo@Normal N@Placebo@High
#> 11                   0             0                0              2
#> 12                   0             0                0              2
#> 13                   0             4               87              8
#> 14                   0             4               87              8
#> 15                   0             0                4              1
#>    N@Placebo@Missing PCT@Treatment@Low PCT@Treatment@Normal PCT@Treatment@High
#> 11                 0        0.00000000           0.03191489         0.00000000
#> 12                 0        0.00000000           0.03191489         0.00000000
#> 13                 0        0.05319149           0.79787234         0.05319149
#> 14                 0        0.05319149           0.79787234         0.05319149
#> 15                 0        0.00000000           0.05319149         0.01063830
#>    PCT@Treatment@Missing PCT@Placebo@Low PCT@Placebo@Normal PCT@Placebo@High
#> 11                     0      0.00000000         0.00000000      0.018867925
#> 12                     0      0.00000000         0.00000000      0.018867925
#> 13                     0      0.03773585         0.82075472      0.075471698
#> 14                     0      0.03773585         0.82075472      0.075471698
#> 15                     0      0.00000000         0.03773585      0.009433962
#>    PCT@Placebo@Missing n@Treatment@Low n@Treatment@Normal n@Treatment@High
#> 11                   0                                                    
#> 12                   0                                                    
#> 13                   0                                                    
#> 14                   0                                                    
#> 15                   0                                                    
#>    n@Treatment@Missing n@Placebo@Low n@Placebo@Normal n@Placebo@High
#> 11                                                                  
#> 12                                                                  
#> 13                                                                  
#> 14                                                                  
#> 15                                                                  
#>    n@Placebo@Missing %@Treatment@Low %@Treatment@Normal %@Treatment@High
#> 11                                                                      
#> 12                                                                      
#> 13                                                                      
#> 14                                                                      
#> 15                                                                      
#>    %@Treatment@Missing %@Placebo@Low %@Placebo@Normal %@Placebo@High
#> 11                                                                  
#> 12                                                                  
#> 13                                                                  
#> 14                                                                  
#> 15                                                                  
#>    %@Placebo@Missing     TREAT N_VISIT dummy1 @Treatment@Low@n @Treatment@Low@%
#> 11                   Treatment      94                                         
#> 12                     Placebo     106                                         
#> 13                   Treatment      94                                         
#> 14                     Placebo     106                                         
#> 15                   Treatment      94                                         
#>    dummy2 @Treatment@Normal@n @Treatment@Normal@% dummy3 @Treatment@High@n
#> 11                                                                        
#> 12                                                                        
#> 13                                                                        
#> 14                                                                        
#> 15                                                                        
#>    @Treatment@High@% dummy4 @Treatment@Missing@n @Treatment@Missing@% dummy5
#> 11                                                                          
#> 12                                                                          
#> 13                                                                          
#> 14                                                                          
#> 15                                                                          
#>    @Placebo@Low@n @Placebo@Low@% dummy6 @Placebo@Normal@n @Placebo@Normal@%
#> 11                                                                         
#> 12                                                                         
#> 13                                                                         
#> 14                                                                         
#> 15                                                                         
#>    dummy7 @Placebo@High@n @Placebo@High@% dummy8 @Placebo@Missing@n
#> 11                                                                 
#> 12                                                                 
#> 13                                                                 
#> 14                                                                 
#> 15                                                                 
#>    @Placebo@Missing@%
#> 11                   
#> 12                   
#> 13                   
#> 14                   
#> 15