Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
A SAS Macro to Present a Summary Table of the Number of Patients Having Experienced Adverse Events in a Clinical Trial Christoph Gerlinger* and Ursula Franke** * Laboratoires Fournier S.C.A. and biodat Gesellschaft für Biometrie und Statistik mbH ** Summary One of the major concerns when testing a new drug treatment are adverse events. An adverse event is defined as any medical event that is experienced by a patient in the course of a clinical trial and that compromises the patient's well-being. This definition includes diseases as well as accidents. For presentation and analyses, adverse events are coded using standardised terminology. These classifications have hierarchical levels of detail. For example, the COSTART code consists of "body systems" which are divided into "subcategories" which are themselves subdivided into "terms". A summary table of the number and percentage of events can be easily computed using PROC TABULATE. However, it is not possible to present in the same way the number of patients having experienced at least once an event which falls into a given category, since a patient may have several events of the same kind or several events which fall into the same category of a higher level. A SAS® macro is presented which calculates the number and percentage of patients falling into each body system, subcategory and term of the classification, as well as the number of events that occured. Introduction A clinical trial is a controlled scientific procedure to assess the efficacy and the safety of a drug treatment in humans. Groups of patients are treated in a standardised way in order to allow the comparison of different drug treatments. Usually a new or experimental drug is compared to a known reference drug or placebo. In the perspective of drug safety, a clinical trial design has to incorporate the evaluation of adverse events, so that the drug-related events (i.e. side effects) can be detected at an early stage of the development of a new drug. Any undesirable medical experience, whether or not related to the tested drug, is considered an adverse event. In order to compare the adverse events of different drug treatments, one wishes to present a summary table like Table 1 below, using in this example the COSTART 1 classifiaction of adverse events. This table is part of the report of the clinical trial. If the new drug is tested successfully, the study report is one of the documents sent to the health authorities in order to obtain the licence to sell the new drug. The Problem When analysing the adverse events which occurred during a clinical trial, one is interested not only in the number of a given event, such as headache, but also in the number and percent of patients who had headache(s). This number of patients experiencing headache at least once cannot be calculated using PROC TABULATE 2 since PROC TABULATE can only display the number of observations in a SAS dataset. Also, PROC TABULATE can only print all categories of a class variable, so that it would print the number of patients with headache, as well as the number of patients without headache next to it. However, in this context the number of patients without a given adverse event is of no interest to the reader. Table 1: Summary Table of Adverse Events COSTART Classification of Adverse Events Any Event BODY AS A WHOLE BODY AS A WHOLE (GENERAL) ALLERGIC REACTION FEVER FLU SYNDROME HEAD EDEMA FACE HEADACHE CARDIOVASCULAR SYSTEM CARDIAC DISORDERS ANGINA PECTORIS Drug A (n=13) Drug B (n=12) Number Numbe Numbe Number of r of % of r of of % of Events Patients Patients Events Patients Patients 36 21 12 6 3 3 9 6 3 15 9 3 10 7 5 4 2 2 5 4 2 6 5 2 76.92 53.85 38.46 30.77 15.38 15.38 38.46 30.77 15.38 46.15 38.46 15.38 20 11 8 3 2 3 3 3 . 9 5 1 5 4 3 2 1 2 2 2 . 3 2 1 41.67 33.33 25.00 16.67 8.33 16.67 16.67 16.67 . 25.00 16.67 8.33 BRADYCARDIA VASCULAR DISORDERS MIGRAINE VASCULITIS 6 6 3 3 4 3 2 2 30.77 23.08 15.38 15.38 4 4 2 2 2 1 1 1 16.67 8.33 8.33 8.33 Another problem lies in the computation of totals and subtotals. SAS PROC TABULATE can print totals and subtotals of a table row or column. This is sufficient to display totals and subtotals of the number of adverse events which occurred. However, a given patient can have several different adverse events and should nevertheless be counted only once for the total number of patients who have experienced any adverse event. For example, a patient having both fever and flu would be counted only once for the body system "BODY AS A WHOLE". Furthermore, we need to insert the subtotals into the table and to indent them properly. The Solution A SAS macro 3 has been developed in order to produce a summary table like Table 1 of the number of events and the number and the percentage of patients who have experienced adverse events with different treatment regimens. The macro creates a special SAS dataset with the table entries which is then formatted and printed using PROC TABULATE. The SAS macro requires two input SAS datasets. The first is a dataset containing one observation per patient which allows the calculation of the total number of patients per group. It contains at least a variable which identifies the patient (typically the patient number) and a variable which indicates the patient's treatment ("Drug A" or "Drug B" in our example). The second input dataset contains one observation per adverse event that occurred. There are several observations for a given patient if this patient had several adverse events or no observation if the patient had no adverse event at all during the clinical trial. If a patient had the same event at several occasions, the dataset contains one observation per occurrence of the adverse event. The table can be custom formatted since the formats of the different table columns as well as the row title space 4 can be passed to the macro as macro parameters. The macro allows the presention of only a subset of the adverse events, such as all events related to the study drug or all serious adverse events. In addition, the selection of a patient subset, such as female patients, is possible. This is achieved by passing two "where clauses" as macro parameters. The first "where clause" is used to select events and is applied to the dataset containing the adverse events. The second "where clause" is used to select patients and is applied to both the events dataset and the dataset containing all patients. It should be noted that the variables used in the "where clause" for the events have to exist in the events dataset and the variables used for the patient selection have to exist in both datasets. The latter is necessary since if one wishes to present, for example, the adverse events of the male patients, the macro has to calculate not only the number of male patients but also the number of the events experienced by male patients. The insertion of the various subtotals is achieved by using a numeric code variable with a SAS format. In fact, a six digit number has been assigned to each COSTART term. The first two digits of the code present the body system and its first four digits present the group. To insert the totals we use the following seven digit code: for COSTART terms, the number 2 is used as seventh digit; for COSTART groups, the numbers 001 are used after the four digits representing the group; and for body systems, the numbers 00000 are used after the two digits representing the body system. This yields a global code in ascending numeric order which includes all subtotals. For the grand total of any adverse event, the code 0 is used. The indention of the different levels of the COSTART code in the tables above has been obtained using a simple trick. The SAS format contains a special character (@ in our example) as the first character of the label, as shown in the following excerpt of the format definition. proc format; value costart 1000000 = "BODY AS A WHOLE" 1000001 = "@ BODY AS A WHOLE (GENERAL)" 1000032 = "@ ALLERGIC REACTION"; run; Once PROC TABULATE has produced the table, the special character @ is replaced by a blank character using an editor. Description of the SAS Macro After assigning defaults values in case no values are given in the macro call for formatting and subgroup selection parameters, PROC SUMMARY2 is called to create a SAS dataset containing an observation with the number of patients per treatment group plus one observation for the total number of patients, regardless of treatment group. This dataset is used in two ways: First to create a control dataset for input into PROC FORMAT2 for the treatment groups which includes the number of patients who are present, such as "Drug A (n=13)". The second use is to create a weight variable defined as 100/(number of patients in treatment group) which gives the weight of one patient as percentage of the number of patients in the treatment group. This weight variable is later summed over all patients having experienced a given adverse event to yield the percentage of patients in the treatment group having had this adverse event at least once. Next, PROC SUMMARY is called to create a SAS dataset containing exactly one observation per patient and per COSTART term, group, or body system. In this dataset each patient occurs only once for any given adverse event, thus eliminating to count him twice in case of multiple events. The total number of events is still available in the variable _FREQ_ which is created by PROC SUMMARY. This output dataset is then merged with the dataset containing the patient weight variable and the SAS bit-testing feature 5 is used to retain the observations with the right crossing of the class variables of PROC SUMMARY. The resulting dataset is used as input to PROC TABULATE which prints the summary table in the form shown in Table 1. Finally PROC CATALOG2 and PROC DATASETS2 are used to delete all datasets and the format created during the macro execution in order to avoid their use afterwards by mistake. SAS Macro Source Code %macro _tabaes ( aesdat, aeswhere, patdat, patwhere, group, grpfmt, total, codpat, rts, nevtfmt, npatfmt, pctnfmt ); %* %* %* %* %* %* %* %* %* %* %* %* %* %* %* %* DESCRIPTION:; ============; ; PARAMETERS:; aesdat : dataset with coded adverse events (one line per event); contains variables costart = COSTART Term; cosgroup = COSTART Group; cosbody = COSTART Body System; as well as the &group and &codpat variables and all; variables used in the &aeswhere AND in the &patwhere clauses; aeswhere: subset where clause for events. DEFAULT is no clause; patdat : dataset with all patients (one line per patient); patwhere: subset where clause for patients, it is also applied to the events dataset. DEFAULT is no clause; group : name of treatment group variable; grpfmt : name of treatment group format; %* %* %* %* %* %* %* %* %* %* %* %* %* %* %* %* %* %* total : flag, triggers total column if set to Yes; codpat : name of patient identifier; rts : proc tabulate rts option. DEFAULT is 30; nevtfmt : numeric format for number of events column. DEFAULT is 8.0 ; npatfmt : numeric format for number of patients column. DEFAULT is 8.0 ; pctnfmt : numeric format for percent of patients column. DEFAULT is 8.2 ; ; PREREQUISITS; the format COSTART must be available; ; SIDEEFFECTS; ; the following local datasets are created: __pats __fmt __sumaes __table; they are deleted at the end of the macro execution; ; the following local formats are created: __aesgr $_aesgr; they are deleted at the end of the macro execution; ; %* definitions and defaults; %local __grpfmt; %if %if %if %if %if %if "&aeswhere" "&patwhere" "&rts." "&nevtfmt" "&npatfmt" "&pctnfmt" eq eq eq eq eq eq "" "" "" "" "" "" %then %then %then %then %then %then %let %let %let %let %let %let aeswhere=1; %* 1=true; patwhere=1; %* 1=true; rts=30; nevtfmt=8.0; %* default; npatfmt=8.0; %* default; pctnfmt=8.2; %* default; %* first step: get number of patients per group in dataset __pats; proc summary data=&patdat. missing; where &patwhere; class &group; format &group &grpfmt.. ; output out=__pats; run; %* second step: create control dataset __fmt for use with proc format to; %* define a format for the treatments including the number ; %* of patients per treatment group.; %* create dataset __pats with variable __weight to merge with; %* events dataset (below); %* the variable __weight is defined as 100/# of patients per; %* group, its sum yields the percentage of patients ; data __pats(keep=&group __weight ) __fmt (keep=start end label fmtname); set __pats; length label $40.; __weight = 100 / _freq_; %* check whether format is numeric or character; %if "%substr(&grpfmt,1,1)" ne "$" %then %do; retain fmtname '__AESGR'; %let __grpfmt = __AESGR; if &group ne . then label = put(&group,&grpfmt..)||" (n="||trim(left(_freq_))||")"; else label = "Total (n="||trim(left(_freq_))||")"; start = &group; end = &group; %end; %else %do; retain fmtname '$_AESGR'; %let __grpfmt = $_AESGR; length start $40. end $40.; if &group ne ' ' then label = trim(put(&group.,&grpfmt..))||" (n="||trim(left(_freq_))||")"; else label = "Total (n="||trim(left(_freq_))||")"; start = &group; end = &group; %end; run; %* create local format for treatment groups; proc format cntlin=__fmt; run; %* third step: count the number of patients having an event at least once; %* create dataset __sumaes. Its variable _freq_ give the number; %* of events for a given event and patient; proc summary data=&aesdat. missing; where &aeswhere and &patwhere; class &group &codpat costart cosgroup cosbody; format &group &grpfmt.. ; output out=__sumaes; run; proc sort data=__sumaes; by &group; run; %* fourth step: create final dataset __table used for proc tabulate; %* the variable __rowvar is created to insert the body systems; %* and costart groups into the costart terms; data __table; merge __sumaes __pats; by &group; select ; when ( _type_ eq '11100'B when ( _type_ eq '11010'B when ( _type_ eq '11001'B when ( _type_ eq '11000'B ) ) ) ) __rowvar=10*costart+2; __rowvar=1000*cosgroup+1; __rowvar=100000*cosbody+0; __rowvar=0; %* id total flag is set then keep sums over all groups; %if "%upcase(&total)" eq "YES" %then %do; when ( _type_ eq '01100'B ) __rowvar=10*costart+2; when ( _type_ eq '01010'B ) __rowvar=1000*cosgroup+1; when ( _type_ eq '01001'B ) __rowvar=100000*cosbody+0; when ( _type_ eq '01000'B ) __rowvar=0; %end; otherwise delete; end; format __rowvar costart.; run; %* fifth step: use proc tabulate to print table; proc tabulate missing format=8.0 data=__table; format &group &__grpfmt..; class __rowvar &group; var __weight _freq_; table __rowvar=' ', &group=' ' * ( _freq_=' ' * sum = 'Number of Events'*f=&nevtfmt. __weight=' ' * ( n = 'Number of Patients'*F=&npatfmt. sum = '% of Patients'*f=&pctnfmt. ) ) / rts=&rts. box = 'COSTART Classification of Adverse Events'; run; %* sixth step: delete datasets and format created during macro execution; proc catalog catalog=formats; %if "%substr(&grpfmt,1,1)" ne "$" %then %do; delete __AESGR /et=format; %end; %else %do; delete _AESGR /et=formatC; %end; run; proc datasets library=work nolist; delete __sumaes __pats __fmt __table; run; %mend _tabaes; Acknowledgement The authors gratefully acknowledge the medical assistance of Nadine IndriAnnesley of Laboratoires Fournier's Pharmacovigilance Department. Addresses of the authors: Christoph Gerlinger Laboratoires Fournier S.C.A. Biometrics Department 50, rue de Dijon F-21121 Daix France Ursula Franke biodat Gesellschaft für Biometrie und Statistik mbH Oranienstraße 25 D-10999 Berlin Germany Telephone: (+33) 80 44 75 72 Telefax: (+33) 80 44 75 69 Email: [email protected] Telephone: (+49) 30 / 614 80 71 Telefax: (+49) 30 / 614 80 77 Email: [email protected] References 1 U.S. Food and Drug Administration, 'COSTART' - Coding Symbols For Thesaurus of Adverse Reaction Terms, Fourth Edition, Rockville, MD: U.S. Food and Drug Administration, 1993. SAS Institute Inc., SAS® Procedures Guide, Version 6, Third Edition, Cary, NC: SAS Institute Inc., 1990. 2 3 SAS Institute Inc., SAS® Guide to Macro Processing, Version 6, Second Edition, Cary, NC: SAS Institute Inc., 1990. SAS Institute Inc., SAS® Guide to TABULATE Processing, Second Edition, Cary, NC: SAS Institute Inc., 1990. page 118. 4 SAS Institute Inc., SAS® Procedures Guide, Version 6, Third Edition, Cary, NC: SAS Institute Inc., 1990. page 381. 5 SAS is a registered trademark of SAS Institute Inc., Cary, NC.