Friday, November 21, 2014

Avoid the error of "no statistic associated with XXX." in PROC REPORT

One can avoid this error by putting a dummy analysis variable on the end of the COLUMN statement.  For example:

proc report data=test headline headskip split='~' nowd spanrows;
      column n vargrp trt, (timer, (statc)) dummy;
      define n /group noprint;
      define vargrp /group order=internal style(column)={cellwidth=1.2in} left ' ' id;
      define trt /across order=internal style(column)={cellwidth=0.6in} center ' ' ;
      define timer /across order=internal style(column)={cellwidth=0.6in} center ' ' ;
      define statc /display style(header column)={cellwidth=0.6in} center ' ';
      define dummy /computed noprint;
run;

Monday, July 21, 2014

Use SAS to score SF-36

Click Here
The following codes are copied from the above link.

options ls=132 ps=53 nocenter;

*****************************************************************;
* SF36V2-4_PUBLIC.SAS
* SAS CODE FOR SCORING 36-ITEM HEALTH SURVEY VERSION 2.0
* STANDARD FORM (NOT ACUTE!);
* WRITTEN BY K. SPRITZER, 9/29/2003
*
* MODIFIED: 2/14/2006 TO ADD AGE/GENDER ADJUSTMENT AND ADD PCS AND MCS
  SCORES.
  ALSO REQUIRED MODIFICATION OF AGE GROUPINGS: V1 HAD 18-24, 25-34,
  35-44, 45-54, 55-64, 65+ WHEREAS V2 BREAKS 65+ INTO 65-74 AND 75+.
  
* MODIFIED: 2/27/2007 TO USE SEPI FARIVAR WEIGHTS.  SEE COMMENTS
  FOR REFERENCE.
  ALSO SOME RESTRUCTURING OF CODE.  
  
* EVERY EFFORT IS MADE TO TEST CODE AS THOROUGHLY AS POSSIBLE BUT
  USER MUST ACCEPT RESPONSIBILITY FOR USE.
  PLEASE REPORT ANY CONCERNS OR PROBLEMS WITH THE CODE TO 
  K. SPRITZER AT KSPRITZER@MEDNET.UCLA.EDU - THANKS.             ;
*****************************************************************;

/* INPUT A FEW DUMMY TEST CASES */
/* INCLUDES SOME OUT OF RANGE DATA */

DATA TEMP1;
INPUT
I1 I2 I3A I3B I3C I3D I3E I3F I3G I3H I3I I3J 
I4A I4B I4C I4D I5A I5B I5C I6 I7 I8 
I9A I9B I9C I9D I9E I9F I9G I9H I9I I10
I11A I11B I11C I11D AGE MALE;
CARDS;
4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 42 1
2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 33 1
3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 25 0
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 45 0
4 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 19 0
2 1 1 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 67 1
1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 1 1 1 2 1 1 1 1 1 1 1 1 2 2 2 1 1 2 1 1 1  . 1
1 1 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 1 1 1 1 5 5 1 1 5 5 1 5 5 5 1 5 1 77 1
1 1 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 1 1 1 1 6 6 1 1 6 6 1 6 5 5 1 5 1 56 0
5 5 1 1 1 . . . . . . . 1 1 1 1 1 1 1 5 6 5 6 1 1 6 6 1 1 6 1 1 . . . 5 48 1
;
RUN;



DATA TEMP1; SET TEMP1;
/** RENAME ITEMS TO CONFORM TO SURVEY **/
RENAME
I1   = I1
I2   = I2
I3A  = I3
I3B  = I4
I3C  = I5
I3D  = I6
I3E  = I7
I3F  = I8
I3G  = I9
I3H  = I10
I3I  = I11
I3J  = I12
I4A  = I13
I4B  = I14
I4C  = I15
I4D  = I16
I5A  = I17
I5B  = I18
I5C  = I19
I6   = I20
I7   = I21
I8   = I22
I9A  = I23
I9B  = I24
I9C  = I25
I9D  = I26
I9E  = I27
I9F  = I28
I9G  = I29
I9H  = I30
I9I  = I31
I10  = I32
I11A = I33
I11B = I34
I11C = I35
I11D = I36 ;
RUN;
*********************************************************;
DATA TEMP1; SET TEMP1;
*********************************************************;
** CODE OUT-OF-RANGE VALUES TO MISSING;
*********************************************************;
ARRAY PT3 I3-I12;
DO OVER PT3;
IF PT3 NOT IN (1,2,3) THEN PT3=.;
END;

ARRAY PT5 I1 I2 I13-I20 I22-I36;
DO OVER PT5;
IF PT5 NOT IN (1,2,3,4,5) THEN PT5=.;
END;

IF I21 NOT IN (1,2,3,4,5,6) THEN I21=.;
RUN;
*********************************************************;

*********************************************************;
DATA TEMP1; SET TEMP1;
* KEEP AS IS: I3-I19, I24, I25, I28, I29, I31, I32, I33, I35;
*********************************************************;
* RAND versions of items;
RAND21=I21;
RAND22=I22;
RAND1=I1;
***************************************************************************;
** WHEN NECESSARY, REVERSE CODE ITEMS SO A HIGHER SCORE MEANS BETTER HEALTH;
***************************************************************************;
IF I21=1 THEN RI21=6.0; ELSE
IF I21=2 THEN RI21=5.4; ELSE
IF I21=3 THEN RI21=4.2; ELSE
IF I21=4 THEN RI21=3.1; ELSE
IF I21=5 THEN RI21=2.2; ELSE
IF I21=6 THEN RI21=1.0; 

IF I21>. THEN DO;
IF I22=1 & I21 =1 THEN RI22=6; ELSE
IF I22=1 & I21>=2 THEN RI22=5; ELSE
IF I22=2 & I21>=1 THEN RI22=4; ELSE
IF I22=3 & I21>=1 THEN RI22=3; ELSE
IF I22=4 & I21>=1 THEN RI22=2; ELSE
IF I22=5 & I21>=1 THEN RI22=1;
END;
ELSE IF I21=. THEN DO;
IF I22=1 THEN RI22=6.0 ; ELSE
IF I22=2 THEN RI22=4.75; ELSE
IF I22=3 THEN RI22=3.5 ; ELSE
IF I22=4 THEN RI22=2.25; ELSE
IF I22=5 THEN RI22=1.0 ; 
END;

IF I1=1 THEN RI1=5.0; ELSE
IF I1=2 THEN RI1=4.4; ELSE
IF I1=3 THEN RI1=3.4; ELSE
IF I1=4 THEN RI1=2.0; ELSE
IF I1=5 THEN RI1=1.0; 

ARRAY CAT5   I2  I20  I23  I26  I27  I30  I34  I36 ;
ARRAY RCAT5  RI2 RI20 RI23 RI26 RI27 RI30 RI34 RI36;
DO OVER CAT5;
IF CAT5=1 THEN RCAT5=5; ELSE
IF CAT5=2 THEN RCAT5=4; ELSE
IF CAT5=3 THEN RCAT5=3; ELSE
IF CAT5=4 THEN RCAT5=2; ELSE
IF CAT5=5 THEN RCAT5=1;
END;

IF RAND21=1 THEN RRAND21=6; ELSE 
IF RAND21=2 THEN RRAND21=5; ELSE 
IF RAND21=3 THEN RRAND21=4; ELSE 
IF RAND21=4 THEN RRAND21=3; ELSE 
IF RAND21=5 THEN RRAND21=2; ELSE 
IF RAND21=6 THEN RRAND21=1;

IF RAND22=1 THEN RRAND22=5; ELSE 
IF RAND22=2 THEN RRAND22=4; ELSE 
IF RAND22=3 THEN RRAND22=3; ELSE 
IF RAND22=4 THEN RRAND22=2; ELSE 
IF RAND22=5 THEN RRAND22=1;  

IF RAND1=1 THEN RRAND1=5; ELSE 
IF RAND1=2 THEN RRAND1=4; ELSE 
IF RAND1=3 THEN RRAND1=3; ELSE 
IF RAND1=4 THEN RRAND1=2; ELSE 
IF RAND1=5 THEN RRAND1=1;  

*****************************************************************;
** RE-CODE ITEMS TO 0-100;
*****************************************************************;
ARRAY FIVEPT RI1 RI2 I13-I16 
      I17-I19 
      RI20  
      RI23 I24 I25 RI26 RI27 I28 I29 RI30 I31 
      I32 
      I33 RI34 I35 RI36
      RRAND1 RRAND22;

ARRAY SIXPT RI21 RI22
            RRAND21;

ARRAY THREEPT I3-I12;
          
DO OVER FIVEPT;
FIVEPT=(FIVEPT-1)*25;
END;

DO OVER SIXPT;
SIXPT=(SIXPT-1)*20;
END;

DO OVER THREEPT;
THREEPT=(THREEPT-1)*50;
END;          

** CREATE SCALES;

PHYFUN10=MEAN(I3,I4,I5,I6,I7,I8,I9,I10,I11,I12);
ROLEP4=MEAN(I13,I14,I15,I16);
SFPAIN2=MEAN(RI21,RI22);
SFGENH5=MEAN(RI1,I33,RI34,I35,RI36);
ENFAT4=MEAN(RI23,RI27,I29,I31);
SOCFUN2=MEAN(RI20,I32);
ROLEE3=MEAN(I17,I18,I19);
EMOT5=MEAN(I24,I25,RI26,I28,RI30);

PAIN2=MEAN(RRAND21,RRAND22);
GENH5=MEAN(RRAND1,I33,RI34,I35,RI36);

label phyfun10="Physical functioning scale";
label rolep4="Physical health problems scale";
label sfpain2="SF-36 pain scale";
label sfgenh5="SF-36 general health perceptions scale";
label enfat4="Energy/fatigue scale";
label socfun2="Social functioning scale";
label rolee3="Emotional health problems scale";
label emot5="Emotional well-being scale";

label pain2="Pain scale (RAND)";
label genh5="General health perceptions scale (RAND)";


** APPLY OPTION THAT REQUIRES AT LEAST HALF OF ITEMS IN A SCALE TO BE PRESENT 
   IN ORDER THAT THE SCALE BE NON-MISSING;
** NEED AT LEAST HALF (OR HALF + 1 FOR SCALES WITH ODD # OF ITEMS) OF ITEMS PRESENT, 
   ELSE SET SCALE TO MISSING;

/* UNCOMMENT THIS SECTION IF YOU WANT TO USE THE OPTION */
/*
IF N(OF I3,I4,I5,I6,I7,I8,I9,I10,I11,I12) <=4 THEN PHYFUN10=.;
IF N(OF I13,I14,I15,I16)                  <=1 THEN ROLEP4  =.;
* IF N(OF RI21,RI22)                      <=0 THEN SFPAIN2 =.;
IF N(OF RI1,I33,RI34,I35,RI36)            <=2 THEN SFGENH5 =.;
IF N(OF RI23,RI27,I29,I31)                <=1 THEN ENFAT4  =.;
* IF N(OF RI20,I32)                       <=0 THEN SOCFUN2 =.;
IF N(OF I17,I18,I19)                      <=1 THEN ROLEE3  =.;
IF N(OF I24,I25,RI26,I28,RI30)            <=2 THEN EMOT5   =.;

* IF N(OF RRAND21,RRAND22)                <=0 THEN PAIN2 =.;
IF N(OF RRAND1,I33,RI34,I35,RI36)         <=2 THEN GENH5 =.;
*/



*****************************************************************;
*** NEMC PHYSICAL AND MENTAL HEALTH COMPOSITE - SF36 ************;
*****************************************************************;

*** 1) Transform SF-36 scores (NEMC Scoring) to z-scores; ******* ;
***    1998 US general population means and SDs are used here ** ;
***    (not age/gender based) *********************************** ;

   PF_Z = (PHYFUN10 - 83.29094) / 23.75883 ;
   RP_Z = (ROLEP4   - 82.50964) / 25.52028 ;
   BP_Z = (SFPAIN2  - 71.32527) / 23.66224 ;
   GH_Z = (SFGENH5  - 70.84570) / 20.97821 ;
   EM_Z = (EMOT5    - 74.98685) / 17.75604 ;
   RE_Z = (ROLEE3   - 87.39733) / 21.43778 ;
   SF_Z = (SOCFUN2  - 84.30250) / 22.91921 ;
   EN_Z = (ENFAT4   - 58.31411) / 20.01923 ;

   label pf_Z="NEMC physical functioning Z-score";
   label rp_Z="NEMC role limitation physical Z-score";
   label bp_Z="NEMC pain Z-score";
   label gh_Z="NEMC general health Z-score";
   label em_Z="NEMC emotional well-being Z-score";
   label re_Z="NEMC role limitation emotional Z-score";
   label sf_Z="NEMC social functioning Z-score";
   label en_Z="NEMC energy/fatigue Z-score";
   

*** 2) Create physical and mental health composite scores: **********;
***    Multiply z-scores by varimax-rotated factor scoring **********;
***    coefficients and sum the products ****************************;

*** NOTE: Aggregates are missing if any subscale score is missing - Qualitymetric has
    a missing data estimator (MDE) product that will allow scoring of aggregates
    when 1 or more subscales are missing.
    See: http://www.qualitymetric.com/products/SFScoring/ScoringMDE.aspx for 
    more information. 
    ;


   AGG_PHYS = (PF_Z * 0.42402) + (RP_Z * 0.35119) + (BP_Z * 0.31754) +
              (GH_Z * 0.24954) + (EM_Z * -.22069) + (RE_Z * -.19206) +
              (SF_Z * -.00753) + (EN_Z * 0.02877);
              
   AGG_MENT = (PF_Z * -.22999) + (RP_Z * -.12329) + (BP_Z * -.09731) +
              (GH_Z * -.01571) + (EM_Z * 0.48581) + (RE_Z * 0.43407) +
              (SF_Z * 0.26876) + (EN_Z * 0.23534);

   label agg_phys="NEMC physical health - SF36 (raw)";
   label agg_ment="NEMC mental health - SF36 (raw)";


*** 3) Transform composite and scale scores to T-scores: ****** ;

   AGG_PHYS_T = 50 + (AGG_PHYS * 10);
   AGG_MENT_T = 50 + (AGG_MENT * 10);

   label agg_phys_t="NEMC physical health T-score - SF36";
   label agg_ment_t="NEMC mental health T-score - SF36";
   PF_T = 50 + (PF_Z * 10) ;
   RP_T = 50 + (RP_Z * 10) ;
   BP_T = 50 + (BP_Z * 10) ;
   GH_T = 50 + (GH_Z * 10) ;
   EM_T = 50 + (EM_Z * 10) ;
   RE_T = 50 + (RE_Z * 10) ;
   SF_T = 50 + (SF_Z * 10) ;
   EN_T = 50 + (EN_Z * 10) ;

   label pf_t="NEMC physical functioning T-score";
   label rp_t="NEMC role limitation physical T-score";
   label bp_t="NEMC pain T-score";
   label gh_t="NEMC general health T-score";
   label em_t="NEMC emotional well-being T-score";
   label re_t="NEMC role limitation emotional T-score";
   label sf_t="NEMC social functioning T-score";
   label en_t="NEMC energy/fatigue T-score";




*****************************************************************;
*** PHYSICAL and MENTAL HEALTH FACTORS **************************;
*****************************************************************;

*** 1) Derive z-scores using age/gender adjusted US general *****;
***    population means and SDs, then multiply each z-score by *;
***    oblique factor scoring coefficient and sum the products **;

*** Feb 2007: oblique factor scoring coeffs come from:

**  Farivar, S. S., Cunningham, W. E., & Hays, R. D. (in press).
    Correlated physical and mental health summary scores for the
    SF-36 and SF-12 Health Survey, V.1., Journal of Health and
    Quality of Life Outcomes.
;

  FFM1=   0.19868 * (PHYFUN10 - 79.9348918)/ 22.709038+
          0.31059 * (ROLEP4   - 76.2860947)/ 34.945958+
          0.22602 * (SFPAIN2  - 72.6616442)/ 23.807217+
          0.19548 * (SFGENH5  - 69.3384676)/ 20.141323+
         -0.03009 * (EMOT5    - 74.6684030)/ 18.209059+
          0.02738 * (ROLEE3   - 79.9677043)/ 34.229373+
          0.10511 * (SOCFUN2  - 82.1785891)/ 23.568127+
          0.13093 * (ENFAT4   - 59.5636224)/ 21.334831;

  FFM2=  -0.01520 * (PHYFUN10 - 79.9348918)/ 22.709038+ 
          0.03496 * (ROLEP4   - 76.2860947)/ 34.945958+
          0.04327 * (SFPAIN2  - 72.6616442)/ 23.807217+
          0.10379 * (SFGENH5  - 69.3384676)/ 20.141323+
          0.35362 * (EMOT5    - 74.6684030)/ 18.209059+
          0.19588 * (ROLEE3   - 79.9677043)/ 34.229373+
          0.13950 * (SOCFUN2  - 82.1785891)/ 23.568127+
          0.28769 * (ENFAT4   - 59.5636224)/ 21.334831 ;

label ffm1 = "Physical health factor score";
label ffm2 = "Mental health factor score";


*** 2) Transform composite scores to t-scores *******************;

  FSFM1 = (FFM1 * 10) +50;
  FSFM2 = (FFM2 * 10) +50;

  label fsfm1="Physical health factor T-score";
  label fsfm2="Mental health factor T-score";

run;

*****************************************************************;
TITLE1 "SF36 V2 (all cases)";
PROC MEANS data=TEMP1; 
VAR phyfun10 rolep4 sfpain2 pain2 sfgenh5 genh5 emot5 rolee3 socfun2 enfat4 agg_phys agg_ment
pf_t rp_t bp_t gh_t em_t re_t sf_t en_t AGG_PHYS_T AGG_MENT_T
ffm1 ffm2 fsfm1 fsfm2;
run;
*****************************************************************;
TITLE1 "SF36 V2 (cases with non-missing age and gender)";
PROC MEANS data=TEMP1; where age > . & male > .; 
VAR phyfun10 rolep4 sfpain2 pain2 sfgenh5 genh5 emot5 rolee3 socfun2 enfat4 agg_phys agg_ment
pf_t rp_t bp_t gh_t em_t re_t sf_t en_t AGG_PHYS_T AGG_MENT_T
ffm1 ffm2 fsfm1 fsfm2;
run;
*****************************************************************;


Click Here too

Tuesday, June 17, 2014

Computing Geometric Means

This sample is from the SAS Sample Library. For additional information refer to SAS Help and Online Documentation.

 /****************************************************************/
 /*          S A S   S A M P L E   L I B R A R Y                 */
 /*                                                              */
 /*    NAME: GEOMEAN                                             */
 /*   TITLE: Computing Geometric Means                           */
 /* PRODUCT: SAS                                                 */
 /*  SYSTEM: ALL                                                 */
 /*    KEYS: DATASTEP ARRAY MEANS DO FUNCTIONS LOG EXP PRINT     */
 /*   PROCS: MEANS PRINT                                         */
 /*    DATA:                                                     */
 /*                                                              */
 /* SUPPORT:                             UPDATE:                 */
 /*     REF:                                                     */
 /*    MISC:                                                     */
 /*                                                              */
 /****************************************************************/


OPTIONS LS=72;
TITLE 'GEOMETRIC MEANS';

DATA; 
   INPUT X Y Z@@; 
CARDS;
2 3 1 2 5 6 4 3 2 1 2 3 45 68 6 5 4 3 2 2 1
2 3 2 2 1  3 -46 7 765 4 33 2 2 32 3  5 5 3 2 25 4 32 23
4 3 2 32 32 23 4 4 -55 2 23 1 1 22 32 32
;
RUN;

DATA LOGS; 
   SET;
   ARRAY L (3) X Y Z;
   DO I=1 TO 3;
     IF L(I)>0 THEN L(I)=LOG(L(I));
             ELSE L(I)=.;
   END;
RUN;

PROC MEANS;
   VAR X Y Z;
   OUTPUT OUT=MEANLOGS MEAN=X1 Y1 Z1;
RUN;

DATA GEOMEAN; 
   SET MEANLOGS;
   ARRAY MLOG(3) X1 Y1 Z1;
   DO I=1 TO 3;
     MLOG(I)=EXP(MLOG(I));
   END;
RUN;

PROC PRINT;
RUN;
 
Also See Geometric Statistics in PK Analysis 
Geometric Statistics, geometric CV 

Tuesday, June 3, 2014

Send Emails from SAS

For Video Click Here

For Article Click Here and Here



Change SAS email options and use SMTP email.  Refer to:
    Usage Note 19767: Using the SAS® System to send SMTP e-mail

For troubleshooting refer to:
    Usage Note 18363: Troubleshooting guidelines for successfully sending an SMTP e-mail from SAS® software
 

Friday, March 28, 2014

A Couple of Proc Template for Report

proc template;
  define style timesrtf;
  parent=styles.journal;
  replace fonts /
     'BatchFixedFont' = ('Times',9pt)
     'TitleFont' = ('Times',12pt)
     'TitleFont2' = ('Times',9pt)
     'FootFont' = ('Times',9pt,Italic)
     'StrongFont' = ('Times',9pt,Bold)
     'EmphasisFont' = ('Times',9pt)
     'FixedEmphasisFont' = (Times,9pt)
     'FixedStrongFont' = (Times,9pt,Bold)
     'FixedHeadingFont' = (Times,9pt)
     'FixedFont' = (Times,9pt)
     'headingEmphasisFont' = ('Times',9pt)
     'headingFont' = ('Times',9pt)
     'docFont' = ('Times',9pt);
  style table from output /
      cellpadding = 2pt
      background=white
      rules=groups
      frame=void;
  style body from document /
      leftmargin=1in
      rightmargin=1in
      topmargin=1in
      bottommargin=0.5in;
  replace color_list  /
     'bgH' = white
     'fg' = black
     'bg' = white;
 end;
run;

proc template;
  define style mystyle;
  parent=styles.printer;
  replace fonts /
     'BatchFixedFont' = ('Courier',8pt)
     'TitleFont2' = ('Courier',9pt,Bold)
     'TitleFont' = ('Courier',9pt,Bold)
     'StrongFont' = ('courier',8pt,Bold)
     'EmphasisFont' = ('Courier',8pt)
     'FixedEmphasisFont' = (Courier,8pt)
     'FixedStrongFont' = (Courier,8pt,Bold)
     'FixedHeadingFont' = (Courier,8pt)
     'FixedFont' = (Courier,8pt)
     'headingEmphasisFont' = ('Courier',8pt)
     'headingFont' = ('Courier',8pt)
     'docFont' = ('Courier',8pt);
  style table from output /
      cellpadding = 1pt
      background=white
      rules=groups
      frame=void;
*      rules=all/*rows*//*groups*/
*     frame=hsides/*box*/;
  style body from document /
      leftmargin=0.36in
      rightmargin=0.25in
      topmargin=0.60in
      bottommargin=0.36in;
  replace color_list  /
     'link' = black
     'bgH' = white
     'fg' = black
     'bg' = white;
 end;
run;