width=cellwid-2*dist;
xstart=int((90 -cellwid * nv)/2) + 5; xgrid=((0:nv-1)#cellwid + xstart)`;
/*-- |
Delineate cells |
--*/ |
|
|
|
cell1=xgrid; |
|
|
|
|
cell1=cell1||(cell1[nv]//cell1[nv-(0:nv-2)]); |
|
|
|
cell2=j(nv, 1, xstart); |
|
|
|
cell2=cell1[,1]||cell2; |
|
|
|
call |
gdrawl(cell1, cell2); |
|
|
|
call gdrawl(cell1[,{2 1}], cell2[,{2 1}]); |
|
|
|
xstart = xstart |
+ dist; ystart = xgrid[nv] + dist; |
|
/*-- |
Label |
variables |
---*/ |
|
|
|
call |
gset("height", 3); |
|
|
|
call |
gset("font","swiss"); |
|
|
|
call gstrlen(len, vname); |
|
|
|
where=xgrid[1:nv] + (cellwid-len)/2; |
|
|
|
call gscript(where, 0, vname) ; |
|
|
|
len=len[nv-(0:nv-1)]; |
|
|
|
where=xgrid[1:nv] + (cellwid-len)/2; |
|
|
|
call gscript(0,where, vname[nv - (0:nv-1)]); |
|
/*-- |
First |
viewport --*/ |
|
|
|
vp=(xstart || ystart)//((xstart || ystart) + width) ; |
|
/* |
|
Since the characters are scaled to the viewport |
*/ |
/* |
|
(which is inversely porportional to the |
*/ |
/* |
|
number of variables), |
*/ |
/* |
|
enlarge it proportional to the number of variables */ |
|
ht=2*nv; |
|
|
|
|
call gset("height", ht); |
|
|
do i=1 to nv; |
|
|
|
|
do j=1 to |
i; |
|
|
|
|
|
call gportstk(vp); |
|
|
|
if |
(i=j) |
then |
; |
|
|
|
|
else |
run |
gscatter(data[,j], data[,i]); |
|
/*-- onto the next viewport --*/
vp[,1] = vp[,1] + cellwid; call gportpop;
end;
vp=(xstart // xstart + width) || (vp[,2] - cellwid); end;
call gshow; finish gscatmat;
/*-- Placement of text is based on the character height. */
/* The IML modules defined here assume percent as the unit of */
/* character height for device independent control. */
goptions gunit=pct;
use &data; vname={&varlist};
read all var vname into xyz; run gscatmat(xyz, vname); quit;
goptions gunit=cell; |
/*-- reset back to default --*/ |
%mend; |
|
Appendix B
Answers to Selected Chapter Exercises
The answers given here assume that the data have been read in as described in the relevant chapter.
Chapter 2
proc univariate data=water normal plot; |
/* 2.1 |
*/ |
var mortal hardness; |
|
|
run; |
|
|
proc sort data=water; |
/* 2.2 |
*/ |
by location; |
|
|
run; |
|
|
proc boxplot data=water; |
|
|
plot (mortal hardness)*location; |
|
|
run; |
|
|
proc univariate data=water normal; |
/* 2.3 |
*/ |
var hardness; |
|
|
histogram hardness / lognormal(theta=est) exponential (theta=est);
probplot hardness / lognormal(theta=est sigma=est zeta=est);
probplot hardness / exponential (theta=est sigma=est);
run; |
|
proc univariate data=water; |
/* 2.4 */ |
var mortal hardness; |
|
histogram mortal hardness /kernel ; |
|
run; |
|
proc sort data=water; |
/* 2.5 */ |
by location; |
|
run; |
|
proc kde data=water out=bivest; |
|
var mortal hardness; |
|
by location; |
|
run; |
|
proc g3d data=bivest; |
|
plot hardness*mortal=density; |
|
by location; |
|
run; |
|
proc gplot data=water; |
/* 2.6 */ |
plot mortal*hardness=location; |
|
symbol1 v=dot i=r l=1; |
|
symbol2 v=circle i=r l=2; |
|
run; |
|
Chapter 3
data pill2; |
/* 3.1 */ |
set the_pill; |
|
use=caseuse; |
|
case='Y'; |
|
output; |
|
use=contruse; |
|
case='N'; |
|
output; |
|
run; |
|
proc freq data=pill2;
tables case*use /riskdiff; weight n;
run;
The short data step restructures the data into separate observations for cases and controls rather than case-control pairs enumerated in Display 3.4.
proc freq data=pistons order=data; |
/* 3.2 */ |
tables machine*site / out=tabout outexpect outpct; |
weight n; |
|
run; |
|
data resids; |
|
set tabout; |
|
r=(count-expected)/sqrt(expected); |
|
radj=r/sqrt((1-percent/pct_row)*(1-percent/pct_col)); |
run; |
|
proc tabulate data=resids; |
|
class machine site; |
|
var r radj; |
|
table machine, |
|
site*r; |
|
table machine, |
|
site*radj; |
|
run; |
|
data lesions2; |
/* 3.3 */ |
set lesions; |
|
region2=region; |
|
if region ne 'Gujarat' then region2='Others'; |
|
run; |
|
proc freq data=lesions2 order=data; |
|
tables site*region2 /exact; |
|
weight n; |
|
run; |
|
Chapter 4
proc reg data=uscrime; |
/* 4.1 */ |
model R= Age--Ed Ex1--X / selection=cp; run;
proc reg data=uscrime; /* 4.2 */ model R= Age Ed Ex1 U2 X / selection=cp start=1 stop=5; plot cp.*np. / cmallows=black;
run;
When selection=cp is used, the start and stop options determine the smallest and largest number of explanatory variables to be included in the model.
data uscrime; |
/* 4.5 */ |
set uscrime; |
|
age_s=age*s; |
|
run; |
|
proc reg data=uscrime; |
|
model R=age s age_s; |
|
output out=regout p=rhat; |
|
run; |
|
proc gplot data=regout; |
|
plot rhat*age=s / vaxis=axis1; |
|
plot2 r*age=s /vaxis=axis1; |
|
symbol1 i=join v=none l=1; |
|
symbol2 i=join v=none l=2; |
|
symbol3 v=dot; |
|
symbol4 v=circle; |
|
axis1 order=20 to 200 by 10; |
|
run; |
|
Because proc reg has no facility for specifying interactions in the model statement, the short data step computes a new variable age_s to be used as an interaction term.
The plot2 statement is used as a “trick” to overlay two y*x=z type plots. To ensure that the vertical axes are kept in alignment the plot and plot2 statements, both use the same vertical axis definition.
Chapter 5
proc anova data=hyper; |
/* 5.1 */ |
class diet drug biofeed; |
|
model logbp=diet drug biofeed; |
|
means drug / bon duncan; |
|
run; |
|
proc sort data=hyper; |
/* 5.2 */ |
by diet; |
|
proc boxplot data=hyper; |
|
plot logbp*diet; |
|
run; |
|
proc sort data=hyper; |
|
by drug; |
|
proc boxplot data=hyper; |
|
plot logbp*drug; |
|
run; |
|
proc sort data=hyper; |
|
by biofeed; |
|
proc boxplot data=hyper; |
|
plot logbp*biofeed; |
|
run; |
|
Chapter 6
6.1
Try using @ to restrict the expansion of the bar operator; for example,
model days=type|sex|origin|grade@3;
or
model days=type|sex|origin|grade@2;
and then specifying additional terms.
data ozkids; |
/* 6.2 */ |
set ozkids; |
|
logdays=log(days+0.5); |
|
run; |
|
Add 0.5 to allow for zeros.
proc tabulate data=ozkids f=6.2; |
/* 6.3 */ |
class type sex origin grade; |
|
var days; |
|
table sex*grade, |
|
origin*type*days*(mean std); |
|
run; |
|
proc glm data=ozkids noprint; |
/* 6.4 */ |
class origin sex grade type; |
|
model days=origin sex grade type; |
|
output out=glmout r=res; |
|
run; |
|
proc univariate data=glmout noprint; |
|
var res; |
|
probplot; |
|
run; |
|
Chapter 7
For exercises 7.1 and 7.2, the data need to be restructured so that each measurement is an observation.
data vision2; set vision;
array xall {8} x1-x8; do i=1 to 8;
if i > 4 then eye='R'; else eye='L';
select(i);
when(1,5) strength=1;
when(2,6) strength=3; when(3,7) strength=6; when(4,8) strength=10;
end;
response=xall{i};
output;
end;
drop i x1-x8;
run; |
|
proc gplot data=vision2; |
/* 7.1 */ |
plot response*strength=eye; |
|
symbol1 i=std1mj l=1; |
|
symbol2 i=std1mj l=2; |
|
run; |
|
proc sort data=vision2; |
/* 7.2 */ |
by eye strength; |
|
run; |
|
proc boxplot data=vision2; |
|
plot response*strength; |
|
by eye; |
|
run; |
|
proc corr data=vision; |
/* 7.3 */ |
var x1-x8; |
|
run; |
|
Chapter 8
proc logistic data=ghq; |
/* 8.1 |
*/ |
class sex; |
|
|
model cases/total=ghq sex ghq*sex; |
|
|
run; |
|
|
proc logistic data=plasma desc; |
/* 8.2 |
*/ |
model esr=fibrinogen|fibrinogen gamma|gamma; |
|
|
run; |
|
|
Chapter 9
proc genmod data=ozkids; |
/* 9.1 |
*/ |
class origin sex grade type; |
|
|
model days=sex origin type grade grade*origin / dist=p |
link=log type1 type3 scale=3.1892; |
|
|
run; |
|
|
data ozkids; |
/* 9.2 |
*/ |
set ozkids; |
|
|
absent=days>13; |
|
|
run; |
|
|
proc genmod data=ozkids desc; class origin sex grade type;
model absent=sex origin type grade grade*origin / dist=b link=logit type1 type3;
run;
proc genmod data=ozkids desc; class origin sex grade type;
model absent=sex origin type grade grade*origin / dist=b link=probit type1 type3;
run;
Chapter 10
data pndep2; |
/* 10.1 */ |
set pndep2; |
|
depz=dep; |
|
run; |
|
proc sort data=pndep2; |
|
by idno time; |
|
run; |
|
proc stdize data=pndep2 out=pndep2; |
|
var depz; |
|
by idno; |
|
run; |
|