source: main/adopters/hi/trunk/src/main/backend_qModules/3.0/qModules30/brfss/SurveyAARateDist9plus.sas @ 24986

Last change on this file since 24986 was 24986, checked in by LoisHaggard_STG, 4 months ago

HI 3.0 backend/qModules30 updated BRFSS, YRBS and YTS value attribute names in .SAS files to use correct value attributes for "Stable" for each survey.

File size: 16.9 KB
Line 
1**********************************************************************;
2* Program filename: TotalSurvAgeBRFSS.sas                             ;
3*                                                                     ;
4* This file is "included" in each BRFSS indicator .def file for AA    ;
5* rates. The macro variables (varname, weight) are also set in the    ;
6* .def file. The %FocusLevel% variable is set in the IBIS Module.xml  ;
7* file as a filter exclude variable. This allows the user to select   ;
8* whether to calculate the at-risk percentage (%VarLevel=1) or the    ;
9* not-at-risk percentage (%VarLevel=2).                               ;
10*                                                                     ;
11* Missing set to . for all indicator and dimension vars               ;
12*                                                                     ;
13**********************************************************************;
14
15OPTIONS MPRINT MLOGIC MLOGICNEST SYMBOLGEN SPOOL SOURCE2 SUMSIZE=138M PAGESIZE=4000 LINESIZE=MAX;
16
17**********************************************************************************************;
18* CODE FOR ADJUSTING FOR MULTIPLE YEARS. ONLY NEEDED IF PRESENTING POPULATION COUNT ESTIMATES.;
19* If cross1 and cross2 are not equal to year, then _llcpwt is divided by the number of years  ;
20* the user selects                                                                            ;
21**********************************************************************************************;
22 
23/* proc print data=tmp (obs=10); run; */
24
25proc freq data=tmp;
26   tables year / out=yrfreq noprint;
27   run;
28   proc print data=yrfreq;
29        title1 ' '; title2 'yrfreq';
30        run;
31 
32 proc summary data=yrfreq;
33        class Year;
34        output out=yrnum n(year)=nyears;
35           proc print data=yrnum;
36                title1 ' '; title2 'yrnum';
37        run;
38
39data yrnum; set yrnum;
40        if year=.;
41        keep year nyears;
42           proc print data=yrnum;
43        title1 ' '; title2 'yrnum only .';
44run;   
45       
46proc sort data=tmp; by year; run;
47
48        proc sql;
49                create table tmpyrwgt as
50                select tmp.*, yrnum.nyears
51                from tmp, yrnum
52        quit;
53   
54 data tmp;
55     set tmpyrwgt;
56         if upcase(%cross1%) ^=YEAR
57         ?cross2? and upcase(%cross2%) ^=YEAR
58         then
59     _llcpwt=_llcpwt/nyears;
60   run;
61   
62/*proc print data=tmp (obs=10);
63        title1 ' '; title2 'checktmp .'; run;
64*/   
65
66/**** SURVEYMEANS*************************************************************;
67* Run the SURVEYMEANS proc with Age BRFSS in domain statement.                ;
68* No cross1 or cross2, run this first to get the totals.                      ;
69******************************************************************************;
70*/
71
72%macro ageadjrt(varname,weight,Focuslevel);
73
74 title1 '***************************************************************';
75 title2 'SURVEYMEANS proc (AgeBRFSS in domain statement and no cross vars)';
76 proc surveymeans data=tmp nobs sum mean stderr;
77        var &varname.;
78        class &varname.;
79        strata ststr;
80        domain AgeBRFSS
81                %surveyvar1%
82                ;
83        ods output statistics=stats
84                summary=summary
85                domain=domain ;
86                weight &weight. ;
87        run;
88
89***** TOTALTMP ****************************************************************;
90* Read the totals into memory and create the total row flag variables, trow1   ;
91* flags the total row for cross1 and trow2 flags the total row for cross2.     ;
92* I think the cross2 with ?s is code that ibisq uses to create the program,    ;
93* it checks for cross2 and uses that line in the program only if cross2 exists.;
94* trow1 and trow2 are used in AGEADJUST step and again used in                 ;
95* redflag step,to recode to appropriate values                                 ;
96*******************************************************************************;
97 title2 'TOTALTMP : Stats for total rows (trow1 and trow2 initialized to 1)';
98 data totaltmp;
99        set work.domain;
100        drop DomainLabel VarLabel;
101        /*trow1 and 2 are used later to get aawt*/
102        trow1 = 1;
103        ?cross2? trow2 = 1;
104run;
105 proc print data=totaltmp noobs; run;
106
107***** TMP ********************************************************************;
108* Set domain vars to AgeBRFSS, cross1, cross2 and run survey means            ;
109******************************************************************************;
110 title2 'TMP: SurveyMeans for domain vars and crosses (AgeBRFSS by cross1 and cross2)';
111 proc surveymeans data=tmp nobs sum mean stderr;
112        var &varname.;
113        class &varname.  ;
114        strata ststr;
115        domain AgeBRFSS*%cross1%
116                ?cross2? *%cross2%
117        ;
118        ods output statistics=stats
119                summary=summary
120                domain=domain ;
121                weight &weight. ;
122        run;
123       
124 proc sort data=work.domain;
125        by %cross1% %cross2% AgeBRFSS ;
126        run;
127       
128***** TMPALL *****************************************************************;
129* CONCATENATE TOTAL ROWS ONTO NEW DOMAIN DATASET                              ;
130* work.domain is the new domain output, totaltemp is the new one with the     ;
131* cross1 and cross2 output. (recodes based on var type (char or num)          ;
132* determined use of SAS vtype function                                        ;
133******************************************************************************;
134 title2 'TMPALL: stats for domain vars with totals added';
135 
136 data tmpall;
137        set work.domain totaltmp;
138    &varname.=input(VarLevel, $54.);
139        drop DomainLabel VarLabel;
140       
141        if (vtype(%cross1%)="C" and %cross1%='') then %cross1% = 'tot';
142        if (vtype(%cross1%)="N" and %cross1%=.) then %cross1% = -1;
143        ?cross2? if (vtype(%cross2%)="C" and %cross2%='') then %cross2% = 'tot';
144        ?cross2? if (vtype(%cross2%)="N" and %cross2%=.) then %cross2% = -1;
145       
146        proc print data=tmpall noobs; run;
147
148***** NORMALIZE **************************************************************;
149* Now, go back to work.domain records and compute new weights that are        ;
150* normalized.                                                                 ;
151* What is the problem? Let us say the user filters the dataset to a small     ;
152*  population, like blacks in Kauai, and that population does not have survey ;
153* records in all 7 AA age groups. The weights will not sum to 1.0. So we do   ;
154* this step that finds the age groups that are represented in the filtered    ;
155* dataset, and recomputes (normalizes) the weights so that they sum to 1.0    ;
156* AgeBRFSS - NCHS Statnote20 distribution #9 WITH 75+ FOR HI BRFSS            ;
157******************************************************************************;
158 title2 'NORMALIZE: grab records in work.domain (actual records)';
159 data norm;
160        set work.domain;
161        drop DomainLabel VarLabel;
162        %ageAdjustedFilter%
163        run;
164        proc print data=norm noobs; run;
165
166 title2 'getwts: grab weights for records actually in dataset, row totals denoted when trow1 and trow2 = 1';
167 data getwts;
168        set norm totaltmp;
169       
170    /* this is just to document the age ranges.
171       Age BRFSS is already in the dataset, and is
172                used in the domain statement for aarates.
173                18-24   0.128809768
174                25-34   0.182648111
175                35-44   0.219076679
176                45-54   0.181652285
177                55-64   0.117541734
178                65-74   0.088966942
179                75+     0.081304482
180   */
181
182        aawt=0; /*probably don't need to set these here, but... ??*/
183        if AgeBRFSS="18-24" then aawt=0.128809768;
184        if AgeBRFSS="25-34" then aawt=0.182648111;
185        if AgeBRFSS="35-44" then aawt=0.219076679;
186        if AgeBRFSS="45-54" then aawt=0.181652285;
187        if AgeBRFSS="55-64" then aawt=0.117541734;
188        if AgeBRFSS="65-74" then aawt=0.088966942;
189        if AgeBRFSS="75+"       then aawt=0.081304482;
190       
191        if N=0 then Mean=0;
192
193   run;
194   proc print data=getwts noobs; run;
195
196***** SUMWTS *****************************************************************;
197* PRODUCE THE SUM OF THE WEIGHTS BASED ON THE AGE GROUPS THAT ARE PRESENT     ;
198******************************************************************************;
199 title2 'SUMWTS: sums of the weights for records in dataset by crossvars';
200 proc summary data=getwts nway;
201   var aawt;
202   class %cross1% %cross2% VarLevel;
203   output out=sumwts sum(aawt)=sumwt;
204   proc sort data=sumwts;
205   by %cross1% %cross2% VarLevel;
206   run;
207   proc print data=sumwts noobs; run;
208
209   proc sort data=tmpall;
210   by %cross1% %cross2% VarLevel;
211   run;
212
213***** AGEADJUST **************************************************************;
214* Merge the sum of the weights onto the dataset and divide aawt by sumwt to   ;
215* provide normalized weights.                                                 ;
216* AgeBRFSS - NCHS Statnote20 distribution #9 + 75+, for HI BRFSS              ;
217******************************************************************************;
218 title2 'AGEADJUST: merge sumwts onto dataset, normalize aawts';
219 data AgeAdjust;
220   merge tmpall sumwts;
221   by %cross1% %cross2% VarLevel;
222        aawt=0;
223        if AgeBRFSS="18-24" then aawt=0.128809768;
224        if AgeBRFSS="25-34" then aawt=0.182648111;
225        if AgeBRFSS="35-44" then aawt=0.219076679;
226        if AgeBRFSS="45-54" then aawt=0.181652285;
227        if AgeBRFSS="55-64" then aawt=0.117541734;
228        if AgeBRFSS="65-74" then aawt=0.088966942;
229        if AgeBRFSS="75+"       then aawt=0.081304482;
230   normwt=aawt/sumwt; *normwt is the "normalized" weight for age-adjusting;
231   if trow1=1 then normwt=aawt;
232   if trow2=1 then normwt=aawt;
233   
234   if N=0 then Mean=0;
235
236   run;
237   proc print data=AgeAdjust noobs; run;
238
239***** TMP ********************************************************************;
240* Produce cross-products for weighted percentages.                            ;
241******************************************************************************;
242 title2 'TMP: dataset with cross-products (wgt_percent)';
243 data tmp;
244   set AgeAdjust;
245   keep AgeBRFSS %cross1% %cross2% VarName VarLevel &varname. N Mean StdErr normwt wgt_percent wgt_var trow1 trow2;
246   &varname.=input(VarLevel, $54.);
247   wgt_percent=mean*normwt;
248   wgt_var=stderr*stderr*normwt*normwt; 
249   proc print data=tmp noobs;
250 run;
251
252***** TMP1 *******************************************************************;
253* SUM CROSS-PRODUCTS WITHIN CROSS VARS TO GET AGE-ADJUSTED RATES              ;
254******************************************************************************;
255 title2 'TMP1: age-adjusted, sum of n and weighted percentages and variances';
256 proc summary data=tmp ;
257   var n wgt_percent wgt_var;
258   class  %cross1% %cross2% &varname.;
259   output out=tmp1 sum(n wgt_percent wgt_var)=;
260   run;   
261   proc print data=tmp1 noobs; run;
262   
263***** RATE *******************************************************************;
264* CALCULATE ASYMMETRIC CONFIDENCE INTERVALS                                   ;
265******************************************************************************;
266 title2 'RATE: RATES COMPUTED';
267 data rate;
268   set tmp1;
269
270   stderr=sqrt(wgt_var);
271   f=log(wgt_percent)-log(1-wgt_percent); 
272   s=stderr/(wgt_percent*(1-wgt_percent));
273   Lf=f-1.96*s; 
274   Uf=f+1.96*s; 
275
276   lower=exp(Lf)/(1+exp(Lf));   
277   upper=exp(Uf)/(1+exp(Uf));
278        if %cross1%=. then delete;
279        else if %cross1%='' then delete;
280        ?cross2? if %cross2%=. then delete;
281        ?cross2? else if %cross2%='' then delete;
282    drop f s Lf Uf wgt_var;
283 run;
284 
285  proc sort data=rate;
286   by %cross1%
287   ?cross2? %cross2%
288   &varname.;
289   run;
290
291 proc print data=rate noobs; run;
292
293***** SAMPLEN ****************************************************************;
294* GENERATE UNWEIGHTED SAMPLEN FOR CROSS1, CROSS2 for cell suppression below   ;
295******************************************************************************;
296 title2 'SAMPLEN: the n from all the varname totals';
297 proc summary data=tmpall nway;
298   var N;
299   class %cross1% %cross2%;
300   output out=sampleN sum(N)=sampleN;
301   run;
302 proc sort data=sampleN;
303   by %cross1% 
304   ?cross2? %cross2%
305   ;
306
307   proc print data=sampleN noobs; run;
308
309 title2 'TMP2: SAMPLEN MERGED INTO TMP1 DATA';
310 data tmp2;
311   merge rate sampleN;
312   by %cross1% 
313   ?cross2? %cross2%
314   ;
315   drop _TYPE_ _FREQ_ ;
316   run;
317   proc print data=tmp2 noobs; run;
318
319*****************************************************************;
320********WGTCOUNTS: Add wgtsum field to every record *************;
321***********Used by Hawaii, they want pop num, not samplen********;
322*****************************************************************;
323proc summary data=tmpall nway;  /*need to do proc summary across all AA age groups to get weighted counts*/
324  var Sum;
325  class %cross1%
326  ?cross2? %cross2%
327  &varname.
328  ;
329  output out=wgtcounts sum(Sum)=;
330  proc sort data=wgtcounts; by %cross1%
331  ?cross2? %cross2% &varname.
332  ;
333  proc print; title2 'wgtcounts';
334  run;
335data tmp4; *Add weighted counts field to each record;
336  merge wgtcounts tmp2 ;
337  by %cross1%
338  ?cross2? %cross2%
339  &varname.
340  ;
341  drop _TYPE_ _FREQ_ ;
342  proc print; title2 'tmp4: Add weighted sample field to every record';
343run;
344
345proc summary data=wgtcounts nway;  /*need to do proc summary across all values of indicator to get weighted denominators*/
346        var sum;
347        class %cross1%
348  ?cross2? %cross2%
349  ;
350  output out=weightedN sum(Sum)=wgtsum;
351  proc print; title2 'weightedN';
352  run;
353  proc sort data=weightedN;
354        by %cross1%
355        ?cross2? %cross2%
356        ;
357        run;
358data tmp6; *Add wgtsum field to each record;
359  merge tmp4 weightedN ;
360  by %cross1%
361  ?cross2? %cross2%
362  ;
363  drop _TYPE_ _FREQ_ ;
364  proc print; title2 'tmp6: Add weighted sample denominator to every record';
365run;
366
367**************************************************************************;
368* redflag is the statistical stability indicator, based on                ;
369* the relative standard error (RSE, or coefficient of  variation.         ;
370* recode total rows  to . (char and num) fore ibisq                       ;
371**************************************************************************;
372data rse;
373   set tmp6;
374   
375  if 0<wgt_percent<.50 then RSE=(StdErr/wgt_percent);
376  if .50<=wgt_percent<1 then RSE=(StdErr/(1-wgt_percent));
377 
378  /* %%% Need value attribute in DB for Stable, use VALUE_ATTRIBUTE_NAME value here */
379  redflag=put('BRFSSStable', $14.);
380 /**********************************************************************************************************
381  * Not sure we are using this, just commenting out, and keeping it here;
382  *   If we do use this we will have to change logic way below where we Convert values for cell suppression;
383  *if rse>.3 then redflag=put('Unstable', $14.);
384  *if rse>.5 then redflag=put('VeryUnstable', $14.);
385  ***********************************************************************************************************/
386  /* may want to comment this out at some future date */
387  /* %%% Need value attribute in DB for No Variance, use VALUE_ATTRIBUTE_NAME value here */
388  if wgt_percent in (0 1) then redflag=put('No Variance', $14.);
389 
390        if %cross1%=-1 then %cross1%=.;
391        else if %cross1%='tot' then %cross1%='.';
392        ?cross2? if %cross2%=-1 then %cross2%=.;
393        ?cross2? else if %cross2%='tot' then %cross2%='.';
394       
395  /* Since these are esimates HI wants to round to 100's and sum is weighted numerator */
396 
397   finalsum=ROUND(sum,100);
398   
399   /* had this as  If 0<sum<50 then finalsum=50;, but in reading emails from around 3/18/2019
400    Katherine want this to be if weighted count is less than 50 show 50, because even if no one
401        responded yes to th e particular indicator question, that does not mean no one in population, just sample
402  */
403    If sum<50 then finalsum=50;
404   
405   wgtsum=ROUND(wgtsum,100);
406   ageadj_percent=100*wgt_percent;
407   lower=100*lower;
408   upper=100*upper;
409
410   run;
411
412   proc sort data=rate;
413   by %cross1%
414   ?cross2? %cross2%
415   ;
416   run;
417   proc print data=rse noobs; title2 'RSE: RSE computed, totals set to dot'; run;
418
419 ***** Hawaii Small Numbers Rule ************************************;
420 * This is where the cell suppression takes place - will update once ;
421 * Hawaii provides their criteria                                    ;
422 * Suppress cells if unweighted samplesize (SampleN) is less than 50 ;
423 * ZW’s program uses ".A" to identify cells for suppression I have   ;
424 * co-opted his method so I can use the NM/now HI logic for cell     ;
425 * suppression instead of the standard IBIS logic. And I need to use ;
426 * ZWs program because it will suppress the table marginals that can ;
427 * be used to calculate the suppressed cells. Needs                  ;
428 * suppressed_variables code at the end of this file to work.        ;
429 ********************************************************************;
430 title2 'TMP: rate with cell suppression';
431 data tmp;
432        set rse;
433        if &varname = '%spvar2%'; /*This is the value for the indicator dimension passed in by the URL.;*/
434        if (0<SampleN<50) OR  (rse >.3) then do;        /* Hawaii cell supression Rule */
435                ageadj_percent = .A;    * Age-adjustedpercent who answered yes or no;
436                lower = .A;                             * lower confidence interval;
437                upper = .A;                             * upper confidence interval;
438                finalsum = .A;                  * pop estimated weighted numerator;
439                wgtsum = .A;                    * pop estimated weighted denominator;
440  /* %%% Need value attribute in DB for Not Reportable, use VALUE_ATTRIBUTE_NAME value here */
441                redflag=put('Not Reportable', $14.);
442        end;
443        proc print data=tmp noobs;  title2 'final tmp'; run;
444
445%mend;
Note: See TracBrowser for help on using the repository browser.