The following example shows a complete program. The example illustrates how procs functions work together, and interact with other sassy functions to create a demographics table with p-value statistics.
library(sassy)
library(procs)
# Prepare Log -------------------------------------------------------------
options("logr.autolog" = TRUE,
"logr.on" = TRUE,
"logr.notes" = FALSE,
"procs.print" = FALSE)
# Get temp directory
tmp <- tempdir()
# Open log
lf <- log_open(file.path(tmp, "example1.log"))
# Prepare formats ---------------------------------------------------------
sep("Prepare formats")
put("Age categories")
agecat <- value(condition(x >= 18 & x <= 29, "18 to 29"),
condition(x >=30 & x <= 39, "30 to 39"),
condition(x >=40 & x <=49, "40 to 49"),
condition(x >= 50, ">= 50"),
condition(TRUE, "Out of range"))
put("Sex decodes")
fmt_sex <- value(condition(is.na(x), "Missing"),
condition(x == "M", "Male"),
condition(x == "F", "Female"),
condition(TRUE, "Other"))
put("Race decodes")
fmt_race <- value(condition(is.na(x), "Missing"),
condition(x == "WHITE", "White"),
condition(x == "BLACK", "Black or African American"),
condition(TRUE, "Other"))
put("Compile format catalog")
fc <- fcat(MEAN = "%.1f", STD = "(%.2f)",
Q1 = "%.1f", Q3 = "%.1f",
MIN = "%d", MAX = "%d",
CNT = "%2d", PCT = "(%5.1f%%)",
AGECAT = agecat,
SEX = fmt_sex,
RACE = fmt_race,
AOV.F = "%5.3f",
AOV.P = "(%5.3f)",
CHISQ = "%5.3f",
CHISQ.P = "(%5.3f)")
# Load and Prepare Data ---------------------------------------------------
sep("Prepare Data")
put("Create sample ADSL data.")
adsl <- read.table(header = TRUE, text = '
SUBJID ARM SEX RACE AGE
"001" "ARM A" "F" "WHITE" 19
"002" "ARM B" "F" "WHITE" 21
"003" "ARM C" "F" "WHITE" 23
"004" "ARM D" "F" "BLACK" 28
"005" "ARM A" "M" "WHITE" 37
"006" "ARM B" "M" "WHITE" 34
"007" "ARM C" "M" "WHITE" 36
"008" "ARM D" "M" "WHITE" 30
"009" "ARM A" "F" "WHITE" 39
"010" "ARM B" "F" "WHITE" 31
"011" "ARM C" "F" "BLACK" 33
"012" "ARM D" "F" "WHITE" 38
"013" "ARM A" "M" "BLACK" 37
"014" "ARM B" "M" "WHITE" 34
"015" "ARM C" "M" "WHITE" 36
"016" "ARM A" "M" "WHITE" 40')
put("Categorize AGE")
adsl$AGECAT <- fapply(adsl$AGE, agecat)
put("Log starting dataset")
put(adsl)
put("Get ARM population counts")
proc_freq(adsl, tables = ARM,
output = long,
options = v(nopercent, nonobs)) -> arm_pop
# Age Summary Block -------------------------------------------------------
sep("Create summary statistics for age")
put("Call means procedure to get summary statistics for age")
proc_means(adsl, var = AGE,
stats = v(n, mean, std, median, q1, q3, min, max),
by = ARM,
options = v(notype, nofreq)) -> age_stats
put("Combine stats")
datastep(age_stats,
format = fc,
drop = find.names(age_stats, start = 4),
{
`Mean (SD)` <- fapply2(MEAN, STD)
Median <- MEDIAN
`Q1 - Q3` <- fapply2(Q1, Q3, sep = " - ")
`Min - Max` <- fapply2(MIN, MAX, sep = " - ")
}) -> age_comb
put("Transpose ARMs into columns")
proc_transpose(age_comb,
var = names(age_comb),
copy = VAR, id = BY,
name = LABEL) -> age_trans
put("Calculate aov")
age_aov <- aov(AGE ~ ARM, data = adsl) |>
summary()
put("Get aov into proper data frame")
age_aov <- age_aov[[1]][1, c("F value", "Pr(>F)")]
names(age_aov) <- c("AOV.F", "AOV.P")
age_aov <- as.data.frame(age_aov) |> put()
put("Combine aov statistics")
datastep(age_aov,
keep = PVALUE,
format = fc,
{
PVALUE <- fapply2(AOV.F, AOV.P)
}) -> age_aov_comb
put("Append aov")
datastep(age_trans, merge = age_aov_comb, {}) -> age_block
# Sex Block ---------------------------------------------------------------
sep("Create frequency counts for SEX")
put("Get sex frequency counts")
proc_freq(adsl, tables = SEX,
by = ARM,
options = nonobs) -> sex_freq
put("Combine counts and percents.")
datastep(sex_freq,
format = fc,
rename = list(CAT = "LABEL"),
drop = v(CNT, PCT),
{
CNTPCT <- fapply2(CNT, PCT)
}) -> sex_comb
put("Transpose ARMs into columns")
proc_transpose(sex_comb, id = BY,
var = CNTPCT,
copy = VAR, by = LABEL) -> sex_trans
put("Clean up")
datastep(sex_trans, drop = NAME,
{
LABEL <- fapply(LABEL, fc$SEX)
LABEL <- factor(LABEL, levels = levels(fc$SEX))
}) -> sex_cnts
put("Sort by label")
proc_sort(sex_cnts, by = LABEL) -> sex_cnts
put("Get sex chisq")
proc_freq(adsl, tables = v(SEX * ARM),
options = v(chisq, notable)) -> sex_chisq
put("Combine chisq statistics")
datastep(sex_chisq,
format = fc,
keep = PVALUE,
{
PVALUE = fapply2(CHISQ, CHISQ.P)
}) -> sex_chisq_comb
put("Append chisq")
datastep(sex_cnts,
merge = sex_chisq_comb,
{}) -> sex_block
# Race block --------------------------------------------------------------
sep("Create frequency counts for RACE")
put("Get race frequency counts")
proc_freq(adsl, tables = RACE,
by = ARM,
options = nonobs) -> race_freq
put("Combine counts and percents.")
datastep(race_freq,
format = fc,
rename = list(CAT = "LABEL"),
drop = v(CNT, PCT),
{
CNTPCT <- fapply2(CNT, PCT)
}) -> race_comb
put("Transpose ARMs into columns")
proc_transpose(race_comb, id = BY, var = CNTPCT,
copy = VAR, by = LABEL) -> race_trans
put("Clean up")
datastep(race_trans, drop = NAME,
where = expression(del == FALSE),
{
LABEL <- fapply(LABEL, fc$RACE)
LABEL <- factor(LABEL, levels = levels(fc$RACE))
}) -> race_cnts
put("Sort by label")
proc_sort(race_cnts, by = LABEL) -> race_cnts
put("Get race chisq")
proc_freq(adsl, tables = RACE * ARM,
options = v(chisq, notable)) -> race_chisq
put("Combine chisq statistics")
datastep(race_chisq,
format = fc,
keep = c("PVALUE"),
{
PVALUE = fapply2(CHISQ, CHISQ.P)
}) -> race_chisq_comb
put("Append chisq")
datastep(race_cnts, merge = race_chisq_comb, {}) -> race_block
# Age Group Block ----------------------------------------------------------
sep("Create frequency counts for Age Group")
put("Get age group frequency counts")
proc_freq(adsl,
table = AGECAT,
by = ARM,
options = nonobs) -> ageg_freq
put("Combine counts and percents and assign age group factor for sorting")
datastep(ageg_freq,
format = fc,
keep = v(VAR, LABEL, BY, CNTPCT),
{
CNTPCT <- fapply2(CNT, PCT)
LABEL <- factor(CAT, levels = levels(fc$AGECAT))
}) -> ageg_comb
put("Sort by age group factor")
proc_sort(ageg_comb, by = v(BY, LABEL)) -> ageg_sort
put("Tranpose age group block")
proc_transpose(ageg_sort,
var = CNTPCT,
copy = VAR,
id = BY,
by = LABEL) -> ageg_trans
put("Some clean up")
datastep(ageg_trans,
drop = NAME,
{}) -> ageg_cnts
put("Get ageg chisq")
proc_freq(adsl, tables = AGECAT * ARM,
options = v(chisq, notable)) -> ageg_chisq
put("Combine chisq statistics")
datastep(ageg_chisq,
format = fc,
keep = c("PVALUE"),
{
PVALUE = fapply2(CHISQ, CHISQ.P)
}) -> ageg_chisq_comb
put("Append chisq")
datastep(ageg_cnts, merge = ageg_chisq_comb,
{}) -> ageg_block
put("Combine blocks into final data frame")
datastep(age_block,
set = list(ageg_block, sex_block, race_block),
{}) -> final
# Report ------------------------------------------------------------------
sep("Create and print report")
var_fmt <- c("AGE" = "Age", "AGECAT" = "Age Group", "SEX" = "Sex", "RACE" = "Race")
plbl <- "Tests of Association{supsc('1')}\n Value (P-Value)"
# Create Table
tbl <- create_table(final, first_row_blank = TRUE) |>
column_defaults(from = `ARM A`, to = `ARM D`, align = "center", width = 1.1) |>
stub(vars = c("VAR", "LABEL"), "Variable", width = 2.5) |>
define(VAR, blank_after = TRUE, dedupe = TRUE, label = "Variable",
format = var_fmt,label_row = TRUE) |>
define(LABEL, indent = .25, label = "Demographic Category") |>
define(`ARM A`, label = "Placebo", n = arm_pop["ARM A"]) |>
define(`ARM B`, label = "Drug 50mg", n = arm_pop["ARM B"]) |>
define(`ARM C`, label = "Drug 100mg", n = arm_pop["ARM C"]) |>
define(`ARM D`, label = "Competitor", n = arm_pop["ARM D"]) |>
define(PVALUE, label = plbl, width = 2, dedupe = TRUE, align = "center") |>
titles("Table 1.0", "Analysis of Demographic Characteristics",
"Safety Population", bold = TRUE) |>
footnotes("Program: DM_Table.R",
"NOTE: Denominator based on number of non-missing responses.",
"{supsc('1')}Pearson's Chi-Square tests will be used for "
%p% "Categorical variables and ANOVA tests for continuous variables.")
rpt <- create_report(file.path(tmp, "ProcsDemoDM.rtf"),
output_type = "RTF",
font = "Times") |>
page_header("Sponsor: Company", "Study: ABC") |>
set_margins(top = 1, bottom = 1) |>
add_content(tbl) |>
page_footer("Date Produced: {Sys.Date()}", right = "Page [pg] of [tpg]")
put("Write out the report")
res <- write_report(rpt)
# Clean Up ----------------------------------------------------------------
sep("Clean Up")
put("Close log")
log_close()
# Uncomment to view report
# file.show(res$modified_path)
# Uncomment to view log
# file.show(lf)
And here is the log:
=========================================================================
Log Path: C:/Users/dbosa/AppData/Local/Temp/RtmpKQddL7/log/example1.log
Program Path: C:/Projects/Archytas/Demo/example1.R
Working Directory: C:/Projects/Archytas/Demo
User Name: dbosa
R Version: 4.2.1 (2022-06-23 ucrt)
Machine: SOCRATES x86-64
Operating System: Windows 10 x64 build 19044
Base Packages: stats graphics grDevices utils datasets methods base Other
Packages: tidylog_1.0.2 procs_0.0.9007 reporter_1.3.7 libr_1.2.6 fmtr_1.5.9
logr_1.3.3 common_1.0.5 sassy_1.0.8
Log Start Time: 2022-10-15 20:01:02
=========================================================================
=========================================================================
Prepare formats
=========================================================================
Age categories
# A user-defined format: 5 conditions
Name Type Expression Label Order
1 obj U x >= 18 & x <= 29 18 to 29 NA
2 obj U x >= 30 & x <= 39 30 to 39 NA
3 obj U x >= 40 & x <= 49 40 to 49 NA
4 obj U x >= 50 >= 50 NA
5 obj U TRUE Out of range NA
Sex decodes
# A user-defined format: 4 conditions
Name Type Expression Label Order
1 obj U is.na(x) Missing NA
2 obj U x == "M" Male NA
3 obj U x == "F" Female NA
4 obj U TRUE Other NA
Race decodes
# A user-defined format: 4 conditions
Name Type Expression Label Order
1 obj U is.na(x) Missing NA
2 obj U x == "WHITE" White NA
3 obj U x == "BLACK" Black or African American NA
4 obj U TRUE Other NA
Compile format catalog
# A format catalog: 15 formats
- $MEAN: type S, "%.1f"
- $STD: type S, "(%.2f)"
- $Q1: type S, "%.1f"
- $Q3: type S, "%.1f"
- $MIN: type S, "%d"
- $MAX: type S, "%d"
- $CNT: type S, "%2d"
- $PCT: type S, "(%5.1f%%)"
- $AGECAT: type U, 5 conditions
- $SEX: type U, 4 conditions
- $RACE: type U, 4 conditions
- $AOV.F: type S, "%5.3f"
- $AOV.P: type S, "(%5.3f)"
- $CHISQ: type S, "%5.3f"
- $CHISQ.P: type S, "(%5.3f)"
=========================================================================
Prepare Data
=========================================================================
Create sample ADSL data.
Categorize AGE
Log starting dataset
SUBJID ARM SEX RACE AGE AGECAT
1 1 ARM A F WHITE 19 18 to 29
2 2 ARM B F WHITE 21 18 to 29
3 3 ARM C F WHITE 23 18 to 29
4 4 ARM D F BLACK 28 18 to 29
5 5 ARM A M WHITE 37 30 to 39
6 6 ARM B M WHITE 34 30 to 39
7 7 ARM C M WHITE 36 30 to 39
8 8 ARM D M WHITE 30 30 to 39
9 9 ARM A F WHITE 39 30 to 39
10 10 ARM B F WHITE 31 30 to 39
11 11 ARM C F BLACK 33 30 to 39
12 12 ARM D F WHITE 38 30 to 39
13 13 ARM A M BLACK 37 30 to 39
14 14 ARM B M WHITE 34 30 to 39
15 15 ARM C M WHITE 36 30 to 39
16 16 ARM A M WHITE 40 40 to 49
Get ARM population counts
proc_freq: input data set 16 rows and 6 columns
tables: ARM
view: TRUE
output: 1 datasets
VAR STAT ARM A ARM B ARM C ARM D
1 ARM CNT 5 4 4 3
=========================================================================
Create summary statistics for age
=========================================================================
Call means procedure to get summary statistics for age
proc_means: input data set 16 rows and 6 columns
by: ARM
var: AGE
stats: n mean std median q1 q3 min max
view: TRUE
output: 1 datasets
BY VAR N MEAN STD MEDIAN Q1 Q3 MIN MAX
1 ARM A AGE 5 34.4 8.706320 37.0 37 39 19 40
2 ARM B AGE 4 30.0 6.164414 32.5 26 34 21 34
3 ARM C AGE 4 32.0 6.164414 34.5 28 36 23 36
4 ARM D AGE 3 32.0 5.291503 30.0 28 38 28 38
Combine stats
datastep: columns decreased from 10 to 7
BY VAR N Mean (SD) Median Q1 - Q3 Min - Max
1 ARM A AGE 5 34.4 (8.71) 37.0 37.0 - 39.0 19 - 40
2 ARM B AGE 4 30.0 (6.16) 32.5 26.0 - 34.0 21 - 34
3 ARM C AGE 4 32.0 (6.16) 34.5 28.0 - 36.0 23 - 36
4 ARM D AGE 3 32.0 (5.29) 30.0 28.0 - 38.0 28 - 38
Transpose ARMs into columns
proc_transpose: input data set 4 rows and 7 columns
var: BY VAR N Mean (SD) Median Q1 - Q3 Min - Max
id: BY
copy: VAR
name: LABEL
output dataset 5 rows and 6 columns
VAR LABEL ARM A ARM B ARM C ARM D
1 AGE N 5 4 4 3
2 AGE Mean (SD) 34.4 (8.71) 30.0 (6.16) 32.0 (6.16) 32.0 (5.29)
3 AGE Median 37.0 32.5 34.5 30.0
4 AGE Q1 - Q3 37.0 - 39.0 26.0 - 34.0 28.0 - 36.0 28.0 - 38.0
5 AGE Min - Max 19 - 40 21 - 34 23 - 36 28 - 38
Calculate aov
Get aov into proper data frame
AOV.F AOV.P
ARM 0.2983651 0.8259486
Combine aov statistics
datastep: columns decreased from 2 to 1
PVALUE
1 0.298 (0.826)
Append aov
datastep: columns increased from 6 to 7
VAR LABEL ARM A ARM B ARM C ARM D PVALUE
1 AGE N 5 4 4 3 0.298 (0.826)
2 AGE Mean (SD) 34.4 (8.71) 30.0 (6.16) 32.0 (6.16) 32.0 (5.29) <NA>
3 AGE Median 37.0 32.5 34.5 30.0 <NA>
4 AGE Q1 - Q3 37.0 - 39.0 26.0 - 34.0 28.0 - 36.0 28.0 - 38.0 <NA>
5 AGE Min - Max 19 - 40 21 - 34 23 - 36 28 - 38 <NA>
=========================================================================
Create frequency counts for SEX
=========================================================================
Get sex frequency counts
proc_freq: input data set 16 rows and 6 columns
tables: SEX
by: ARM
view: TRUE
output: 1 datasets
BY VAR CAT CNT PCT
1 ARM A SEX F 2 40.00000
2 ARM A SEX M 3 60.00000
3 ARM B SEX F 2 50.00000
4 ARM B SEX M 2 50.00000
5 ARM C SEX F 2 50.00000
6 ARM C SEX M 2 50.00000
7 ARM D SEX F 2 66.66667
8 ARM D SEX M 1 33.33333
Combine counts and percents.
datastep: columns decreased from 5 to 4
BY VAR LABEL CNTPCT
1 ARM A SEX F 2 ( 40.0%)
2 ARM A SEX M 3 ( 60.0%)
3 ARM B SEX F 2 ( 50.0%)
4 ARM B SEX M 2 ( 50.0%)
5 ARM C SEX F 2 ( 50.0%)
6 ARM C SEX M 2 ( 50.0%)
7 ARM D SEX F 2 ( 66.7%)
8 ARM D SEX M 1 ( 33.3%)
Transpose ARMs into columns
proc_transpose: input data set 8 rows and 4 columns
by: LABEL
var: CNTPCT
id: BY
copy: VAR
name: NAME
output dataset 2 rows and 7 columns
VAR LABEL NAME ARM A ARM B ARM C ARM D
1 SEX F CNTPCT 2 ( 40.0%) 2 ( 50.0%) 2 ( 50.0%) 2 ( 66.7%)
2 SEX M CNTPCT 3 ( 60.0%) 2 ( 50.0%) 2 ( 50.0%) 1 ( 33.3%)
Clean up
datastep: columns decreased from 7 to 6
VAR LABEL ARM A ARM B ARM C ARM D
1 SEX Female 2 ( 40.0%) 2 ( 50.0%) 2 ( 50.0%) 2 ( 66.7%)
2 SEX Male 3 ( 60.0%) 2 ( 50.0%) 2 ( 50.0%) 1 ( 33.3%)
Sort by label
proc_sort: input data set 2 rows and 6 columns
by: LABEL
keep: VAR LABEL ARM A ARM B ARM C ARM D
order: a
nodupkey: FALSE
output data set 2 rows and 6 columns
VAR LABEL ARM A ARM B ARM C ARM D
2 SEX Male 3 ( 60.0%) 2 ( 50.0%) 2 ( 50.0%) 1 ( 33.3%)
1 SEX Female 2 ( 40.0%) 2 ( 50.0%) 2 ( 50.0%) 2 ( 66.7%)
Get sex chisq
proc_freq: input data set 16 rows and 6 columns
tables: SEX * ARM
view: TRUE
output: 1 datasets
CHISQ CHISQ.DF CHISQ.P
1 0.5333333 3 0.9115095
Combine chisq statistics
datastep: columns decreased from 3 to 1
PVALUE
1 0.533 (0.912)
Append chisq
datastep: columns increased from 6 to 7
VAR LABEL ARM A ARM B ARM C ARM D PVALUE
1 SEX Male 3 ( 60.0%) 2 ( 50.0%) 2 ( 50.0%) 1 ( 33.3%) 0.533 (0.912)
2 SEX Female 2 ( 40.0%) 2 ( 50.0%) 2 ( 50.0%) 2 ( 66.7%) <NA>
=========================================================================
Create frequency counts for RACE
=========================================================================
Get race frequency counts
proc_freq: input data set 16 rows and 6 columns
tables: RACE
by: ARM
view: TRUE
output: 1 datasets
BY VAR CAT CNT PCT
1 ARM A RACE BLACK 1 20.00000
2 ARM A RACE WHITE 4 80.00000
3 ARM B RACE BLACK 0 0.00000
4 ARM B RACE WHITE 4 100.00000
5 ARM C RACE BLACK 1 25.00000
6 ARM C RACE WHITE 3 75.00000
7 ARM D RACE BLACK 1 33.33333
8 ARM D RACE WHITE 2 66.66667
Combine counts and percents.
datastep: columns decreased from 5 to 4
BY VAR LABEL CNTPCT
1 ARM A RACE BLACK 1 ( 20.0%)
2 ARM A RACE WHITE 4 ( 80.0%)
3 ARM B RACE BLACK 0 ( 0.0%)
4 ARM B RACE WHITE 4 (100.0%)
5 ARM C RACE BLACK 1 ( 25.0%)
6 ARM C RACE WHITE 3 ( 75.0%)
7 ARM D RACE BLACK 1 ( 33.3%)
8 ARM D RACE WHITE 2 ( 66.7%)
Transpose ARMs into columns
proc_transpose: input data set 8 rows and 4 columns
by: LABEL
var: CNTPCT
id: BY
copy: VAR
name: NAME
output dataset 2 rows and 7 columns
VAR LABEL NAME ARM A ARM B ARM C ARM D
1 RACE BLACK CNTPCT 1 ( 20.0%) 0 ( 0.0%) 1 ( 25.0%) 1 ( 33.3%)
2 RACE WHITE CNTPCT 4 ( 80.0%) 4 (100.0%) 3 ( 75.0%) 2 ( 66.7%)
Clean up
datastep: columns decreased from 7 to 6
VAR LABEL ARM A ARM B ARM C ARM D
1 RACE Black or African American 1 ( 20.0%) 0 ( 0.0%) 1 ( 25.0%) 1 ( 33.3%)
2 RACE White 4 ( 80.0%) 4 (100.0%) 3 ( 75.0%) 2 ( 66.7%)
Sort by label
proc_sort: input data set 2 rows and 6 columns
by: LABEL
keep: VAR LABEL ARM A ARM B ARM C ARM D
order: a
nodupkey: FALSE
output data set 2 rows and 6 columns
VAR LABEL ARM A ARM B ARM C ARM D
2 RACE White 4 ( 80.0%) 4 (100.0%) 3 ( 75.0%) 2 ( 66.7%)
1 RACE Black or African American 1 ( 20.0%) 0 ( 0.0%) 1 ( 25.0%) 1 ( 33.3%)
Get race chisq
proc_freq: input data set 16 rows and 6 columns
tables: RACE * ARM
view: TRUE
output: 1 datasets
CHISQ CHISQ.DF CHISQ.P
1 1.449573 3 0.6939569
Combine chisq statistics
datastep: columns decreased from 3 to 1
PVALUE
1 1.450 (0.694)
Append chisq
datastep: columns increased from 6 to 7
VAR LABEL ARM A ARM B ARM C ARM D
1 RACE White 4 ( 80.0%) 4 (100.0%) 3 ( 75.0%) 2 ( 66.7%)
2 RACE Black or African American 1 ( 20.0%) 0 ( 0.0%) 1 ( 25.0%) 1 ( 33.3%)
PVALUE
1 1.450 (0.694)
2 <NA>
=========================================================================
Create frequency counts for Age Group
=========================================================================
Get age group frequency counts
proc_freq: input data set 16 rows and 6 columns
tables: AGECAT
by: ARM
view: TRUE
output: 1 datasets
BY VAR CAT CNT PCT
1 ARM A AGECAT 18 to 29 1 20.00000
2 ARM A AGECAT 30 to 39 3 60.00000
3 ARM A AGECAT 40 to 49 1 20.00000
4 ARM B AGECAT 18 to 29 1 25.00000
5 ARM B AGECAT 30 to 39 3 75.00000
6 ARM B AGECAT 40 to 49 0 0.00000
7 ARM C AGECAT 18 to 29 1 25.00000
8 ARM C AGECAT 30 to 39 3 75.00000
9 ARM C AGECAT 40 to 49 0 0.00000
10 ARM D AGECAT 18 to 29 1 33.33333
11 ARM D AGECAT 30 to 39 2 66.66667
12 ARM D AGECAT 40 to 49 0 0.00000
Combine counts and percents and assign age group factor for sorting
datastep: columns decreased from 5 to 4
VAR LABEL BY CNTPCT
1 AGECAT 18 to 29 ARM A 1 ( 20.0%)
2 AGECAT 30 to 39 ARM A 3 ( 60.0%)
3 AGECAT 40 to 49 ARM A 1 ( 20.0%)
4 AGECAT 18 to 29 ARM B 1 ( 25.0%)
5 AGECAT 30 to 39 ARM B 3 ( 75.0%)
6 AGECAT 40 to 49 ARM B 0 ( 0.0%)
7 AGECAT 18 to 29 ARM C 1 ( 25.0%)
8 AGECAT 30 to 39 ARM C 3 ( 75.0%)
9 AGECAT 40 to 49 ARM C 0 ( 0.0%)
10 AGECAT 18 to 29 ARM D 1 ( 33.3%)
11 AGECAT 30 to 39 ARM D 2 ( 66.7%)
12 AGECAT 40 to 49 ARM D 0 ( 0.0%)
Sort by age group factor
proc_sort: input data set 12 rows and 4 columns
by: BY LABEL
keep: VAR LABEL BY CNTPCT
order: a a
nodupkey: FALSE
output data set 12 rows and 4 columns
VAR LABEL BY CNTPCT
1 AGECAT 18 to 29 ARM A 1 ( 20.0%)
2 AGECAT 30 to 39 ARM A 3 ( 60.0%)
3 AGECAT 40 to 49 ARM A 1 ( 20.0%)
4 AGECAT 18 to 29 ARM B 1 ( 25.0%)
5 AGECAT 30 to 39 ARM B 3 ( 75.0%)
6 AGECAT 40 to 49 ARM B 0 ( 0.0%)
7 AGECAT 18 to 29 ARM C 1 ( 25.0%)
8 AGECAT 30 to 39 ARM C 3 ( 75.0%)
9 AGECAT 40 to 49 ARM C 0 ( 0.0%)
10 AGECAT 18 to 29 ARM D 1 ( 33.3%)
11 AGECAT 30 to 39 ARM D 2 ( 66.7%)
12 AGECAT 40 to 49 ARM D 0 ( 0.0%)
Tranpose age group block
proc_transpose: input data set 12 rows and 4 columns
by: LABEL
var: CNTPCT
id: BY
copy: VAR
name: NAME
output dataset 3 rows and 7 columns
VAR LABEL NAME ARM A ARM B ARM C ARM D
1 AGECAT 18 to 29 CNTPCT 1 ( 20.0%) 1 ( 25.0%) 1 ( 25.0%) 1 ( 33.3%)
2 AGECAT 30 to 39 CNTPCT 3 ( 60.0%) 3 ( 75.0%) 3 ( 75.0%) 2 ( 66.7%)
3 AGECAT 40 to 49 CNTPCT 1 ( 20.0%) 0 ( 0.0%) 0 ( 0.0%) 0 ( 0.0%)
Some clean up
datastep: columns decreased from 7 to 6
VAR LABEL ARM A ARM B ARM C ARM D
1 AGECAT 18 to 29 1 ( 20.0%) 1 ( 25.0%) 1 ( 25.0%) 1 ( 33.3%)
2 AGECAT 30 to 39 3 ( 60.0%) 3 ( 75.0%) 3 ( 75.0%) 2 ( 66.7%)
3 AGECAT 40 to 49 1 ( 20.0%) 0 ( 0.0%) 0 ( 0.0%) 0 ( 0.0%)
Get ageg chisq
proc_freq: input data set 16 rows and 6 columns
tables: AGECAT * ARM
view: TRUE
output: 1 datasets
CHISQ CHISQ.DF CHISQ.P
1 2.436364 6 0.8755205
Combine chisq statistics
datastep: columns decreased from 3 to 1
PVALUE
1 2.436 (0.876)
Append chisq
datastep: columns increased from 6 to 7
VAR LABEL ARM A ARM B ARM C ARM D PVALUE
1 AGECAT 18 to 29 1 ( 20.0%) 1 ( 25.0%) 1 ( 25.0%) 1 ( 33.3%) 2.436 (0.876)
2 AGECAT 30 to 39 3 ( 60.0%) 3 ( 75.0%) 3 ( 75.0%) 2 ( 66.7%) <NA>
3 AGECAT 40 to 49 1 ( 20.0%) 0 ( 0.0%) 0 ( 0.0%) 0 ( 0.0%) <NA>
Combine blocks into final data frame
datastep: columns started with 7 and ended with 7
VAR LABEL ARM A ARM B ARM C ARM D
1 AGE N 5 4 4 3
2 AGE Mean (SD) 34.4 (8.71) 30.0 (6.16) 32.0 (6.16) 32.0 (5.29)
3 AGE Median 37.0 32.5 34.5 30.0
4 AGE Q1 - Q3 37.0 - 39.0 26.0 - 34.0 28.0 - 36.0 28.0 - 38.0
5 AGE Min - Max 19 - 40 21 - 34 23 - 36 28 - 38
6 AGECAT 18 to 29 1 ( 20.0%) 1 ( 25.0%) 1 ( 25.0%) 1 ( 33.3%)
7 AGECAT 30 to 39 3 ( 60.0%) 3 ( 75.0%) 3 ( 75.0%) 2 ( 66.7%)
8 AGECAT 40 to 49 1 ( 20.0%) 0 ( 0.0%) 0 ( 0.0%) 0 ( 0.0%)
9 SEX Male 3 ( 60.0%) 2 ( 50.0%) 2 ( 50.0%) 1 ( 33.3%)
10 SEX Female 2 ( 40.0%) 2 ( 50.0%) 2 ( 50.0%) 2 ( 66.7%)
11 RACE White 4 ( 80.0%) 4 (100.0%) 3 ( 75.0%) 2 ( 66.7%)
12 RACE Black or African American 1 ( 20.0%) 0 ( 0.0%) 1 ( 25.0%) 1 ( 33.3%)
PVALUE
1 0.298 (0.826)
2 <NA>
3 <NA>
4 <NA>
5 <NA>
6 2.436 (0.876)
7 <NA>
8 <NA>
9 0.533 (0.912)
10 <NA>
11 1.450 (0.694)
12 <NA>
=========================================================================
Create and print report
=========================================================================
Write out the report
# A report specification: 1 pages
- file_path: 'C:\Users\dbosa\AppData\Local\Temp\RtmpKQddL7/ProcsDemoDM.rtf'
- output_type: RTF
- units: inches
- orientation: landscape
- margins: top 1 bottom 1 left 1 right 1
- line size/count: 9/36
- page_header: left=Sponsor: Company right=Study: ABC
- page_footer: left=Date Produced: 2022-10-15 center= right=Page [pg] of [tpg]
- content:
# A table specification:
- data: data.frame 'final' 12 rows 7 cols
- show_cols: all
- use_attributes: all
- title 1: 'Table 1.0'
- title 2: 'Analysis of Demographic Characteristics'
- title 3: 'Safety Population'
- footnote 1: 'Program: DM_Table.R'
- footnote 2: 'NOTE: Denominator based on number of non-missing responses.'
- footnote 3: '¹Pearson's Chi-Square tests will be used for Categorical variables and ANOVA tests for continuous variables.'
- stub: VAR LABEL 'Variable' width=2.5 align='left'
- define: VAR 'Variable' dedupe='TRUE'
- define: LABEL 'Demographic Category'
- define: ARM A 'Placebo'
- define: ARM B 'Drug 50mg'
- define: ARM C 'Drug 100mg'
- define: ARM D 'Competitor'
- define: PVALUE 'Tests of Association¹
Value (P-Value)' width=2 align='center' dedupe='TRUE'
=========================================================================
Clean Up
=========================================================================
Unload libname
lib_sync: synchronized data in library 'sdtm'
lib_unload: library 'sdtm' unloaded
Close log
=========================================================================
Log End Time: 2022-10-15 20:01:03
Log Elapsed Time: 0 00:00:00
=========================================================================