source: main/adopters/md/trunk/src/main/backend_qModules/brfss23/SurveyCrudeRate.sas @ 19541

Last change on this file since 19541 was 19541, checked in by Paul Leo, 11 months ago

New Age group distributions for use in calculating age adjusted rates

File size: 11.0 KB
Line 
1*******************************************************************************************************;
2* Program filename: SurveyCrudeRate.sas                                                                 ;
3*                                                                                                      ;
4* This file is "included" in each BRFSS indicator .def file for crude rates. The macro variables       ;
5* (varname, weight) are also set in the .def file. The %spvar2% variable is referenced in the .def     ;
6* file. The value for %spvar2% is set in the IBIS Module.xml file. It is also a filter-exclude         ;
7* variable, which allows keeps the whole survey dataset in the analytic file, and allows the user to   ;
8* select whether to calculate the at-risk percentage (%VarLevel=1) or the not-at-risk percentage       ;
9* (%VarLevel=2).                                                                                       ;
10*                                                                                                      ;
11* Missing values have been set to '.' for all indicator and dimension variables.                       ;
12*                                                                                                      ;
13* Notes for ibisq survey program.                                                                      ;
14*                                                                                                      ;
15* surveyvar1 allow the variance estimate to be calculated with the entire dataset, regardless of other ;
16* dataset filters. This is appropriate according to Michael Friedrichs in Utah.                        ;
17*                                                                                                      ;
18* ageadjfilter has something to do with maintaining the entire population dataset in the results for   ;
19* the state overall.                                                                                   ;
20*******************************************************************************************************;
21
22OPTIONS MPRINT MLOGIC SYMBOLGEN SPOOL SOURCE2;
23options sumsize=138m nocenter pagesize=4000 linesize=MAX;
24
25/* CODE FOR ADJUSTING FOR MULTIPLE YEARS.
26    CURRENTLY NOT USING SINCE ONLY DOING ONE YEAR
27        COULD LEAVE THIS IN, BUT PREFER NOT TO
28       
29   proc freq data=tmp noprint;
30     tables year / out=wgt;
31     run;
32     proc print data=wgt noobs; title1 '-------------'; title2 'wgt: first output frequency table'; run;
33   
34   data wgt;
35     set wgt;
36     keep year wpercent;
37     wpercent=percent/100;
38     run;
39     proc print data=wgt noobs; title1 '-------------'; title2 'wgt: final year percentages'; run;
40     
41   proc sort data=tmp; by year; run;
42   data tmp;
43     merge wgt tmp;
44     by year;
45     _LLCPWT=_LLCPWT*wpercent;
46     run;
47    *proc print data=tmp (obs=10); title2 'tmp: for submission to proc surveymeans'; run;
48       
49*/
50
51title2 'PROC SURVEYMEANS OUTPUT';
52
53******************************************************************************;
54*%macro crudrt(varname,weight,FocusLevel);
55******************************;
56%macro crudrt(varname,weight);
57
58?cross1? proc surveymeans data=tmp nomcar nobs sum mean stderr CLM CV;
59?cross1?  var &varname. ;
60?cross1?   class &varname. ;
61?cross1?   strata _STSTR;
62?cross1?   domain
63?cross1? %cross1%
64?cross1? %surveyvar1%
65?cross1? ;
66?cross1?   ods output statistics=stats
67?cross1?        summary=sum
68?cross1?        domain=domain ;
69?cross1?   weight &weight. ;
70?cross1?   proc print data=stats; title1 ' '; title2 'stats';
71?cross1?   proc print data=domain; title2 'domain';
72?cross1? run;
73
74?cross1? ?cross2? proc surveymeans data=tmp nomcar nobs sum mean stderr CLM CV;
75?cross1? ?cross2?   var &varname. ;
76?cross1? ?cross2?   class &varname. ;
77?cross1? ?cross2?   strata _STSTR;
78?cross1? ?cross2?  domain
79?cross1? ?cross2? %cross1%*%cross2%
80?cross1? ?cross2? %surveyvar1%
81?cross1? ?cross2? ;
82?cross1? ?cross2?   ods output statistics=stats
83?cross1? ?cross2?       summary=sum
84?cross1? ?cross2?       domain=domain ;
85?cross1? ?cross2?   weight &weight. ;
86?cross1? ?cross2?   proc print data=stats; title1 ' '; title2 'stats';
87?cross1? ?cross2?   proc print data=domain; title2 'domain';
88?cross1? ?cross2? run;
89
90*****************************************************************;
91********* tmp1: Grab stats for dimension totals *****************;
92*****************************************************************;
93data tmp1;
94  set stats;
95  wgtN=ROUND(sum,1);
96  &varname.=input(VarLevel, 8.);
97  %cross1% = -1;
98  ?cross2? %cross2% = -1;
99  *drop VarLevel VarName VarLabel wgtN StdDev;
100  proc print;
101        title1 '===================================================================';
102        title2 'tot: Grab percentage for MD overall';
103run;
104
105******************************************************************;
106********* tmp2: Grab %, SE, codes for indicator variable *********;
107******************************************************************;
108data tmp2;
109  set domain;
110    wgtN=ROUND(sum,1);
111  &varname.=input(VarLevel, 8.);
112  *drop LowerCLMean UpperCLMean VarLevel DomainLabel VarLabel VarName wgtN StdDev;
113  %if '%cross1%' != 'year' %then %do;
114        if year_sflag<=0 then delete;
115  %end;
116  proc print; title2 'tmp2: stats for indicator variable';
117run;
118
119**********************************************************;
120********** tmp3: Grab sample size (denominator) **********;
121****** N Number of respondents in sample *****************;
122*****  Denom denominator in each cross by group **********;
123**********************************************************;
124proc summary data=tmp2;
125  var N;
126  class %cross1%
127  ?cross2? %cross2%
128  &varname.
129  ;
130  output out=sampleD sum(N)=Denom;
131  proc sort data=SampleD; by %cross1%
132  ?cross2? %cross2%
133  ;
134  proc print; title2 'SampleD - (Unweighted number of folks who answered either y or n) Number of Records for cell suppression';
135  run;
136data tmp3;
137  set SampleD;
138  if &varname. =.;
139  *Denom=N;
140  drop  _TYPE_ _FREQ_ N ;
141  if %cross1% = . then %cross1% = -1;
142  ?cross2? if %cross2% = . then %cross2% = -1;
143  proc print; title2 'tmp3, Sample Size (denominator)';
144run;
145/*   MD will not use Asymmetric Confidence Intervals
146        If they want to in future, need to align the tmp datasets
147*****************************************************************;
148********** tmp4: Calculate asymmetric confidence ints ***********;
149*****************************************************************;
150data tmp2;
151        set tmp2;
152run;
153data tmp4;
154  set tmp2 tmp1;
155  f=log(mean)-log(1-mean); 
156  s=stderr/(mean*(1-mean));
157  Lf=f-1.96*s; 
158  Uf=f+1.96*s; 
159  percent=mean*100;
160  lower=(exp(Lf)/(1+exp(Lf)))*100;   
161  upper=(exp(Uf)/(1+exp(Uf)))*100;
162  drop f s Lf Uf VarName;
163  proc sort data=tmp4; by %cross1%
164        ?cross2? %cross2%
165        ;
166  proc print; title2 'tmp4: Calculate asymmetric CIs';
167run;
168*/
169data tmp4;
170        set tmp2 tmp1; /* totals onto the domain (cross1 and cross2 */
171        percent=mean*100;
172        lower=LowerCLMean*100;
173        upper=UpperCLMean*100;
174         proc sort data=tmp4; by %cross1%
175        ?cross2? %cross2%
176        ;
177        proc print; title2 'tmp4:merged tmp2 (from proc summary) and tmp1 (stats), and set percent=mean';
178run;
179******************************************************************;
180********* tmp5: Add Denom field to every record ******************;
181********* this is only for cell suppression           ************;
182******************************************************************;
183
184data tmp5; *Add Denom field to each record;
185  merge tmp3 tmp4 ;
186  by %cross1%
187  ?cross2? %cross2%
188  ;
189  proc print; title2 'tmp5: Add denom field to every record';
190run;
191
192*****************************************************************;
193********** tmp5alt: Add wgtdenom field to every record ************;
194**********wgtdenom is the weighted denominator
195*********Used by MD and HI, they want pop num, not Denom*******;
196***********  **************************;
197*****************************************************************;
198proc summary data=tmp5;
199  var wgtN;
200  class %cross1%
201  ?cross2? %cross2%
202  &varname.
203  ;
204  output out=wgtNdat sum(wgtN)=wgtdenom;
205  proc sort data=wgtNdat; by %cross1%
206  ?cross2? %cross2%
207  ;
208  proc print; title2 'wgtNdat - estimated population category in that category or response';
209  run;
210  data wgtdenomdat;
211  set wgtNdat;
212  if &varname. =.;
213  if %cross1% = . then delete;
214        ?cross2? if %cross2% = . then delete;
215  proc print; title2 'wgtdenomdat: Total rows of weighted N - estimated number in that category or response';
216        run;
217       
218  proc sort data=tmp5;
219        by %cross1%
220        ?cross2? %cross2%
221        ;
222        run;
223  proc sort data=wgtdenomdat;
224        by %cross1%
225        ?cross2? %cross2%
226        ;
227        run;
228
229data tmp6; *Add wgtdenom field to each record;
230  merge wgtdenomdat tmp5;
231  by %cross1%
232  ?cross2? %cross2%
233  ;
234  drop _TYPE_ _FREQ_ ;
235  proc print; title2 'tmp6: Add weighted sample (wgtdenom) field to every record';
236run;
237
238************************************************************;
239********** tmp6: Add RSE, redflag to dataset, clean up *****;
240************************************************************;
241* redflag is the statistical stability indicator, based on  ;
242* the relative standard error (RSE, or coefficient of       ;
243* variation.                                                ;
244************************************************************;
245
246data tmp7;
247  set tmp6;
248/* USING CV instead
249  if 0<mean<.50 then RSE=(StdErr/mean);
250  if .50<=mean<1 then RSE=(StdErr/(1-mean));
251 */
252  redflag=put('Stable', $14.);
253  if CV>.3 then redflag=put('Unstable', $14.);
254  if Denom in (0 1) then redflag=put('No Variance', $14.);
255
256
257
258  if (%cross1%=-1) then %cross1%=.;
259  ?cross2? if (%cross2%=-1) then %cross2%=.;
260  popnum=wgtdenom;
261  *drop RSE Mean StdErr Denom;
262
263  proc sort data=tmp7; by %cross1%
264  ?cross2? %cross2%
265  &varname.
266  ;
267  run;
268
269proc print data=tmp7; title2 'tmp7: Add redflag to dataset, clean up';
270run;
271
272************************************************************;
273*********** tmp: Convert values for cell suppression *******;
274************************************************************;
275data tmp;
276  set tmp7;
277  **** spvar2 ************************************************************;
278  * spvar2 is the indicator DIMENSION/VALUE passed in by the URL.         ;
279  * I have included "." in the if statement because ZWs total row cell    ;
280  * suppression algorithm was getting confused about where the total rows ;
281  * were and suppressing too many rows. ibisph-view will ignore all but   ;
282  * the grand total row. But the others need to stay in.                  ;
283  ************************************************************************;
284  if &varname in (%spvar2% .);
285  if (0<Denom<30)  OR  (CV >.3) then do;        /* MD cell supression Rule  Denom (number of folks who answered either y or n)*/
286        wgtN  = .A;
287        percent = .A;
288        lower = .A;
289        upper = .A;
290        popnum = .A;
291        redflag=put('Not Reportable', $14.);
292  end;
293  proc print data=tmp; title2 'final tmp: Convert values for cell suppression';
294run;
295
296%mend;
297
Note: See TracBrowser for help on using the repository browser.