BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.

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

 

Fill.png

 

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:

Fill2.png

 

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.

 

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
1 ACCEPTED SOLUTION

Accepted Solutions
PGStats
Opal | Level 21

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 ;

PGStats_0-1617474533408.png

Note that the order is important in the list of limits, so that the more extreme values are named last.

 

PG

View solution in original post

6 REPLIES 6
FreelanceReinh
Jade | Level 19

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 ;
PGStats
Opal | Level 21

Add options nooutline noextend to the band statement to get rid of the colored lines.

PG
FreelanceReinh
Jade | Level 19

@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:

SGPlot34.png

Of course, it doesn't hurt to include them and they could be important in other situations.

Quentin
Super User

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!

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
PGStats
Opal | Level 21

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 ;

PGStats_0-1617474533408.png

Note that the order is important in the list of limits, so that the more extreme values are named last.

 

PG

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 6 replies
  • 1141 views
  • 4 likes
  • 4 in conversation