There was an interesting question on LinkedIn, where the desire was to fill the peaks of a series plot with one color, and the valleys as another color.
https://www.linkedin.com/feed/update/urn:li:activity:6783694808239128576
I'm wondering how folks would approach this.
Graphing guru Kriss Harriss had the good idea of using bandplot, and posted the approach in his excellent Daily Coding series:
https://www.linkedin.com/posts/krissharris_dailycoding-day91-sgf-activity-6783513455380041728-vO9n
When I played with this, I started with a sine wave and the goal of coloring the peaks and valleys different colors, without specifying the x-values to define each peak. I got close to what I wanted, but unfortunately there is no /BREAK option for the band statement, so SGPLOT connects the peaks.
My code:
data foo;
do x = 0 to 3.14*4 by 0.01;
y = sin(x);
output;
end;
run;
data foo2 ;
set foo ;
if y > .5 then do ;
group=1 ;
limit=.5 ;
end ;
else if y < -.75 then do ;
group= 2 ;
limit= -.75 ;
end ;
run ;
proc sgplot data=foo2 ;
series x=x y=y ;
band x = x lower = limit upper = y / group=group nomissinggroup;
run ;
My output, within the unwanted connecting bands highlighted:
I thought this was an interesting question, so was curious about other approaches.
Since the OP has reference lines for each band, I think my approach might actually 'work' because you could make the reference lines cover the unwanted band lines.
I guess you could do:
data foo;
do x = 0 to 3.14*4 by 0.01;
y = sin(x) + 10;
output;
end;
run;
data foo2 ;
set foo ;
output;
t = x; x = .;
do Limit = 9.7, 9.2, 10.5, 10.75;
if (y-10) / (limit-10) > 1 then z = y;
else z = limit;
output;
end ;
run ;
proc sgplot data=foo2 ;
band x = t lower = limit upper = z / group=limit nomissinggroup;
series x = x y = y ;
run ;
Note that the order is important in the list of limits, so that the more extreme values are named last.
Hello @Quentin,
It looks like Simon Bacha opened an own thread about this the day before yesterday and that @PGStats's solution avoids the problem of the connecting lines. I'm still trying to understand the trick, but it seems that the way he defines the limits is about as important as omitting the GROUP= option (and using two BAND statements instead).
Something like this:
data foo2 ;
set foo ;
limit1 = min(y, .5) ;
limit2 = max(y, -.75) ;
run ;
proc sgplot data=foo2 ;
series x=x y=y ;
band x = x lower = limit1 upper = y / fillattrs=(color=CX6F7EB3) legendlabel='Group 1' ;
band x = x lower = limit2 upper = y / fillattrs=(color=CXD05B5B) legendlabel='Group 2' ;
run ;
Add options nooutline noextend to the band statement to get rid of the colored lines.
@PGStats wrote:
Add options nooutline noextend to the band statement to get rid of the colored lines.
Thanks, @PGStats, for chiming in. These two options didn't seem to have an impact on the graph (with Quentin's data), which is why I omitted them for simplicity:
Of course, it doesn't hurt to include them and they could be important in other situations.
As @FreelanceReinh mentioned, adding NOOUTLINE NOEXTEND doesn't avoid the connecting line.
It looks like your nifty solution avoids the connecting line by having data where the upper value and the lower value are the same, so I suspect SGPLOT is drawing a band with height 0. So for my approach using group, the hack would be to add records for each group, something like:
data foo2 ;
set foo ;
if y > .5 then do ;
group=1 ;
limit=.5 ;
output ;
end ;
else if y < -.75 then do ;
group= 2 ;
limit= -.75 ;
output ;
end ;
else do ;
limit=y ;
group=1 ; output ;
group=2 ; output ;
end ;
run ;
proc sgplot data=foo2 ;
series x=x y=y ;
band x = x lower = limit upper = y / group=group nomissinggroup ;
run ;
So in the absence of a /break option, looks like a band of height 0 achieves the same effect.
But your solution in the other thread is better than this one!
I guess you could do:
data foo;
do x = 0 to 3.14*4 by 0.01;
y = sin(x) + 10;
output;
end;
run;
data foo2 ;
set foo ;
output;
t = x; x = .;
do Limit = 9.7, 9.2, 10.5, 10.75;
if (y-10) / (limit-10) > 1 then z = y;
else z = limit;
output;
end ;
run ;
proc sgplot data=foo2 ;
band x = t lower = limit upper = z / group=limit nomissinggroup;
series x = x y = y ;
run ;
Note that the order is important in the list of limits, so that the more extreme values are named last.
See also a related idea: Create a density curve with shaded tails
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.