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")
)
Laboratory Tests Results data frame.
column name containing visit names, default to "VISIT".
column name containing visit numbers, default to "VISITNUM".
column name containing reference range indicators, default to "LBNRIND".
column name containing unique subject inditifiers, default to "USUBJID".
column name containing lab tests or examination names, default to "LBTEST".
column name containing baseline flags, default to "LBBLFL".
baseline flag value to use for baseline identification. Its default is "Y".
column name containing treatment names, default to NA
.
levels to use for reference range indicators
labels to use for reference range indicators
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.
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
#> <char> <char>
#> 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
#> <char> <fctr>
#> 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)
)
)]
#> Key: <USUBJID>
#> USUBJID VISITNUM LBTEST VISIT LBBLFL TREAT LBNRIND
#> <char> <int> <char> <char> <char> <fctr> <char>
#> 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
Lab Test
Visit
Reference Range Indicator
Treatment
Placebo
Low
Normal
High
Missing
Low
Normal
High
Missing
n
%
n
%
n
%
n
%
n
%
n
%
n
%
n
%
Albumin
WEEK 2
(N=94)
Low
0
00.0
3
03.2
0
00.0
0
00.0
0
00.0
0
00.0
2
01.9
0
00.0
0
00.0
3
03.2
0
00.0
0
00.0
0
00.0
0
00.0
2
01.9
0
00.0
Normal
5
05.3
75
79.8
5
05.3
0
00.0
4
03.8
87
82.1
8
07.5
0
00.0
5
05.3
75
79.8
5
05.3
0
00.0
4
03.8
87
82.1
8
07.5
0
00.0
High
0
00.0
5
05.3
1
01.1
0
00.0
0
00.0
4
03.8
1
00.9
0
00.0
0
00.0
5
05.3
1
01.1
0
00.0
0
00.0
4
03.8
1
00.9
0
00.0
Missing
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
Sum
5
05.3
83
88.3
6
06.4
0
00.0
4
03.8
91
85.8
11
10.4
0
00.0
5
05.3
83
88.3
6
06.4
0
00.0
4
03.8
91
85.8
11
10.4
0
00.0
MONTH 3
(N=94)
Low
0
00.0
2
02.1
1
01.1
0
00.0
0
00.0
2
01.9
0
00.0
0
00.0
0
00.0
2
02.1
1
01.1
0
00.0
0
00.0
2
01.9
0
00.0
0
00.0
Normal
4
04.3
70
74.5
11
11.7
0
00.0
4
03.8
90
84.9
5
04.7
0
00.0
4
04.3
70
74.5
11
11.7
0
00.0
4
03.8
90
84.9
5
04.7
0
00.0
High
0
00.0
5
05.3
1
01.1
0
00.0
0
00.0
4
03.8
1
00.9
0
00.0
0
00.0
5
05.3
1
01.1
0
00.0
0
00.0
4
03.8
1
00.9
0
00.0
Missing
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
Sum
4
04.3
77
81.9
13
13.8
0
00.0
4
03.8
96
90.6
6
05.7
0
00.0
4
04.3
77
81.9
13
13.8
0
00.0
4
03.8
96
90.6
6
05.7
0
00.0
Sodium
WEEK 2
(N=94)
Low
0
00.0
3
03.2
0
00.0
0
00.0
0
00.0
2
01.9
1
00.9
0
00.0
0
00.0
3
03.2
0
00.0
0
00.0
0
00.0
2
01.9
1
00.9
0
00.0
Normal
3
03.2
71
75.5
8
08.5
0
00.0
4
03.8
83
78.3
10
09.4
0
00.0
3
03.2
71
75.5
8
08.5
0
00.0
4
03.8
83
78.3
10
09.4
0
00.0
High
0
00.0
9
09.6
0
00.0
0
00.0
0
00.0
6
05.7
0
00.0
0
00.0
0
00.0
9
09.6
0
00.0
0
00.0
0
00.0
6
05.7
0
00.0
0
00.0
Missing
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
Sum
3
03.2
83
88.3
8
08.5
0
00.0
4
03.8
91
85.8
11
10.4
0
00.0
3
03.2
83
88.3
8
08.5
0
00.0
4
03.8
91
85.8
11
10.4
0
00.0
MONTH 3
(N=94)
Low
0
00.0
3
03.2
0
00.0
0
00.0
0
00.0
3
02.8
0
00.0
0
00.0
0
00.0
3
03.2
0
00.0
0
00.0
0
00.0
3
02.8
0
00.0
0
00.0
Normal
2
02.1
75
79.8
5
05.3
0
00.0
6
05.7
86
81.1
5
04.7
0
00.0
2
02.1
75
79.8
5
05.3
0
00.0
6
05.7
86
81.1
5
04.7
0
00.0
High
1
01.1
8
08.5
0
00.0
0
00.0
0
00.0
5
04.7
1
00.9
0
00.0
1
01.1
8
08.5
0
00.0
0
00.0
0
00.0
5
04.7
1
00.9
0
00.0
Missing
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
0
00.0
Sum
3
03.2
86
91.5
5
05.3
0
00.0
6
05.7
94
88.7
6
05.7
0
00.0
3
03.2
86
91.5
5
05.3
0
00.0
6
05.7
94
88.7
6
05.7
0
00.0