NESUG 16 Pharmaceuticals “ACROSS” in PROC REPORT Cephalon Inc. West Chester, PA Jiang Jin INDEX1, INDEX2, and INDEX3 are used to adjust BODY, TERM, and TREAT in sequential order. There are not any patient in the BODY1, TERM1, and DOSE2 rows as well as some other categories. These cells are represented by " 0 " in the summary table. ABSTRACT The PROC REPORT has been known as one of the most powerful and user friendly procedures in clinical trial study summary table writing. According to the SAS user manual, columns covered by across variables contain only numeric variables. The preferable alternative of selecting ACROSS usage in the DEFINE statement in PROC REPORT has not been practiced by many SAS users. Min Fu introduced a new method to use ACROSS to cover character variables in "Using ACROSS Variable in PROC REPORT PROCEDURE" on NESUG'96 Proceedings. Following the suggestions as documented in Min Fu' coding examples, this paper provides the answer to many detailed problems in using ACROSS usage and makes it a practical approach in clinical summary tables writing. The author assumes all readers of this paper have prior experience using PROC REPORT. The common algorithm to create the shown summary table with the data set listed above is using PROC TRANSPOSE to generate a new data set (which splits VALUE into 4 treatment columns) and then performing PROC REPORT to produce the table. One issue related to the PROC TRANSPOSE for this case is: if a similar table with only one study dose(PLACEBO and DOSE1) is requested, the program has to be modified to specifically match the number of columns. This issue could cause extra coding work when a generic report macro is required. In the next section questions related to selecting ACROSS usage in the DEFINE statement in PROC REPORT and using the given data set in PROC REPORT directly are discussed. The coding procedure in the example could serve as a practical approach of generating clinical trial summary tables using ACROSS usage. INTRODUCTION A common layout of the clinical trial summary table is: USING ACROSS: As introduced in Min Fu's paper, the first step is adding a dummy variable dummy=1 in the given data set. Then submit the following program: ----------- TREATMENT GROUP-------BODY BBODY PREFERRED SYSTEM MSYSTEM TERM PLACEBO DOSE1 DOSE2 TOTAL ( N=88 ) ( N=87 ) ( N=68 ) ( N=263 ) ------------------------------------------------------------------------------------------------------------TOTAL T TOTAL BODY1 B BODY1 TOTAL BODY2 20 ( 22.7% ) 18 ( 20.7% ) 12 ( 17.7% ) 8 ( 9.1% ) 8 ( 9.2 % ) 6 ( 8.8% ) TERM1 5 ( 5.7% ) 6 ( 6.9% ) 0 . 11 ( 4.2% ) TERM2 6 ( 6.8% ) 0 . 4 ( 5.9% ) 10 ( 3.8% ) TERM3 3 ( 3.4% ) 2 ( 2.3% ) 2 ( 2.9% ) 7 ( 2.7% ) B BODY2 TOTAL 8 ( 9.1% ) TERM1 0 TERM2 TERM3 . 8 ( 9.2 % ) 6 ( 8.8% ) proc report data=sample2 nowd headline headskip spacing=4 split="\"; col body term treat, (value) dummy; define body / group order=data "BODY \ SYSTEM" width=8 left; define term / group order=data "PREFERRED \ TERM" width=14 left; define treat / across order=data "-TREATMENT GROUP- \ " ; define value / " " width=14; define dummy / noprint; break after body / skip; run; 50 ( 20.0% ) 22 ( 8.4% ) 22 ( 8.4% ) 6 ( 6.9% ) 5 ( 7.4% ) 11 ( 4.2% ) 6 ( 6.8% ) 0 . 4 ( 5.9% ) 10 ( 3.8% ) 3 ( 3.4% ) 2 ( 2.3% ) 2 ( 2.9% ) 7 ( 2.7% ) The table is created as: ………………………………………………………. ------------------- TREATMENT GROUP-----------------BODY BBODY PREFERRED SYSTEM S SYSTEM TERM The structure of a data set(SAMPLE2) used to produce this summary would be: BODY INDEX2 TERM INDEX3 TREAT VALUE -------------------------------------------------------------------------------------TOTAL 1 1 PLACEBO 20 ( 22.7% ) TOTAL 1 2 DOSE1 18 ( 20.7% ) TOTAL 1 3 DOSE2 12 ( 17.7% ) TOTAL 1 4 TOTAL 50 ( 20.0% ) BODY1 2 TOTAL 1 PLACEBO 8 ( 9.1% ) BODY1 2 TOTAL 2 DOSE1 8 ( 9.2 % ) BODY1 2 TOTAL 3 DOSE2 6 ( 8.8% ) BODY1 2 TOTAL 4 TOTAL 22 ( 8.4% ) BODY1 3 TERM1 1 PLACEBO 5 ( 5.7% ) BODY1 3 TERM1 2 DOSE1 6 ( 6.9% ) BODY1 3 TERM1 4 TOTAL 11 ( 4.2% ) BODY1 3 TERM2 1 PLACEBO 6 ( 6.8% ) BODY1 3 TERM2 3 DOSE2 4 ( 5.9% ) BODY1 3 TERM2 4 TOTAL 10 ( 3.8% ) ...... PLACEBO DOSE1 DOSE2 TOTAL --------------------------------------------------------------------------------------------------------------TOTAL T TOTAL BODY1 B BODY1 TOTAL TERM1 TERM2 6 ( 6.8% ) TERM3 3 ( 3.4% ) B BODY2 TOTAL 8 ( 9.1% ) BODY2 20 ( 22.7% ) 18 ( 20.7% ) 12 ( 17.7% ) 8 ( 9.1% ) 8 ( 9.2 % ) 6 ( 8.8% ) 5 ( 5.7% ) 6 ( 6.9% ) TERM1 2 ( 2.3% ) 8 ( 9.2 % ) 6 ( 6.9% ) TERM2 6 ( 6.8% ) TERM3 3 ( 3.4% ) 2 ( 2.3% ) …………………………………… 50 ( 20.0% ) 22 ( 8.4% ) 11 ( 4.2% ) 4 ( 5.9% ) 10 ( 3.8% ) 2 ( 2.9% ) 7 ( 2.7% ) 6 ( 8.8% ) 22 ( 8.4% ) 5 ( 7.4% ) 11 ( 4.2% ) 4 ( 5.9% ) 10 ( 3.8% ) 2 ( 2.9% ) 7 ( 2.7% ) NESUG 16 Pharmaceuticals Compared with the required table in the introduction section, three problems need to be solved. #1. header "---TREATMENT GROUP -----" should only cover PLACE, DOSE1, and DOSE2 columns but not TOTAL column. #2. numbers of patient (N= ) in each group are missing. #3. "0 " is required to fill null cells in the table. -----TREATMENT GROUP-----BODY PPPREFERRED SYSTEM PLACEBO DOSE1 DOSE2 TOTAL ( N= 88 ) ( N=87 ) ( N=68 ) ( N=263 ) M TERM ------------------------------------------------------------------------------------------- ANSWER TO PROBLEM #1. To shift "TREATMENT GROUP" in order not to cover TOTAL column, perform data _null_; call symput("header", "--TREATMENT GROUP-10)); run; " || repeat(byte(9), Format $trt is used to add number of patients in each treatment group and the total group in the header. Note: byte(9) is for PC SAS, byte(160) is for SAS on UNIX or other large system. ANSWER TO PROBLEM #3. proc report data=sample2 nowd headline headskip spacing=4 split="\"; col body term treat, (value) dummy; define body / group order=data "BODY \ SYSTEM" width=8 left; define term / group order=data "PREFERRED \ TERM" width=14 left; define treat / across order=data "&header \ " ; define value / " " width=14; define dummy / noprint; break after body / skip; run; proc format; value $value ""=" 0 " ; run; proc report data=sample2 nowd headline headskip spacing=4 split="\"; col body term treat, (value) dummy; define body / group order=data "BODY \ SYSTEM" width=8 left; define term / group order=data "PREFERRED \ TERM" width=14 left; define treat / across order=data "&header \ " format=$trt.; define value / " " format=$value. width=14; define dummy / noprint; break after body / skip; run; table with header shifted to the left can be produced. -----TREATMENT GROUP----BODY P PREFERRED PLACEBO DOSE1 DOSE2 TOTAL SYSTEM TE TERM --------------------------------------------------------------------------- Format $value is added to change null cell in the table to " 0 ". CONCLUSION: &header is used to shift the TREATMENT GROUP header to not cover TOTAL column. The technique of using ACROSS usage in the DEFINE statement in PROC REPORT is presented in this paper. Also, the methods of shifting header, adding number of patients under each treatment column, and changing null cells to " 0 " are introduced by coding example. Practicing the algorithm introduced by this paper could save SAS users' coding time and avoid potential mistakes caused by PROC TRANSPOSE. ANSWER TO PROBLEM #2. To add number of patients (N) under each treatment and total column, the following block of code can be added to generate format $trt. proc sql; create table fmts as select '$trt' as fmtname , treat as start , trim(treat) || '\(N=' || put(count(distinct patno),3.) || ')' as label length=20 from sample1 group by index3, treat; proc format cntlin=sfmt; quit; Note: SAMPLE1 is the original data set used to generate SAMPLE2. With macro variable &header and format $trt, REFERENCES SAS Institute, Inc., SAS Technical Report P-222, Changes and Enhancements to Base SAS Software, Release 6.07, Cary, NC. SAS Guide to the SQL Procedure, Usage and Reference, Version 6, First Edition. SAS is a registered trademark or trademark of SAS Institute Inc. in the USA and other countries. â indicates USA registration. proc report data=sample2 nowd headline headskip spacing=4 split="\"; col body term treat, (value) dummy; define body / group order=data "BODY \ SYSTEM" width=8 left; define term / group order=data "PREFERRED \ TERM" width=14 left; define treat / across order=data "&header \ " format=$trt.; define value / " " width=14; define dummy / noprint; break after body / skip; run; ACKNOWLEDGMENTS I would like to thank Vincent Rabatin for his input and assistance. CONTACT INFORMATION Email: jjin@cephalon.com generates the table below with the following header. 2