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!
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
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.