/************************************************************************************ /* Program Name: Carolina Premenstrual Assessment Scoring System (C-PASS) * /* * /* Date Created: 12/1/2015 * /* * /* Macro Authors: Tory Eisenlohr-Moul, Ph.D. & Jacqueline Johnson, Dr.PH * /* * /* Purpose: To Diagnose DSM-5 Premenstrual Dysphoric Disorder from 2-4 months of * /* daily ratings using the Daily Record of Severity of Problems (DRSP; * /* Endicott et al., 2006) * /* * /* Website: www.toryeisenlohrmoul.com/cpass * /* * /* Inputs: Enter the following when calling the CPASS macro: * /* * /* - "data": the name of the SAS dataset containing daily ratings (see format * /* instructions below) * /* - "samplestat": 'on' (default)= print frequencies and histogram for diagnoses * /* in this dataset. 'off'= do not print sample-level frequences or histogram. * /* - "visualsublist": 'off' (default)= suppress graphs of daily ratings by cycle. * /* To print graphs of daily ratings and symptom-level diagnoses by cycle, * /* enter the subject numbers of women for whom you want to print graphs. * /* Separate subject numbers in the list with a comma (ex: visualsublist=2,4,9) * /* * /* Outputs: * /* * /* 1) Output Dataset - "cpassout," which includes diagnostic and dimensional * /* symptom variables for each woman: * /* - ncycles: Number of cycles (i.e., perimenstrual timeframes) for this woman * /* - dxcat: 0=No Diagnosis, 1=MRMD, 2=DSM-5 PMDD * /* - MRMD: 0=No Diagnosis, 1=MRMD or DSM-5 PMDD * /* - PMDD: 0=No Diagnosis or MRMD, 1=DSM-5 PMDD * /* - Avgdsm5crit: Woman's Average # of DSM-5 symptoms meeting criteria per cycle * /* - PMDDcycprop: Proportion of cycles meeting DSM-5 criteria * /* - MRMDcycprop: Proportion of cycles meeting MRMD criteria * /* - AvgPctEl1-24: Woman's Average % Premenstrual Elevation on DRSP1-DRSP24 * /* - AvgPostMax1-24: Woman's Average Postmenstrual Max on DRSP1-24 * /* - AvgPostMn1-24: Woman's Average Postmenstrual Mean on DRSP1-24 * /* - AvgPreMn1-24: Woman's Average Premenstrual Mean on DRSP1-24 * /* - AvgPreMax1-24: Woman's Average Premenstrual Max on DRSP1-24 * /* - AvgSevDays1-24: Woman's Average # Severe (>=4) Premenstrual Days on DRSP1-24 * /* * /* 2) Sample-Level Frequencies and Histogram - If you specify "on" in the "sample- * /* stats=" option, macro provides a frequency table and histogram representing * /* frequencies of MRMD and DSM-5 PMDD diagnosis in the dataset. * /* * /* 3) Diagnostic Information. Specifies number of cycles, Woman-Level Diagnoses * /* of MRMD and PMDD, and symptom-level diagnoses in each cycle. * /* * /* 4) Visual Output - If you supply a comma-delimited subject list in the * /* "visualsublist=" option, the macro will provide graphs of daily ratings * /* and symptom-level diagnoses by cycle for the subject numbers you specify. * /* * /* Instructions for Data Preparation and Macro Use: * /* * /* Before using the macro, please read the following paper: * /* * /* Eisenlohr-Moul et al., 2017. Toward the Reliable Diagnosis of DSM-5 * /* Premenstrual Dysphoric Disorder (PMDD): The Carolina Premenstrual Assessment * /* Scoring System (C-PASS). American Journal of Psychiatry. * /* * /* 1) Data must be in the following format: * /* * /* ROWS: * /* - one observation per day, and 14 observations per person per cycle * /* (i.e., 14 days of ratings, making up one perimenstrual frame: * /* days -7 to -1 for the premenstrual week, and days 4-10 in the * /* postmenstrual week; day -1=day prior to onset, day 1= menstrual onset) * /* * /* COLUMNS: * /* - "Subject" - Person-Level ID variable * /* - "Cycle" - Cycle-Level ID variable (1,2,3,4) * /* - "Phase" - Dichotomous variable for cycle phase * /* (0=PostMenstrual, 1=Premenstrual) * /* - "Day" - Day-level ID variable (Premenstrual: -7 to -1, * /* Postmenstrual: 4 to 10) * /* - "DRSP1...DRSP24" - daily rating value for each item (ranging from 1-6); * /* * /* 2) Missing items must be coded as . (not 999, -99, etc). Days should be coded * /* as missing if a woman reports a significant external stressor that is * /* not caused by her symptoms. 4 non-missing days per phase are * /* required for scoring. * /* * /* 3) Each woman must have between 2 and 4 cycles (2-4 sets of premenstrual and * /* postmenstrual phases, i.e., "perimenstrual frames") of data. * /* * /* 4) To call the cpass macro, input your dataset at the bottom of this document * /* using the "%cpass" macro statement. Specify the dataset, whether you want * /* sample-level information, and whether you want person-level visuals. * /* * /* 5) The CPASS macro can be used in conjunction with an %inc statement. * /* ------------------------------------------------------------------------------- */ %macro cpass (data=, samplestat=on, visualsublist=); * Calculate scale range for each person and cycle; * Results in _OUT3_ dataset; proc means data=&data nway noprint; class subject; var drsp1-drsp24; output out=_out1_(drop=_type_ _freq_) max=Max1-Max24; run; proc transpose data=_out1_ out=_out2_ prefix=Max; by subject; run; proc means data=_out2_ max nway noprint; class subject; var max1; output out=_OUT3_(drop=_type_ _freq_) max=WomanMax; run; * Compute mean of each symptom in each phase; * Compute max of each symptom in each phase; * Compute number non-missing of each symptom in each phase; proc means data=&data nway noprint; where phase=1; class subject cycle; var drsp1-drsp24; output out=_out4_(drop=_type_ _freq_) mean=PreMn1-PreMn24 n=PreN1-PreN24 max=PreMax1-PreMax24; run; proc means data=&data nway noprint; where phase=0; class subject cycle; var drsp1-drsp24; output out=_out5_(drop=_type_ _freq_) mean=PostMn1-PostMn24 n=PostN1-PostN24 max=PostMax1-PostMax24; run; * Compute number of days greater than 4; data _out6_; set &data(where=(phase=1)); array drsp{24}; array Ind{24}; do i=1 to 24; Ind[i]=(drsp[i]>=4); end; keep subject cycle ind1-ind24; run; proc means data=_out6_ nway noprint; class subject cycle; var ind1-ind24; output out=_out7_(drop=_type_ _freq_) sum=PreDays1-PreDays24; run; * Compute absolute difference between phases; * Compute percent difference between phases; * Compute whether meet criteria on each symptom; data _all1_; merge _out4_ _out5_ _out7_; by subject cycle; run; data _all1_; merge _all1_ _OUT3_; by subject; array PreMn{24}; array PostMn{24}; array PostMax{24}; array PreN{24}; array PostN{24}; array PctCh{24}; array PreDays{24}; do i=1 to 24; if PreN[i]>=4 and PostN[i]>=4 then PctCh[i]=((PreMn[i] - PostMn[i])/ (womanmax-1))*100; PctChInd=(PctCh[i]>=30); PostMaxInd=(PostMax[i]<=3); PreDaysInd=(PreDays[i]>=2); MetCrit=(sum(pctchind, postmaxind, predaysind)=3); Domain=1*(i=1) + 1*(i=2) + 1*(i=3) +2*(i=4) +3*(i=5) + 3*(i=6) +4*(i=7) + 4*(i=8) +5*(i=9) +6*(i=10) +7*(i=11) +8*(i=12) + 8*(i=13) +9*(i=14) + 9*(i=15) +10*(i=16) + 10*(i=17) +11*(i=18) + 11*(i=19) + 11*(i=21); if PctCh[i]=. then do; PctChInd=.; PostMaxInd=.; PreDaysInd=.; MetCrit=.; end; output; end; keep subject cycle MetCrit Domain I pctch1-pctch24 premn1-premn24 predays1-predays24 premax1-premax24 postmax1-postmax24 postmn1-postmn24; rename i=Symptom; run; * Compute whether meet criteria in each domain; * Compute number of domains on which meet criteria; * Compute whether meet MRMD and PMDD criteria for each cycle; proc means data=_all1_ nway noprint; where domain>0; class subject cycle domain; var metcrit; output out=_out8_(drop=_type_ _freq_) Max=DomainMetCrit; run; proc means data=_out8_ nway noprint; class subject cycle; var domainmetcrit; output out=_out9_(drop=_type_ _freq_) Sum=NumDomainMetCrit; run; proc means data=_out8_ (where=(domain<5)) nway noprint; class subject cycle; var domainmetcrit; output out=_out1_0(drop=_type_ _freq_) Sum=coremetcrit; run; proc means data=_all1_ nway noprint; var PctCh1-PctCh24; by subject; output out=avgcyc (drop=_type_ _freq_) mean=AvgPctEl1-AvgPctEl24; run; proc means data=_all1_ nway noprint; var PostMn1-PostMn24; by subject; output out=avgpost (drop=_type_ _freq_) mean=AvgPostmn1-AvgPostmn24; run; proc means data=_all1_ nway noprint; var Postmax1-Postmax24; by subject; output out=avgpostmax (drop=_type_ _freq_) mean=AvgPostmax1-AvgPostmax24; run; proc means data=_all1_ nway noprint; var Premn1-Premn24; by subject; output out=avgpre (drop=_type_ _freq_) mean=AvgPremn1-AvgPremn24; run; proc means data=_all1_ nway noprint; var Premax1-Premax24; by subject; output out=avgpremax (drop=_type_ _freq_) mean=AvgPremax1-AvgPremax24; run; proc means data=_all1_ nway noprint; var PreDays1-Predays24; by subject; output out=avgdays (drop=_type_ _freq_) mean=AvgPreDays1-AvgPreDays24; run; data _all2_; merge _out9_ _out1_0; by subject cycle; if coremetcrit=. or numdomainmetcrit=. then PMDDCycleMetCrit=.; else if (coremetcrit>=1) and (numdomainmetcrit>=5) then PMDDCycleMetCrit=1; else PMDDCycleMetCrit=0; if coremetcrit=. or numdomainmetcrit=. then MRMDCycleMetCrit=.; else if (coremetcrit>=1) then MRMDCycleMetCrit=1; else MRMDCycleMetCrit=0; run; * Compute whether meet MRMD and PMDD criteria for two or more cycles; * Compute number of cycles assessed; proc means data=_all2_ nway noprint; class subject; var pmddcyclemetcrit mrmdcyclemetcrit numdomainmetcrit; output out=_out1_1(drop=_type_ _freq_) mean=pmddcycprop mrmdcycprop avgdsm5crit sum=PMDDMonthsMetCrit MRMDMonthsMetCrit n=NCycles; run; data cpassout; merge _out1_1 avgcyc avgdays avgpre avgpremax avgpost avgpostmax; by subject; PMDD=(PMDDMonthsMetCrit>=2); MRMD=(MRMDMonthsMetCrit>=2); dxcat=.; if PMDD=1 then DXCAT=2; if MRMD=1 and PMDD=0 then DXCAT=1; if MRMD=0 and PMDD=0 then DXCAT=0; if ncycles<=1 then do; pmdd=.; mrmd=.; dxcat=.; end; keep subject womanID ncycles pmdd mrmd dxcat pmddcycprop mrmdcycprop avgdsm5crit AvgPctEl1-AvgPctEl24 avgpredays1-avgpredays24 avgpostmax1-avgpostmax24 avgpremax1-avgpremax24 avgpremn1-avgpremn24 avgpostmn1-avgpostmn24; label dxcat="C-PASS Diagnosis"; label ncycles="Number of Cycles"; WomanID=subject; call symput("ncyc", ncycles); run; proc sort data=cpassout; by dxcat; run; proc format ; value cat .="Unscored" 0="No Diagnosis" 1="MRMD" 2="DSM-5 PMDD"; value dx .="Unscored" 0="No" 1="Yes"; value metcrit 0="No" 1="Yes"; run; /*Output Sample-Level Frequencies*/ %if &samplestat=on %then %do; ods graphics / width=5 in height=4 in; ods noproctitle; proc freq data=cpassout; table dxcat /missing; Title "Carolina Premenstrual Assessment Scoring System (C-PASS)"; Title2 "Sample-Level Results"; format dxcat cat.; run; proc sgplot data=cpassout; histogram dxcat/scale=count showbins nbins=3; Title "Sample-Level Diagnostic Frequencies"; format dxcat cat.; run; ods graphics off; %end; /*Output Diagnostic Status of Each Subject*/ proc sort data=cpassout; by womanid; run; proc print data=cpassout noobs; var womanid PMDD MRMD NCycles; format mrmd dx.; format pmdd dx.; Title "Carolina Premenstrual Assessment Scoring System (C-PASS)"; Title2 "Diagnostic Status of Each Subject"; run; /*Generate Detailed Output for Specified Subjects with Daily Rating Visuals and Symptom-Level Diagnoses by Cycle*/ proc format ; value noseven 7=" "; run; proc transpose data=_all1_ out=_all1wide_ prefix=metcrit_; var metcrit; by subject cycle; run; data outwcycles; merge cpassout(keep=subject ncycles) &data; by subject; run; data cpassgraph; merge outwcycles _all1wide_; by subject cycle; womanID=subject; run; %let nsubj=%sysfunc(countw(&visualsublist)); %do j=1 %to &nsubj; %let subj=%scan(&visualsublist, &j); %let ncyc=; data _null_; set cpassgraph; where subject=&subj; call symput("ncyc", ncycles); run; /*Print Cycle-Level Diagnoses for Each Symptom by Subject*/ proc sort data=cpassgraph out=cpassgraphp nodupkey; by subject cycle; run; proc print data=cpassgraphp noobs heading=h label split='*'; var cycle metcrit_1-metcrit_8; where subject=&subj; Title "Subject &subj: Item-Level Diagnoses in each Cycle"; Title2 "- Core Emotional Symptoms -"; label metcrit_1="Depressed" metcrit_2="Hopeless" metcrit_3="Worthless* or* Guilty" metcrit_4="Anxious" metcrit_5="Mood* Swings" metcrit_6="Rejection* Sensitivity" metcrit_7="Anger or* Irritability" metcrit_8="Interpersonal* Conflict"; format metcrit_1-metcrit_24 metcrit.; run; proc print data=cpassgraphp noobs heading=h label split='*'; var cycle metcrit_9-metcrit_21; where subject=&subj; Title "Subject &subj: Item-Level Diagnoses in each Cycle"; Title2 "- Secondary Symptoms - "; label metcrit_9="Less* Interest" metcrit_10="Difficulty* Concentrating" metcrit_11="Lethargic" metcrit_12="Appetite* or* Overate" metcrit_13="Food* Cravings" metcrit_14="Slept* More" metcrit_15="Trouble* Sleeping" metcrit_16="Overwhelmed" metcrit_17="Out of* Control" metcrit_18="Breast* Tenderness" metcrit_19="Swelling,* Bloating,* Weight Gain" metcrit_20="Headache* (Not in* DSM-5 Dx)" metcrit_21="Joint or* Muscle* Pain"; format metcrit_1-metcrit_24 metcrit.; run; proc print data=cpassgraphp noobs heading=h label split='*'; var cycle metcrit_22-metcrit_24; where subject=&subj; Title "Subject &subj: Item-Level Diagnoses in each Cycle"; Title2 "- Interference Items -"; Title3 "(Not Required for DSM-5 Diagnosis)"; label metcrit_22="Work* Interference" metcrit_23="Hobby/Social* Interference" metcrit_24="Relationship* Interference"; format metcrit_1-metcrit_24 metcrit.; run; /*Graph Daily Ratings*/ %if &visualsublist ne "off" %then %do; %let width=6; %let height=%sysevalf(&ncyc*2.75); ods graphics / width=&width in height=&height in; %do i=1 %to 24; proc sgpanel data=cpassgraph noautolegend; where subject=&subj; panelby cycle metcrit_&i/columns=1; refline 3.8/axis=y lineattrs=(color=black thickness=1 pattern=4) name="sig" legendlabel="Threshold for Clinical Significance"; refline 3.2/axis=y lineattrs=(pattern=35 color=black thickness=2) name="clear" legendlabel="Threshold for Clearance"; refline 1 /axis=x labelattrs=(weight=bold) lineattrs=(thickness=2 color=black) label="Premenstrual Week" labelpos=max; refline 11/axis=x labelattrs=(weight=bold) lineattrs=(thickness=2 color=black) label="Postmenstrual Week" labelpos=max; keylegend "sig" "clear"/ position=bottom; band x=drsp&i upper=6 lower=3.8 / transparency=.80 fillAttrs=(color=green); rowaxis min=1 max=7; colaxis min=-1 max=11 values=(-7, -6, -5, -4, -3, -2, -1, 4, 5, 6, 7, 8, 9, 10, 11) fitpolicy=stagger; series x=day y=drsp&i / group=phase markers MARKERATTRS=(symbol=circlefilled size=8 color=black) lineattrs=(pattern=1 color=black thickness=1); title "Daily Ratings for Subject &subj - DRSP&i"; label cycle="Cycle"; label drsp1="Depressed, Down, Blue" drsp2="Hopeless" drsp3="Worthless or Guilty" drsp4="Anxious, Keyed Up, or On Edge" drsp5="Mood Swings" drsp6="Rejection Sensitivity" drsp7="Anger, Irritability" drsp8="Interpersonal Conflict" drsp9="Less Interest in Usual Activities" drsp10="Difficulty Concentrating" drsp11="Lethargic, Tired" drsp12="Increased Appetite, Overate" drsp13="Specific Food Cravings" drsp14="Slept More, Took Naps, Difficulty Getting Up" drsp15="Trouble Getting to or Staying Asleep" drsp16="Felt Overwhelmed, Couldn't Cope" drsp17="Felt Out of Control" drsp18="Breast Tenderness" drsp19="Breast Swelling, Bloating, Weight Gain" drsp20="Headache (Not in DSM-5 Dx)" drsp21="Joint or Muscle Pain" drsp22="Work Interference (Not in DSM-5 Dx)" drsp23="Hobbies or Social Activity Interference (Not in DSM-5 Dx)" drsp24="Relationship Interference (Not in DSM-5 Dx)" day="Cycle Day" ncycles="Number of Cycles" metcrit_&i="Does DRSP&i Meet DSM-5 Criteria this Cycle?"; format drsp&i noseven.; format metcrit_&i metcrit.; run; %end; %end; %end; %mend cpass; /*********************************************************************/ /********************CALLING THE C-PASS MACRO*************************/ /*********************************************************************/; libname cpass "/folders/myfolders/dx_study"; %cpass (data=, samplestat=, visualsublist=)