Is there any way to get the band generated by the BAND statement to *smoothly* follow the line generated by SERIES when the SERIES statement is making use of the SMOOTHCONNECT option? I have tried referencing the named line with the 'modelname' option in the BAND statement, but it seems to ignore that -- i.e., the band is still jagged while the line is smooth. I realize that if I knew what algorithm was used by SMOOTHCONNECT, I could probably generate the upper and lower limits of the band manually, but I'm wondering if there's a simpler way?
The below code generates some test data and illustrates the issue. Thanks for any help!
data test;
call streaminit(123456);
y=0;
pop=5000;
do x=1 to 50;
y+rand('normal')*10;
sd=500+rand('uniform')*250;
l95=y-sd/sqrt(pop);
u95=y+sd/sqrt(pop);
output;
pop+(-rand('integer',15,35));
end;
run;
proc sgplot data=test noautolegend;
series x=x y=y / smoothconnect name="line" lineattrs=(color=black thickness=2);
band x=x lower=l95 upper=u95 / modelname="line"
fillattrs=(color=red) transparency=0.6;
run;
The result:
data test;
call streaminit(123456);
y=0;
pop=5000;
do x=1 to 50;
y+rand('normal')*10;
sd=500+rand('uniform')*250;
l95=y-sd/sqrt(pop);
u95=y+sd/sqrt(pop);
output;
pop+(-rand('integer',15,35));
end;
run;
proc sql noprint;
select count(*) into :nobs from test;
select min(x),max(x) into :x_min, :x_max from test;
select x into :x separated by ',' from test;
select y into :mean separated by ',' from test;
select l95 into :l95 separated by ',' from test;
select u95 into :u95 separated by ',' from test;
quit;
data msplint;
do x=&x_min. to &x_max. by 0.1;
spline_mean=msplint(x, &nobs.,&x., &mean.);
spline_l95=msplint(x, &nobs.,&x., &l95.);
spline_u95=msplint(x, &nobs.,&x., &u95.);
output;
end;
run;
proc sgplot data=msplint noautolegend;
band x=x lower=spline_l95 upper=spline_u95/fillattrs=(color=red) transparency=0.6;
series x=x y=spline_mean / smoothconnect lineattrs=(color=black thickness=2);
run;
data test;
call streaminit(123456);
y=0;
pop=5000;
do x=1 to 50;
y+rand('normal')*10;
sd=500+rand('uniform')*250;
l95=y-sd/sqrt(pop);
u95=y+sd/sqrt(pop);
output;
pop+(-rand('integer',15,35));
end;
run;
proc sql noprint;
select count(*) into :nobs from test;
select min(x),max(x) into :x_min, :x_max from test;
select x into :x separated by ',' from test;
select y into :mean separated by ',' from test;
select l95 into :l95 separated by ',' from test;
select u95 into :u95 separated by ',' from test;
quit;
data msplint;
do x=&x_min. to &x_max. by 0.1;
spline_mean=msplint(x, &nobs.,&x., &mean.);
spline_l95=msplint(x, &nobs.,&x., &l95.);
spline_u95=msplint(x, &nobs.,&x., &u95.);
output;
end;
run;
proc sgplot data=msplint noautolegend;
band x=x lower=spline_l95 upper=spline_u95/fillattrs=(color=red) transparency=0.6;
series x=x y=spline_mean / smoothconnect lineattrs=(color=black thickness=2);
run;
Wow, very nice! Had never heard of the msplint function - thank you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.