<?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: Modify data/cell with specific condition. in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Modify-data-cell-with-specific-condition/m-p/480041#M124021</link>
    <description>&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/*------------------------------------------------------------------*   
| MACRO NAME  : senspe   
| SHORT DESC  : Calculate sensitivity and specificity   
*------------------------------------------------------------------*   
| CREATED BY  : Cha, Stephen                  (08/18/2005  9:51)   
*------------------------------------------------------------------*   
| PURPOSE   
|   
| Get a) Freq table with missing options   
| b) calculate sensitivity and specificity with 95% CI   
| c) calculate PPV and PNV with 95% CI   
*------------------------------------------------------------------*   
| OPERATING SYSTEM COMPATIBILITY   
|   
| UNIX SAS v8   :   
| UNIX SAS v9   :   YES   
| MVS SAS v8    :   
| MVS SAS v9    :   
| PC SAS v8     :   
| PC SAS v9     :   
*------------------------------------------------------------------*   
| MACRO CALL   
|   
| %senspe  (   
|            data= ,   
|            testvar= ,   
|            truthvar=   
|          );   
*------------------------------------------------------------------*   
| REQUIRED PARAMETERS   
|   
| Name      : data   
| Default   :   
| Type      : Text   
| Purpose   : SAS dataset   
|   
| Name      : testvar   
| Default   :   
| Type      : Text   
| Purpose   : a test variable (Y=1 and N=1)   
|   
| Name      : truthvar   
| Default   :   
| Type      : Text   
| Purpose   : the gold standard variable (Y=1 and N=0)   
|   
*------------------------------------------------------------------*   
| Copyright 2005 Mayo Clinic College of Medicine.   
|   
| This program is free software; you can redistribute it and/or   
| modify it under the terms of the GNU General Public License as   
| published by the Free Software Foundation; either version 2 of   
| the License, or (at your option) any later version.   
|   
| This program is distributed in the hope that it will be useful,   
| but WITHOUT ANY WARRANTY; without even the implied warranty of   
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   
| General Public License for more details.   



*------------------------------------------------------------------*/
/** Macro to compute the    
a) specificity and sensitivity, and their 95% confidence interval    
b) PPV and PNV and their 95% confidence Interval     
*****************************************************************;    
*** SAS MACRO spesen                                          ***;    
*** DATE: 9/02/2003                                           ***;    
*** AUTHOR: CHA, STEPHEN &amp;amp; STEPHANIE BAGNIEWSKI               ***;    
*****************************************************************;     
THIS MACRO(SPESEN) COMPUTES THE Specifity,Sensitivity, PPV, and PNV    
and their 95% CONFIDENCE INTERVAL. FOR A 2*2 TABLE WHERE THE ROWS    
AND COLUMNS CONTAIN 2 LEVELS (0=NO, 1=YES).     
REFERENCE: BISHOP, FIENBERG AND HOLLAND. DISCRETE MULTIVARIATE               
ANALYSIS: THEORY AND PRACTICE. MIT PRESS(1975).     

INPUT:  SAS DATA SET WITH N OBSERVATIONS CONTAINING THE ROW VARIABLE      
AND THE COLUMN VARIABLE ON THE SAME OBSERVATION.     

MACRO CALL:  %spesen(DATA,testVAR=,TruthVAR=);
 
OUTPUT: A)FREQUENCY TABLE (WITH MISSING OPTIONS) 
 
B)Sensitivity and Specivity and 95% CI            
C)PPV and PNV and 95% CI     
example: %spesen(data=temp,testvar=xvar,truthvar=yvar);
**/





%macro spesen(data=,testvar=,truthvar=);
	**************************************;
	* Take out missing and dump freq     *;
	**************************************;
	proc format;
		value ansf  0="No "                1="Yes";

	data temp1;
		set &amp;amp;data;
		format &amp;amp;testvar &amp;amp;truthvar ansf.;

	proc freq;
		tables &amp;amp;testvar*&amp;amp;truthvar/nopct missing;

	data temp2;
		set temp1;

		if &amp;amp;testvar=. or &amp;amp;truthvar=. then
			delete;

	proc freq;
		tables &amp;amp;testvar*&amp;amp;truthvar/noprint sparse out=dd1;

		**************************************;
		* get specificity and Sensitivity    *;
		**************************************;
	data tmp1;
		set dd1;
		id=1;

	proc sort;
		by id;

	data tmp2;
		set tmp1;
		by id;
		keep a b c d;

		if first.id then
			do;
				a=0;
				b=0;
				c=0;
				d=0;
				retain a b c d;
			end;

		if &amp;amp;testvar=1 &amp;amp; &amp;amp;truthvar=1 then
			A=count;

		if &amp;amp;testvar=1 &amp;amp; &amp;amp;truthvar=0 then
			B=count;

		if &amp;amp;testvar=0 &amp;amp; &amp;amp;truthvar=1 then
			C=count;

		if &amp;amp;testvar=0 &amp;amp; &amp;amp;truthvar=0 then
			D=count;

		if last.id then
			output;

	data tmp3;
		set tmp2;
		cat="Sensitivity";
		rate=A/(A+C);
		LPCT=(1.0-95.0/100)/2;
		UPCT=1-LPCT;
		Phat=rate;

		**NORMAL APPROXIMATION;    L_normal=PHAT+PROBIT(LPCT)*SQRT(PHAT*(1-PHAT)/(A+C));
		*LOWER LIMIT;    U_normal=PHAT+PROBIT(UPCT)*SQRT(PHAT*(1-PHAT)/(A+C));
		*UPPER LIMIT;
		**POISSON APPROXIMATION;    DF_LO=2*A;    DF_UP=2*(A+1);
		IF A GT 0 THEN
			L_poissn=GAMINV(LPCT,DF_LO/2)/(A+C);

		*LOWER LIMIT;
		ELSE L_POI=0;
		U_poissn=GAMINV(UPCT,DF_UP/2)/(A+C);

		*UPPER LIMIT;
		*** EXACT BINOMIAL CONFIDENCE LIMITS ***equn 10.7 of Feller*;
		* Upper limit;
		if A&amp;lt;(A+C) then
			u_exact=1-betainv(lpct,C,A+1);
		else u_exact=1;

		* Lower limit;
		if A&amp;gt;0 then
			l_exact=1-betainv(upct,C+1,A);
		else l_exact=0;
		keep cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;

	data tmp4;
		set tmp2;
		cat="Specificity";
		rate=D/(B+D);
		LPCT=(1.0-95.0/100)/2;
		UPCT=1-LPCT;
		Phat=rate;

		**NORMAL APPROXIMATION;    L_normal=PHAT+PROBIT(LPCT)*SQRT(PHAT*(1-PHAT)/(B+D));
		*LOWER LIMIT;    U_normal=PHAT+PROBIT(UPCT)*SQRT(PHAT*(1-PHAT)/(B+D));
		*UPPER LIMIT;
		**POISSON APPROXIMATION;    DF_LO=2*D;    DF_UP=2*(D+1);
		IF D GT 0 THEN
			L_poissn=GAMINV(LPCT,DF_LO/2)/(B+D);

		*LOWER LIMIT;
		ELSE L_POI=0;
		U_poissn=GAMINV(UPCT,DF_UP/2)/(B+D);

		*UPPER LIMIT;
		*** EXACT BINOMIAL CONFIDENCE LIMITS ***equn 10.7 of Feller*;
		* Upper limit;
		if D&amp;lt;(B+D) then
			u_exact=1-betainv(lpct,B,D+1);
		else u_exact=1;

		* Lower limit;
		if D&amp;gt;0 then
			l_exact=1-betainv(upct,B+1,D);
		else l_exact=0;
		keep cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;

	data tmp5;
		set tmp2;
		cat="PPV";
		rate=A/(A+B);
		LPCT=(1.0-95.0/100)/2;
		UPCT=1-LPCT;
		Phat=rate;

		**NORMAL APPROXIMATION;    L_normal=PHAT+PROBIT(LPCT)*SQRT(PHAT*(1-PHAT)/(A+B));
		*LOWER LIMIT;    U_normal=PHAT+PROBIT(UPCT)*SQRT(PHAT*(1-PHAT)/(A+B));
		*UPPER LIMIT;
		**POISSON APPROXIMATION;    DF_LO=2*A;    DF_UP=2*(A+1);
		IF A GT 0 THEN
			L_poissn=GAMINV(LPCT,DF_LO/2)/(A+B);

		*LOWER LIMIT;
		ELSE L_POI=0;
		U_poissn=GAMINV(UPCT,DF_UP/2)/(A+B);

		*UPPER LIMIT;
		*** EXACT BINOMIAL CONFIDENCE LIMITS ***equn 10.7 of Feller*;
		* Upper limit;
		if A&amp;lt;(A+B) then
			u_exact=1-betainv(lpct,B,A+1);
		else u_exact=1;

		* Lower limit;
		if A&amp;gt;0 then
			l_exact=1-betainv(upct,B+1,A);
		else l_exact=0;
		keep cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;

	data tmp6;
		set tmp2;
		cat="PNV";
		rate=D/(C+D);
		LPCT=(1.0-95.0/100)/2;
		UPCT=1-LPCT;
		Phat=rate;

		**NORMAL APPROXIMATION;    L_normal=PHAT+PROBIT(LPCT)*SQRT(PHAT*(1-PHAT)/(C+D));
		*LOWER LIMIT;    U_normal=PHAT+PROBIT(UPCT)*SQRT(PHAT*(1-PHAT)/(C+D));
		*UPPER LIMIT;
		**POISSON APPROXIMATION;    DF_LO=2*D;    DF_UP=2*(D+1);
		IF D GT 0 THEN
			L_poissn=GAMINV(LPCT,DF_LO/2)/(C+D);

		*LOWER LIMIT;
		ELSE L_POI=0;
		U_poissn=GAMINV(UPCT,DF_UP/2)/(C+D);

		*UPPER LIMIT;
		*** EXACT BINOMIAL CONFIDENCE LIMITS ***equn 10.7 of Feller*;
		* Upper limit;
		if D&amp;lt;(C+D) then
			u_exact=1-betainv(lpct,C,D+1);
		else u_exact=1;

		* Lower limit;
		if D&amp;gt;0 then
			l_exact=1-betainv(upct,C+1,D);
		else l_exact=0;
		keep cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;

	data tmp7;
		set tmp2;
		cat="ACCURACY";
		rate=(A+D)/(A+B+C+D);
		LPCT=(1.0-95.0/100)/2;
		UPCT=1-LPCT;
		Phat=rate;

		**NORMAL APPROXIMATION;    L_normal=PHAT+PROBIT(LPCT)*SQRT(PHAT*(1-PHAT)/(C+D));
		*LOWER LIMIT;    U_normal=PHAT+PROBIT(UPCT)*SQRT(PHAT*(1-PHAT)/(C+D));
		*UPPER LIMIT;
		**POISSON APPROXIMATION;    DF_LO=2*D;    DF_UP=2*(D+1);
		IF D GT 0 THEN
			L_poissn=GAMINV(LPCT,DF_LO/2)/(C+D);

		*LOWER LIMIT;
		ELSE L_POI=0;
		U_poissn=GAMINV(UPCT,DF_UP/2)/(C+D);

		*UPPER LIMIT;
		*** EXACT BINOMIAL CONFIDENCE LIMITS ***equn 10.7 of Feller*;
		* Upper limit;
		if D&amp;lt;(C+D) then
			u_exact=1-betainv(lpct,C,D+1);
		else u_exact=1;

		* Lower limit;
		if D&amp;gt;0 then
			l_exact=1-betainv(upct,C+1,D);
		else l_exact=0;
		keep cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;

	data output;
		set tmp3 tmp4 tmp5 tmp6 tmp7;
		rate=rate*100;
		L_normal=L_Normal*100;
		u_normal=u_normal*100;
		l_poissn=l_poissn*100;
		u_poissn=u_poissn*100;
		l_exact=l_exact*100;
		u_exact=u_exact*100;
		label L_normal="Normal Approximation (L)"          
		U_normal="95% CI (Upper)"          
		L_poissn="Poisson Approximation (L)"          
		U_poissn="95% CI (Upper)"          
		L_exact="Exact Binomial (L)"          
		U_exact="95% CI (Upper)";

	proc print label n;
		var cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;
	run;

%mend;&lt;/CODE&gt;&lt;/PRE&gt;</description>
    <pubDate>Fri, 20 Jul 2018 19:28:23 GMT</pubDate>
    <dc:creator>Reeza</dc:creator>
    <dc:date>2018-07-20T19:28:23Z</dc:date>
    <item>
      <title>Modify data/cell with specific condition.</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Modify-data-cell-with-specific-condition/m-p/480032#M124019</link>
      <description>&lt;P&gt;I&amp;nbsp;calculated 2 tables in SAS like the following:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Table1:&lt;/P&gt;&lt;P&gt;_NUME_&amp;nbsp; &amp;nbsp; &amp;nbsp; Positive&amp;nbsp; &amp;nbsp; Negative&amp;nbsp; &amp;nbsp; &amp;nbsp;Total&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Sensitivity&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Specificity&lt;/P&gt;&lt;P&gt;Positive&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 6&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 6&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1&lt;BR /&gt;Negative&amp;nbsp; &amp;nbsp; &amp;nbsp; 0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 78&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 78&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0.5407418736&amp;nbsp; &amp;nbsp; 0.9538075797&lt;BR /&gt;Total&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;6&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 78&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 84&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Table2:&lt;/P&gt;&lt;P&gt;_NUME_&amp;nbsp; &amp;nbsp; &amp;nbsp; Positive&amp;nbsp; &amp;nbsp; Negative&amp;nbsp; &amp;nbsp; &amp;nbsp;Total&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Sensitivity&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Specificity&lt;/P&gt;&lt;P&gt;Positive&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1&lt;BR /&gt;Negative&amp;nbsp; &amp;nbsp; &amp;nbsp; 0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 83&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 83 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0.957&lt;BR /&gt;Total&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 83&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 84&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I want to change the Sensitivity if the intersected cell Positive*Positive =0, then all the numbers in column Sensitivity=0.&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%MACRO XXXXXXXX
********other macro code ***************
data outcome2 (replace=yes);
		set outcome1;
		if Positive=0 then Sensitivity=0;
		run;

********** more code ****************&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;My code will not fit table1's situation, since Positive*Positive not equal to 0, but Positive*Negative=0. Apply this code will change the Sensitivity in my table1 to 0's too, how can I fix it?&lt;/P&gt;</description>
      <pubDate>Fri, 20 Jul 2018 19:03:31 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Modify-data-cell-with-specific-condition/m-p/480032#M124019</guid>
      <dc:creator>y_fu</dc:creator>
      <dc:date>2018-07-20T19:03:31Z</dc:date>
    </item>
    <item>
      <title>Re: Modify data/cell with specific condition.</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Modify-data-cell-with-specific-condition/m-p/480038#M124020</link>
      <description>&lt;P&gt;Did you see the link I listed yesterday that had all the formulas needed for these calculations. If you want an automates solution, the approach you're using seems a bit of overkill. Will this always be a two by two table?&amp;nbsp;&lt;/P&gt;
&lt;P&gt;How general do you want it to be?&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Usually for these types of projects, I strongly recommend the following steps:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;1. Get it working for a base case - no macro logic at all&lt;/P&gt;
&lt;P&gt;2. Replace variable names with macro variable references and data sets names iwth macro variable reference&lt;/P&gt;
&lt;P&gt;3. Add a step to clean up any temporary data sets not needed&lt;/P&gt;
&lt;P&gt;4. Wrap it in a %MACRO/%MEND and add the parameters as from #2.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This process usually ensure that you won't run into any errors.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you want to maintain this approach, please clarify the following:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;SPAN&gt;My code will not fit table1's situation, since Positive*Positive not equal to 0, but Positive*Negative=0. Apply this code will change the Sensitivity in my table1 to 0's too, how can I fix it?&lt;/SPAN&gt;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Are you referring to the data step code in the post, the single line of if/then?&lt;/P&gt;
&lt;P&gt;How is your input data structured? When you say Positive*Positive which cells are you referring to? Are you trying to work with a single row or across a column?&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I'd probably guess for a two by two table its easiest to reformat the data to have it all in one line. Do all your calculations and then reformat for the output.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 20 Jul 2018 19:17:27 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Modify-data-cell-with-specific-condition/m-p/480038#M124020</guid>
      <dc:creator>Reeza</dc:creator>
      <dc:date>2018-07-20T19:17:27Z</dc:date>
    </item>
    <item>
      <title>Re: Modify data/cell with specific condition.</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Modify-data-cell-with-specific-condition/m-p/480041#M124021</link>
      <description>&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/*------------------------------------------------------------------*   
| MACRO NAME  : senspe   
| SHORT DESC  : Calculate sensitivity and specificity   
*------------------------------------------------------------------*   
| CREATED BY  : Cha, Stephen                  (08/18/2005  9:51)   
*------------------------------------------------------------------*   
| PURPOSE   
|   
| Get a) Freq table with missing options   
| b) calculate sensitivity and specificity with 95% CI   
| c) calculate PPV and PNV with 95% CI   
*------------------------------------------------------------------*   
| OPERATING SYSTEM COMPATIBILITY   
|   
| UNIX SAS v8   :   
| UNIX SAS v9   :   YES   
| MVS SAS v8    :   
| MVS SAS v9    :   
| PC SAS v8     :   
| PC SAS v9     :   
*------------------------------------------------------------------*   
| MACRO CALL   
|   
| %senspe  (   
|            data= ,   
|            testvar= ,   
|            truthvar=   
|          );   
*------------------------------------------------------------------*   
| REQUIRED PARAMETERS   
|   
| Name      : data   
| Default   :   
| Type      : Text   
| Purpose   : SAS dataset   
|   
| Name      : testvar   
| Default   :   
| Type      : Text   
| Purpose   : a test variable (Y=1 and N=1)   
|   
| Name      : truthvar   
| Default   :   
| Type      : Text   
| Purpose   : the gold standard variable (Y=1 and N=0)   
|   
*------------------------------------------------------------------*   
| Copyright 2005 Mayo Clinic College of Medicine.   
|   
| This program is free software; you can redistribute it and/or   
| modify it under the terms of the GNU General Public License as   
| published by the Free Software Foundation; either version 2 of   
| the License, or (at your option) any later version.   
|   
| This program is distributed in the hope that it will be useful,   
| but WITHOUT ANY WARRANTY; without even the implied warranty of   
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   
| General Public License for more details.   



*------------------------------------------------------------------*/
/** Macro to compute the    
a) specificity and sensitivity, and their 95% confidence interval    
b) PPV and PNV and their 95% confidence Interval     
*****************************************************************;    
*** SAS MACRO spesen                                          ***;    
*** DATE: 9/02/2003                                           ***;    
*** AUTHOR: CHA, STEPHEN &amp;amp; STEPHANIE BAGNIEWSKI               ***;    
*****************************************************************;     
THIS MACRO(SPESEN) COMPUTES THE Specifity,Sensitivity, PPV, and PNV    
and their 95% CONFIDENCE INTERVAL. FOR A 2*2 TABLE WHERE THE ROWS    
AND COLUMNS CONTAIN 2 LEVELS (0=NO, 1=YES).     
REFERENCE: BISHOP, FIENBERG AND HOLLAND. DISCRETE MULTIVARIATE               
ANALYSIS: THEORY AND PRACTICE. MIT PRESS(1975).     

INPUT:  SAS DATA SET WITH N OBSERVATIONS CONTAINING THE ROW VARIABLE      
AND THE COLUMN VARIABLE ON THE SAME OBSERVATION.     

MACRO CALL:  %spesen(DATA,testVAR=,TruthVAR=);
 
OUTPUT: A)FREQUENCY TABLE (WITH MISSING OPTIONS) 
 
B)Sensitivity and Specivity and 95% CI            
C)PPV and PNV and 95% CI     
example: %spesen(data=temp,testvar=xvar,truthvar=yvar);
**/





%macro spesen(data=,testvar=,truthvar=);
	**************************************;
	* Take out missing and dump freq     *;
	**************************************;
	proc format;
		value ansf  0="No "                1="Yes";

	data temp1;
		set &amp;amp;data;
		format &amp;amp;testvar &amp;amp;truthvar ansf.;

	proc freq;
		tables &amp;amp;testvar*&amp;amp;truthvar/nopct missing;

	data temp2;
		set temp1;

		if &amp;amp;testvar=. or &amp;amp;truthvar=. then
			delete;

	proc freq;
		tables &amp;amp;testvar*&amp;amp;truthvar/noprint sparse out=dd1;

		**************************************;
		* get specificity and Sensitivity    *;
		**************************************;
	data tmp1;
		set dd1;
		id=1;

	proc sort;
		by id;

	data tmp2;
		set tmp1;
		by id;
		keep a b c d;

		if first.id then
			do;
				a=0;
				b=0;
				c=0;
				d=0;
				retain a b c d;
			end;

		if &amp;amp;testvar=1 &amp;amp; &amp;amp;truthvar=1 then
			A=count;

		if &amp;amp;testvar=1 &amp;amp; &amp;amp;truthvar=0 then
			B=count;

		if &amp;amp;testvar=0 &amp;amp; &amp;amp;truthvar=1 then
			C=count;

		if &amp;amp;testvar=0 &amp;amp; &amp;amp;truthvar=0 then
			D=count;

		if last.id then
			output;

	data tmp3;
		set tmp2;
		cat="Sensitivity";
		rate=A/(A+C);
		LPCT=(1.0-95.0/100)/2;
		UPCT=1-LPCT;
		Phat=rate;

		**NORMAL APPROXIMATION;    L_normal=PHAT+PROBIT(LPCT)*SQRT(PHAT*(1-PHAT)/(A+C));
		*LOWER LIMIT;    U_normal=PHAT+PROBIT(UPCT)*SQRT(PHAT*(1-PHAT)/(A+C));
		*UPPER LIMIT;
		**POISSON APPROXIMATION;    DF_LO=2*A;    DF_UP=2*(A+1);
		IF A GT 0 THEN
			L_poissn=GAMINV(LPCT,DF_LO/2)/(A+C);

		*LOWER LIMIT;
		ELSE L_POI=0;
		U_poissn=GAMINV(UPCT,DF_UP/2)/(A+C);

		*UPPER LIMIT;
		*** EXACT BINOMIAL CONFIDENCE LIMITS ***equn 10.7 of Feller*;
		* Upper limit;
		if A&amp;lt;(A+C) then
			u_exact=1-betainv(lpct,C,A+1);
		else u_exact=1;

		* Lower limit;
		if A&amp;gt;0 then
			l_exact=1-betainv(upct,C+1,A);
		else l_exact=0;
		keep cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;

	data tmp4;
		set tmp2;
		cat="Specificity";
		rate=D/(B+D);
		LPCT=(1.0-95.0/100)/2;
		UPCT=1-LPCT;
		Phat=rate;

		**NORMAL APPROXIMATION;    L_normal=PHAT+PROBIT(LPCT)*SQRT(PHAT*(1-PHAT)/(B+D));
		*LOWER LIMIT;    U_normal=PHAT+PROBIT(UPCT)*SQRT(PHAT*(1-PHAT)/(B+D));
		*UPPER LIMIT;
		**POISSON APPROXIMATION;    DF_LO=2*D;    DF_UP=2*(D+1);
		IF D GT 0 THEN
			L_poissn=GAMINV(LPCT,DF_LO/2)/(B+D);

		*LOWER LIMIT;
		ELSE L_POI=0;
		U_poissn=GAMINV(UPCT,DF_UP/2)/(B+D);

		*UPPER LIMIT;
		*** EXACT BINOMIAL CONFIDENCE LIMITS ***equn 10.7 of Feller*;
		* Upper limit;
		if D&amp;lt;(B+D) then
			u_exact=1-betainv(lpct,B,D+1);
		else u_exact=1;

		* Lower limit;
		if D&amp;gt;0 then
			l_exact=1-betainv(upct,B+1,D);
		else l_exact=0;
		keep cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;

	data tmp5;
		set tmp2;
		cat="PPV";
		rate=A/(A+B);
		LPCT=(1.0-95.0/100)/2;
		UPCT=1-LPCT;
		Phat=rate;

		**NORMAL APPROXIMATION;    L_normal=PHAT+PROBIT(LPCT)*SQRT(PHAT*(1-PHAT)/(A+B));
		*LOWER LIMIT;    U_normal=PHAT+PROBIT(UPCT)*SQRT(PHAT*(1-PHAT)/(A+B));
		*UPPER LIMIT;
		**POISSON APPROXIMATION;    DF_LO=2*A;    DF_UP=2*(A+1);
		IF A GT 0 THEN
			L_poissn=GAMINV(LPCT,DF_LO/2)/(A+B);

		*LOWER LIMIT;
		ELSE L_POI=0;
		U_poissn=GAMINV(UPCT,DF_UP/2)/(A+B);

		*UPPER LIMIT;
		*** EXACT BINOMIAL CONFIDENCE LIMITS ***equn 10.7 of Feller*;
		* Upper limit;
		if A&amp;lt;(A+B) then
			u_exact=1-betainv(lpct,B,A+1);
		else u_exact=1;

		* Lower limit;
		if A&amp;gt;0 then
			l_exact=1-betainv(upct,B+1,A);
		else l_exact=0;
		keep cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;

	data tmp6;
		set tmp2;
		cat="PNV";
		rate=D/(C+D);
		LPCT=(1.0-95.0/100)/2;
		UPCT=1-LPCT;
		Phat=rate;

		**NORMAL APPROXIMATION;    L_normal=PHAT+PROBIT(LPCT)*SQRT(PHAT*(1-PHAT)/(C+D));
		*LOWER LIMIT;    U_normal=PHAT+PROBIT(UPCT)*SQRT(PHAT*(1-PHAT)/(C+D));
		*UPPER LIMIT;
		**POISSON APPROXIMATION;    DF_LO=2*D;    DF_UP=2*(D+1);
		IF D GT 0 THEN
			L_poissn=GAMINV(LPCT,DF_LO/2)/(C+D);

		*LOWER LIMIT;
		ELSE L_POI=0;
		U_poissn=GAMINV(UPCT,DF_UP/2)/(C+D);

		*UPPER LIMIT;
		*** EXACT BINOMIAL CONFIDENCE LIMITS ***equn 10.7 of Feller*;
		* Upper limit;
		if D&amp;lt;(C+D) then
			u_exact=1-betainv(lpct,C,D+1);
		else u_exact=1;

		* Lower limit;
		if D&amp;gt;0 then
			l_exact=1-betainv(upct,C+1,D);
		else l_exact=0;
		keep cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;

	data tmp7;
		set tmp2;
		cat="ACCURACY";
		rate=(A+D)/(A+B+C+D);
		LPCT=(1.0-95.0/100)/2;
		UPCT=1-LPCT;
		Phat=rate;

		**NORMAL APPROXIMATION;    L_normal=PHAT+PROBIT(LPCT)*SQRT(PHAT*(1-PHAT)/(C+D));
		*LOWER LIMIT;    U_normal=PHAT+PROBIT(UPCT)*SQRT(PHAT*(1-PHAT)/(C+D));
		*UPPER LIMIT;
		**POISSON APPROXIMATION;    DF_LO=2*D;    DF_UP=2*(D+1);
		IF D GT 0 THEN
			L_poissn=GAMINV(LPCT,DF_LO/2)/(C+D);

		*LOWER LIMIT;
		ELSE L_POI=0;
		U_poissn=GAMINV(UPCT,DF_UP/2)/(C+D);

		*UPPER LIMIT;
		*** EXACT BINOMIAL CONFIDENCE LIMITS ***equn 10.7 of Feller*;
		* Upper limit;
		if D&amp;lt;(C+D) then
			u_exact=1-betainv(lpct,C,D+1);
		else u_exact=1;

		* Lower limit;
		if D&amp;gt;0 then
			l_exact=1-betainv(upct,C+1,D);
		else l_exact=0;
		keep cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;

	data output;
		set tmp3 tmp4 tmp5 tmp6 tmp7;
		rate=rate*100;
		L_normal=L_Normal*100;
		u_normal=u_normal*100;
		l_poissn=l_poissn*100;
		u_poissn=u_poissn*100;
		l_exact=l_exact*100;
		u_exact=u_exact*100;
		label L_normal="Normal Approximation (L)"          
		U_normal="95% CI (Upper)"          
		L_poissn="Poisson Approximation (L)"          
		U_poissn="95% CI (Upper)"          
		L_exact="Exact Binomial (L)"          
		U_exact="95% CI (Upper)";

	proc print label n;
		var cat rate L_normal u_normal l_poissn u_poissn l_exact u_exact;
	run;

%mend;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Fri, 20 Jul 2018 19:28:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Modify-data-cell-with-specific-condition/m-p/480041#M124021</guid>
      <dc:creator>Reeza</dc:creator>
      <dc:date>2018-07-20T19:28:23Z</dc:date>
    </item>
  </channel>
</rss>

