<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: A Macro For Getting More Out Of Your ROC Curve: Cut off for best sensitivity Specificity trade in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/A-Macro-For-Getting-More-Out-Of-Your-ROC-Curve-Cut-off-for-best/m-p/260024#M50391</link>
    <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;When I run your macro as is proposed in the paper I get&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;ERROR: Variable SENSIT not found.&lt;/PRE&gt;
&lt;P&gt;And that is understandable as the column is called _SENSIT_ with the surrounding underscores. The underscores are present in the paper so I assume a type of sorts is at play. For me this simple fix helped:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;* %LET LIST = SENSIT SPEC TA YI NPV PPV MCC TME TME1 TME2 WME WME1 WME2;
%LET LIST = _SENSIT_ SPEC TA YI NPV PPV MCC TME TME1 TME2 WME WME1 WME2;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;What helps in troubleshooting macro's &amp;nbsp;is running your code with the appropriate options. For they were&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options mprint symbolgen;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;but there are more.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Regards, Jan.&lt;/P&gt;</description>
    <pubDate>Wed, 30 Mar 2016 11:10:11 GMT</pubDate>
    <dc:creator>jklaverstijn</dc:creator>
    <dc:date>2016-03-30T11:10:11Z</dc:date>
    <item>
      <title>A Macro For Getting More Out Of Your ROC Curve: Cut off for best sensitivity Specificity trade</title>
      <link>https://communities.sas.com/t5/SAS-Programming/A-Macro-For-Getting-More-Out-Of-Your-ROC-Curve-Cut-off-for-best/m-p/260007#M50385</link>
      <description>&lt;P&gt;Hi everyone,&lt;/P&gt;
&lt;P&gt;I really hope someone will take the time and effort to correct this Macro, I have have been trying to figure out what the problem is but in vain.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This is a Macro that calculates the optimal cut off trae for sensitivity and specificty, the priginal post back from 2008 is available here:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www2.sas.com/proceedings/forum2008/231-2008.pdf" target="_blank"&gt;http://www2.sas.com/proceedings/forum2008/231-2008.pdf&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This is a great macro of use to many people. It has been used in several published papers, now it seems to be broken, and I am trying to fix it without any luck, but I am not a power programmer as many others here are, hoping someone will solve it for all of us needing this macro otherwise.&lt;/P&gt;
&lt;P&gt;Here is the code: I think the error come after the line with the Data _Null_ step.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%MACRO SNSP_TRADEOFF(
/**********************************************************************
MACRO NAME : SNSP_TRADEOFF
PURPOSE : CREATES A GRAPH WITH MULTIPLE ROC MEASURES
SAS VERSION : VERSION 8.2, 9.1
PARAMETERS :
-----------------------------------------------------------------------
NAME TYPE DEFAULT DESCRIPTION AND VALID VALUES
--------- -------- -------- -----------------------------------------
DATASET REQUIRED : SOURCE DATASET
OUTCOME REQUIRED : RESPONSE VARIABLE (CATEGORICAL)
OUTCOME_LEV REQUIRED : EVENT OF INTEREST. A LEVEL OF THE OUTCOME
PARAMETER THAT DEFINES THE EVENT
(E.G., OUTCOME_LEV=1 OR OUTCOME_LEV=RELAPSE)
XVAR REQUIRED : CONTINUOUS PREDICTOR
FONT OPTIONAL ARIAL : FONT TYPE OF GRAPHICAL OUTPUT
XVAR_LABEL OPTIONAL : LABEL OF PREDICTOR IN GRAPHICAL OUTPUT
AUC OPTIONAL Y : Y/N. DISPLAY AREA UNDER CURVE
SN OPTIONAL Y : Y/N. DISPLAY SENSITIVITY
SP OPTIONAL Y : Y/N. DISPLAY SPECIFICITY
TA OPTIONAL : Y/N. DISPLAY TOTAL ACCURACY
YI OPTIONAL : Y/N. DISPLAY YOUDEN INDEX
NPV OPTIONAL : Y/N. DISPLAY NEGATIVE PREDICTIVE VALUE
PPV OPTIONAL : Y/N. DISPLAY POSITIVE PREDICTIVE VALUE
MCC OPTIONAL : Y/N. DISPLAY MCC
TME OPTIONAL : Y/N. DISPLAY TOTAL MISCLASSIFICATION
ERROR USING INVERSE OF TARGET GROUP
AS LOSS
TME1 OPTIONAL : Y/N. DISPLAY TOTAL MISCLASSIFICATION
ERROR USING INVERSE OF OVERALL
SAMPLE SIZE AS LOSS
TME2 OPTIONAL : Y/N. DISPLAY TOTAL MISCLASSIFICATION
ERROR USING RATIO OF LOSSES
WME OPTIONAL : Y/N. DISPLAY WEIGHTED MISCLASSIFICATION
ERROR USING INVERSE OF TARGET GROUP
AS LOSS
WME1 OPTIONAL : Y/N. DISPLAY WEIGHTED MISCLASSIFICATION
ERROR USING INVERSE OF OVERALL
SAMPLE SIZE AS LOSS
WME2 OPTIONAL : Y/N. DISPLAY WEIGHTED MISCLASSIFICATION
ERROR USING RATIO OF LOSSES
GAMMA REQUIRED IF : Y/N. POSITIVE NUMERIC VALUE OF RATIO OF
LFN/LFP
TME2 OR WME2=Y (I.E., LOSS DUE TO
MISCLASSIFICATION OF A TRUE
POSITIVE EVENT IS "GAMMA" TIMES
LARGER THAN MISCLASSIFICATION
OF A TRUE NEGATIVE EVENT)
-------------------------------------------------------------------------
NOTES :THE FOLLOWING DATASETS ARE CREATED IN THE WORK LIBRARY AND DELETED
BY THE MACRO PRIOR TO ALL CALCULATIONS.
_SNSP_EST, _SNSP_ROC1, _SNSP_AUC, _SNSP_OUTPUT.
**************************************************************************/
DATASET = , OUTCOME = , OUTCOME_LEV = , XVAR = , FONT = ARIAL,
XVAR_LABEL = , AUC = Y, SN = Y, SP = Y, TA = , YI = , NPV = ,
PPV = , MCC = , TME = , TME1 = , TME2 = , WME = , WME1 = ,
WME2 = , GAMMA = );
%PUT MACRO SNSP_TRADEOFF IS NOW EXECUTING...;
%*****************************************************************;
%* CHECKING THAT REQUIRED PARAMETERS ARE SPECIFIED *;
%*****************************************************************;
%IF %SYSFUNC(EXIST(&amp;amp;DATASET)) = 0 %THEN %DO;
%PUT ERROR: DATA SET &amp;amp;DATASET IS MISSING;
%GOTO EXIT;
%END;
%IF %LENGTH(&amp;amp;DATASET) = 0 %THEN %DO;
%PUT ERROR: VALUE FOR PARAMETER DATASET IS MISSING;
%GOTO EXIT;
%END;
%IF %LENGTH(&amp;amp;OUTCOME) = 0 %THEN %DO;
%PUT ERROR: VALUE FOR PARAMETER OUTCOME IS MISSING;
%GOTO EXIT;
%END;
%IF %LENGTH(&amp;amp;OUTCOME_LEV) = 0 %THEN %DO;
%PUT ERROR: VALUE FOR PARAMETER OUTCOME_LEV IS MISSING;
%GOTO EXIT;
%END;
%IF %LENGTH(&amp;amp;XVAR) = 0 %THEN %DO;
%PUT ERROR: VALUE FOR PARAMETER XVAR IS MISSING;
%GOTO EXIT;
%END;
%IF &amp;amp;TME2 = Y OR &amp;amp;WME2 = Y %THEN %DO;
%IF %SYSEVALF(&amp;amp;GAMMA &amp;lt;= 0) %THEN %DO;
%PUT ERROR: VALUE FOR GAMMA IS MISSING OR INCORRECT;
%GOTO EXIT;
%END;
%END;
%LOCAL COUNT;
%LOCAL CURDATA;
%LET DATASETS = _SNSP_EST _SNSP_ROC1 _SNSP_AUC _SNSP_OUTPUT;
%IF %LENGTH(&amp;amp;DATASETS) &amp;gt; 0 %THEN %DO;
%LET COUNT=1;
%LET CURDATA =%SCAN(&amp;amp;DATASETS,&amp;amp;COUNT,' ');
%DO %WHILE(&amp;amp;CURDATA NE);
%IF %SYSFUNC(EXIST(&amp;amp;CURDATA)) %THEN %DO;
PROC DATASETS NOLIST;
DELETE &amp;amp;CURDATA;
RUN; QUIT;
%END;
%LET COUNT=%EVAL(&amp;amp;COUNT+1);
%LET CURDATA =%SCAN(&amp;amp;DATASETS,&amp;amp;COUNT,' ');
%END;
%END;
%LET AUC=%UPCASE(&amp;amp;AUC);
%LET SN=%UPCASE(&amp;amp;SN);
%LET SP=%UPCASE(&amp;amp;SP);
%LET TA=%UPCASE(&amp;amp;TA);
%LET YI=%UPCASE(&amp;amp;YI);
%LET NPV=%UPCASE(&amp;amp;NPV);
%LET PPV=%UPCASE(&amp;amp;PPV);
%LET MCC=%UPCASE(&amp;amp;MCC);
%LET TME=%UPCASE(&amp;amp;TME);
%LET TME1=%UPCASE(&amp;amp;TME1);
%LET TME2=%UPCASE(&amp;amp;TME2);
%LET WME=%UPCASE(&amp;amp;WME);
%LET WME1=%UPCASE(&amp;amp;WME1);
%LET WME2=%UPCASE(&amp;amp;WME2);
%LET OUTCOME_LEV = %SYSFUNC(TRANWRD(&amp;amp;OUTCOME_LEV,%STR(%"),));
%LET OUTCOME_LEV = %SYSFUNC(TRANWRD(&amp;amp;OUTCOME_LEV,%STR(%'),));
%*****************************************************************;
%* GETTING ROC OUTPUT FROM MODEL *;
%*****************************************************************;
ODS LISTING CLOSE;
PROC LOGISTIC DATA=&amp;amp;DATASET OUTEST=_SNSP_EST;
MODEL &amp;amp;OUTCOME (EVENT = "&amp;amp;OUTCOME_LEV") = &amp;amp;XVAR/EXPB OUTROC=_SNSP_ROC1;
ODS OUTPUT ASSOCIATION=_SNSP_AUC (WHERE = (UPCASE(LABEL2) = "C"));
RUN;
ODS LISTING;
DATA _SNSP_ROC1;
SET _SNSP_ROC1; INDEX =1;
RUN;
DATA _SNSP_EST (KEEP=INTERCEPT &amp;amp;XVAR INDEX);
SET _SNSP_EST; INDEX =1;
RUN;
DATA _SNSP_OUTPUT;
MERGE _SNSP_ROC1 _SNSP_EST;
BY INDEX;
SPEC = 1-_1MSPEC_;
YI = (_SENSIT_ + SPEC) - 1;
N = _POS_+ _NEG_+ _FALPOS_+ _FALNEG_;
TA = (_POS_ + _NEG_)/N;
X_VALUE = (LOG(_PROB_/(1-_PROB_))-INTERCEPT)/&amp;amp;XVAR;
IF (_NEG_+_FALNEG_) NE 0 THEN DO;
NPV = _NEG_/(_NEG_ +_FALNEG_);
END;
IF (_POS_+_FALPOS_) NE 0 THEN DO;
PPV = _POS_/(_POS_ +_FALPOS_);
END;
IF((_POS_+_FALPOS_)*(_POS_+_FALNEG_)*(_NEG_+_FALPOS_)*(_NEG_+_FALNEG_)) NE 0
THEN DO;
MCC = ((_POS_*_NEG_)-(_FALPOS_*_FALNEG_))/SQRT(((_POS_+_FALPOS_)*(_POS_+_FALNEG_)*(_NEG_+_FALPOS_)*(_NEG_+_FALNEG_)));
END;
%*****************************************************************;
%* FOR TOTAL ERRORS *;
%*****************************************************************;
%***TARGET GROUP;
LFN = 1/(_POS_ + _FALNEG_);
LFP = 1/(_NEG_ + _FALPOS_);
TLN = _FALNEG_*LFN;
TLP = _FALPOS_*LFP;
TME = TLN+TLP;
%***EQUAL FPR/FNR;
LFN1 = 1/N;
LFP1 = 1/N;
TLN1 = _FALNEG_*LFN1;
TLP1 = _FALPOS_*LFP1;
TME1 = TLN1+TLP1;
%*****************************************************************;
%* FOR WEIGHTED ERRORS *;
%*****************************************************************;
%***TARGET GROUP;
WFN = LFN/(LFN+LFP);
WFP = LFP/(LFN+LFP);
WLN = (_FALNEG_*WFN)/N;
WPN = (_FALPOS_*WFP)/N;
WME = WLN+WPN;
%***EQUAL FPR/FNR;
WFN1 = LFN1/(LFN1+LFP1);
WFP1 = LFP1/(LFN1+LFP1);
WLN1 = (_FALNEG_*WFN1)/N;
WPN1 = (_FALPOS_*WFP1)/N;
WME1 = WLN1+WPN1;
DENSITY = 0;
RUN;
%*****************************************************************;
%* RATIO FOR TOTAL-AND-WEIGHTED ERRORS *;
%*****************************************************************;


DATA _SNSP_OUTPUT;
SET _SNSP_OUTPUT;
%IF %SYSEVALF(&amp;amp;GAMMA &amp;gt; 0) %THEN %DO;
G=&amp;amp;GAMMA;
TME2_NSCALE = TLN1+TLP1*(1/G);
WME2 = TLN1*(G/(1+G))+TLP1*(1/(1+G));
RUN;
PROC SQL NOPRINT;
SELECT MAX(TME2_NSCALE) INTO: MAX_TME2
FROM _SNSP_OUTPUT;
QUIT;
DATA _SNSP_OUTPUT;
SET _SNSP_OUTPUT;
TME2 = TME2_NSCALE/&amp;amp;MAX_TME2;
RUN;
%END;
%ELSE %DO;
TME2 = .;
WME2 = .;

%LET WME2 = N;
%LET TME2 = N;
%END;
RUN;

%IF &amp;amp;AUC = Y %THEN %DO;
DATA _NULL_;
SET _SNSP_AUC;
CALL SYMPUT("AUCVALUE", PUT((NVALUE2),8.3));
RUN;
%END;
%LET FIRST = / &amp;amp;SN/ &amp;amp;SP/ &amp;amp;TA/ &amp;amp;YI/ &amp;amp;NPV/ &amp;amp;PPV/ &amp;amp;MCC/ &amp;amp;TME/ &amp;amp;TME1/ &amp;amp;TME2/ &amp;amp;WME/ &amp;amp;WME1/ &amp;amp;WME2;
%LET LIST = SENSIT SPEC TA YI NPV PPV MCC TME TME1 TME2 WME WME1 WME2;

%DO I = 1 %TO 13;
%IF %SCAN(&amp;amp;FIRST, &amp;amp;I, "/") = Y %THEN %DO;
%LET TT&amp;amp;I = %SCAN(&amp;amp;LIST, &amp;amp;I, " ")*X_VALUE=%EVAL(&amp;amp;I+1);
%END;
%ELSE %LET TT&amp;amp;I = ;
%END;

TITLE "Operating characteristics for &amp;amp;OUTCOME = &amp;amp;OUTCOME_LEV";
AXIS1 W=1 OFFSET=(3 PCT) LABEL=(F=&amp;amp;FONT H=2 "&amp;amp;XVAR_LABEL");
AXIS2 W=1 OFFSET=(3 PCT) LABEL=(F=&amp;amp;FONT H=2 A=90 R=0 "Proportion") ORDER = (0 TO 1 BY 0.1);
LEGEND1 VALUE=(F=&amp;amp;FONT H=1.5) LABEL=(F=&amp;amp;FONT H=1.5 "Operating Characteristics:");
%IF &amp;amp;AUC = Y %THEN %DO;
LEGEND2 VALUE=(F=&amp;amp;FONT H=1.5)
LABEL=(F=&amp;amp;FONT H=1.5 JUSTIFY=C "Operating Characteristics:"
H=1.3 JUSTIFY=C "AUC=&amp;amp;AUCVALUE");
%END;
SYMBOL1 H=0.3 I=NONE W=1 C=BLACK V="|";
SYMBOL2 H=1 I=JOIN L=1 W=2C=RED;
SYMBOL3 H=1 I=JOIN L=2 W=2C=BLUE;
SYMBOL4 H=1 I=JOIN L=4 W=2C=GREEN;
SYMBOL5 H=1 I=JOIN L=6 W=2 C=PURPLE;
SYMBOL6 H=1 I=JOIN L=8 W=2 C=ORANGE;
SYMBOL7 H=1 I=JOIN L=10 W=2 C=BLACK;
SYMBOL8 H=1 I=JOIN L=12 W=2 C=RGR;
SYMBOL9 H=1 I=JOIN L=14 W=2 C=LIME;
SYMBOL10 H=1 I=JOIN L=16 W=2 C=BROWN;
SYMBOL11 H=1 I=JOIN L=22 W=2 C=PINK;
SYMBOL12 H=1 I=JOIN L=32 W=2 C=MAGENTA;
SYMBOL13 H=1 I=JOIN L=33 W=2 C=YELLOW;
SYMBOL14 H=1 I=JOIN L=24 W=2 C=VLIGB;
PROC GPLOT DATA = _SNSP_OUTPUT;
PLOT DENSITY*X_VALUE=1 &amp;amp;TT1 &amp;amp;TT2 &amp;amp;TT3 &amp;amp;TT4 &amp;amp;TT5 &amp;amp;TT6 &amp;amp;TT7 &amp;amp;TT8 &amp;amp;TT9 &amp;amp;TT10 &amp;amp;TT11 &amp;amp;TT12 &amp;amp;TT13 /OVERLAY VAXIS=AXIS2 HAXIS=AXIS1
%IF &amp;amp;AUC = Y %THEN %DO;
LEGEND=LEGEND2;
%END;
%ELSE %DO;
LEGEND=LEGEND1;
%END;
LABEL DENSITY = "Data Density" TA = "Total Accuracy" YI= "Youden Index"
SPEC = "Specificity" TME = "Total Error, Group" TME1 = "Total
Error, Overall"
TME2 = "Scaled Total Error, Ratio" WME = "Weighted Error, Group"
WME1 = "Weighted Error, Overall" WME2 = "Weighted Error, Ratio";
RUN;
QUIT;
%EXIT:
TITLE;
%MEND SNSP_TRADEOFF;
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Wed, 30 Mar 2016 08:58:05 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/A-Macro-For-Getting-More-Out-Of-Your-ROC-Curve-Cut-off-for-best/m-p/260007#M50385</guid>
      <dc:creator>ammarhm</dc:creator>
      <dc:date>2016-03-30T08:58:05Z</dc:date>
    </item>
    <item>
      <title>Re: A Macro For Getting More Out Of Your ROC Curve: Cut off for best sensitivity Specificity trade</title>
      <link>https://communities.sas.com/t5/SAS-Programming/A-Macro-For-Getting-More-Out-Of-Your-ROC-Curve-Cut-off-for-best/m-p/260024#M50391</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;When I run your macro as is proposed in the paper I get&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;ERROR: Variable SENSIT not found.&lt;/PRE&gt;
&lt;P&gt;And that is understandable as the column is called _SENSIT_ with the surrounding underscores. The underscores are present in the paper so I assume a type of sorts is at play. For me this simple fix helped:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;* %LET LIST = SENSIT SPEC TA YI NPV PPV MCC TME TME1 TME2 WME WME1 WME2;
%LET LIST = _SENSIT_ SPEC TA YI NPV PPV MCC TME TME1 TME2 WME WME1 WME2;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;What helps in troubleshooting macro's &amp;nbsp;is running your code with the appropriate options. For they were&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;options mprint symbolgen;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;but there are more.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Regards, Jan.&lt;/P&gt;</description>
      <pubDate>Wed, 30 Mar 2016 11:10:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/A-Macro-For-Getting-More-Out-Of-Your-ROC-Curve-Cut-off-for-best/m-p/260024#M50391</guid>
      <dc:creator>jklaverstijn</dc:creator>
      <dc:date>2016-03-30T11:10:11Z</dc:date>
    </item>
    <item>
      <title>Re: A Macro For Getting More Out Of Your ROC Curve: Cut off for best sensitivity Specificity trade</title>
      <link>https://communities.sas.com/t5/SAS-Programming/A-Macro-For-Getting-More-Out-Of-Your-ROC-Curve-Cut-off-for-best/m-p/260029#M50393</link>
      <description>&lt;P&gt;Thanks Jan, Appreciate your help&lt;/P&gt;
&lt;P&gt;Kind regards&lt;/P&gt;
&lt;P&gt;Am&lt;/P&gt;</description>
      <pubDate>Wed, 30 Mar 2016 11:17:07 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/A-Macro-For-Getting-More-Out-Of-Your-ROC-Curve-Cut-off-for-best/m-p/260029#M50393</guid>
      <dc:creator>ammarhm</dc:creator>
      <dc:date>2016-03-30T11:17:07Z</dc:date>
    </item>
  </channel>
</rss>

