SASUnit Examples  Version 1.5.0
boxplot.sas
Go to the documentation of this file.
1 
37 %MACRO boxplot(
38  data =
39  ,x =
40  ,y =
41  ,group =
42  ,report =
43 );
44 
45 %local dsid grouptype xvalues xvalues2;
46 
47 /*-- check input data set ----------------------------------------------------*/
48 %let dsid=%sysfunc(open(&data));
49 %if &dsid=0 %then %do;
50  %put ERROR: boxplot: Data set &data does not exist;
51  %return;
52 %end;
53 /*-- check whether x variable has been specified -----------------------------*/
54 %if "&x"="" %then %do;
55  %put ERROR: boxplot: X variable not specified;
56  %let dsid=%sysfunc(close(&dsid));
57  %return;
58 %end;
59 /*-- check for existence of x variable ---------------------------------------*/
60 %if %sysfunc(varnum(&dsid,&x))=0 %then %do;
61  %put ERROR: boxplot: Variable &x does not exist in data set &data ;
62  %let dsid=%sysfunc(close(&dsid));
63  %return;
64 %end;
65 
66 /*-- check whether x variable is numeric -------------------------------------*/
67 %if %sysfunc(vartype(&dsid,%sysfunc(varnum(&dsid,&x)))) NE N %then %do;
68  %put ERROR: boxplot: Variable &x in data set &data must be numeric;
69  %let dsid=%sysfunc(close(&dsid));
70  %return;
71 %end;
72 /*-- determine values of x variable for axis ---------------------------------*/
73 proc sql noprint;
74  select distinct &x into :xvalues separated by '" "' from &data;
75  select distinct &x into :xvalues2 separated by ' ' from &data;
76 quit;
77 /*-- check whether y variable has been specified -----------------------------*/
78 %if "&y"="" %then %do;
79  %put ERROR: boxplot: Y variable not specified;
80  %let dsid=%sysfunc(close(&dsid));
81  %return;
82 %end;
83 /*-- check for existence of y variable ---------------------------------------*/
84 %if %sysfunc(varnum(&dsid,&y))=0 %then %do;
85  %put ERROR: boxplot: Variable &y does not exist in data set &data ;
86  %let dsid=%sysfunc(close(&dsid));
87  %return;
88 %end;
89 /*-- check wheter y variable ist numeric -------------------------------------*/
90 %if %sysfunc(vartype(&dsid,%sysfunc(varnum(&dsid,&y)))) NE N %then %do;
91  %put ERROR: boxplot: Variable &y in data set &data must be numeric;
92  %let dsid=%sysfunc(close(&dsid));
93  %return;
94 %end;
95 /*-- check whether group variable has been specified -------------------------*/
96 %if "&group"="" %then %do;
97  %put ERROR: boxplot: Group variable must be specified;
98  %let dsid=%sysfunc(close(&dsid));
99  %return;
100 %end;
101 /*-- check for existence of group variable -----------------------------------*/
102 %if %sysfunc(varnum(&dsid,&group))=0 %then %do;
103  %put ERROR: boxplot: Variable &group does not exist in data set &data ;
104  %let dsid=%sysfunc(close(&dsid));
105  %return;
106 %end;
107 /*-- check for number of groups and determine variable type and group sequence -*/
108 %let grouptype=%sysfunc(vartype(&dsid,%sysfunc(varnum(&dsid,&group))));
109 %local count lower;
110 proc sql noprint;
111  select count(distinct &group) into :count from &data;
112  select min(&group) into :lower from &data;
113 quit;
114 %if &lower=. %then %do;
115  %put ERROR: boxplot: Missing values in group variable are not allowed;
116  %return;
117  %*** This is code not covered by any test case and left intentionally here to ***;
118  %*** demonstrate the functionality of the test coverage ***;
119  proc sql noprint; drop table &d_1; quit;
120 %end;
121 %if &count NE 2 %then %do;
122  %put ERROR: boxplot: Variable &group must have exactly two values;
123  %return;
124 %end;
125 
126 %let dsid=%sysfunc(close(&dsid));
127 
128 /*-- calculate distance between the x values ---------------------------------*/
129 %local d_1;
130 DATA; RUN;
131 %let d_1=&syslast;
132 
133 proc sql noprint;
134  create table &d_1 as select distinct &x from &data;
135 quit;
136 
137 data &d_1;
138  set &d_1;
139  &x = &x - lag(&x);
140  if _n_>1 then output;
141 run;
142 
143 %local xdiff1 xdiff2 xmin xmax misscount;
144 proc sql noprint;
145  select mean(&x), min(&x) into :xdiff1, :xdiff2 from &d_1;
146  select min(&x), max(&x) into :xmin, :xmax from &data;
147 %let misscount=0;
148  select count(*) into :misscount from &data where &x is missing;
149 quit;
150 %if &xdiff1=. %then %do;
151  %put ERROR: boxplot: x variable must have at least two values;
152  proc sql noprint; drop table &d_1; quit;
153  %return;
154 %end;
155 %if &misscount>0 %then %do;
156  %put ERROR: boxplot: Missing values in x variable are not allowed;
157  proc sql noprint; drop table &d_1; quit;
158  %return;
159 %end;
160 
161 %let xmin=%sysevalf(&xmin-&xdiff1);
162 %let xmax=%sysevalf(&xmax+&xdiff1);
163 
164 run;
165 %if &xdiff1 ne &xdiff2 %then %do;
166  %put ERROR: boxplot: Values of x variable are not equidistant;
167  proc sql noprint; drop table &d_1; quit;
168  %return;
169 %end;
170 
171 /*-- calculate offset between the plots of the two groups --------------------*/
172 %local d_plot;
173 data;
174  SET &data (KEEP=&x &y &group);
175  IF &group = %if &grouptype=N %then &lower; %else "&lower"; THEN DO;
176  &x = &x - 0.11*&xdiff1;
177  END;
178  ELSE DO;
179  &x = &x + 0.11*&xdiff1;
180  END;
181 RUN;
182 %let d_plot=&syslast;
183 
184 /*-- create chart ------------------------------------------------------------*/
185 GOPTIONS FTEXT="Helvetica" HTEXT=12pt hsize=16cm vsize=16cm;
186 SYMBOL1 WIDTH = 3 BWIDTH = 3 COLOR = gray LINE = 2 VALUE = none INTERPOL = BOXJT00 MODE = include;
187 SYMBOL2 WIDTH = 3 BWIDTH = 3 COLOR = black LINE = 1 VALUE = none INTERPOL = BOXJT00 MODE = include;
188 AXIS1 LABEL=(ANGLE=90) MINOR=none;
189 AXIS2 ORDER=(&xmin &xvalues2 &xmax) VALUE=(" " "&xvalues" " ") MINOR=none;
190 LEGEND1 FRAME;
191 
192 ODS PDF FILE="&report";
193 ODS LISTING CLOSE;
194 PROC GPLOT DATA=&d_plot;
195  PLOT &y * &x = &group / VAXIS=Axis1 HAXIS=Axis2 LEGEND=Legend1 NOFRAME;
196 RUN;
197 QUIT;
198 ODS PDF CLOSE;
199 ODS LISTING;
200 
201 proc sql noprint;
202  drop table &d_plot;
203  drop table &d_1;
204 quit;
205 
206 %MEND boxplot;