SAS (Base SAS)+
*==============================================================================;
* Cross-Tabulation: Two-Way Frequency Table
*==============================================================================;
*------------------------------------------------------------------------------;
* Step 1 - Create a small ADSL-like dataset
*------------------------------------------------------------------------------;
data adsl;
infile datalines dlm='|' dsd missover;
input USUBJID : $10. SEX : $1. TRT01P : $12. AGEGR1 : $10.;
datalines;
S-001|M|Placebo|<65
S-002|F|Drug A|<65
S-003|M|Drug B|>=65
S-004|F|Placebo|<65
S-005|M|Drug A|>=65
S-006|F|Drug B|<65
S-007|M|Placebo|>=65
S-008|F|Drug A|<65
S-009|M|Drug B|>=65
S-010|F|Placebo|<65
S-011|M|Drug A|>=65
S-012|F|Drug B|<65
;
run;
*------------------------------------------------------------------------------;
* Step 2 - Two-way frequency table (default format)
*------------------------------------------------------------------------------;
proc freq data=adsl;
tables SEX * TRT01P / nocum nopercent;
run;
*------------------------------------------------------------------------------;
* Step 3 - Cross-list format (one row per combination)
*------------------------------------------------------------------------------;
proc freq data=adsl;
tables SEX * TRT01P / crosslist nocum nopercent;
run;
*------------------------------------------------------------------------------;
* Step 4 - Save the cross-tabulation to a dataset
*------------------------------------------------------------------------------;
proc freq data=adsl noprint;
tables SEX * TRT01P / out=freq_sex_trt;
run;
proc print data=freq_sex_trt;
run;- We start by building a 12-row ADSL dataset with USUBJID, SEX, TRT01P and AGEGR1 so we have realistic clinical variable names.
- To produce a two-way frequency table, we write
TABLES SEX * TRT01PinsidePROC FREQ— the asterisk crosses the two variables. NOCUMsuppresses the cumulative frequency column, andNOPERCENTremoves the percentage column, giving us a clean count-only table.- The default output is a matrix with SEX on the rows and TRT01P across the columns — exactly the layout we see in clinical tables.
- Adding the
CROSSLISToption switches to a listing format with one row per SEX-TRT01P combination, which is easier to scan when there are many categories. - To save the counts for downstream processing, we add
OUT=freq_sex_trtandNOPRINT— the output dataset contains SEX, TRT01P, COUNT and PERCENT columns. - After running, we open freq_sex_trt and verify that the COUNT column sums to 12 — our original number of subjects.