BookmarkSubscribeRSS Feed
dmuenz
Obsidian | Level 7

I'm creating a vertical bar chart in SGPANEL, and I want to increase the "offset" within each panel, squeezing together the bars within a panel. If the x-axis is consistent across panels, then no problem, I just use the OFFSETMIN and OFFSETMAX options in the COLAXIS statement. But when I use the PROPORTIONAL option of the PANELBY statement due to differing x-axes, then the OFFSETMIN/MAX options seem to get ignored. This interaction is not documented as far as I can tell.

 

Here's an example, creating plots with two panels in one row. The first plot has the same x-axis across panels and works as desired. The second plot has different x-axes across panels and does not honor the offset options.

 

data plotdata;
	call streaminit(123);
	do panel = 1, 2;
		do group = 'A', 'B', 'C';
			y = rand("Uniform", 0, 100);
			output;
		end;
	end;
run;

title1 "Plot with consistent x-axes across panels";
title2 "The bars are squeezed together just as I wanted";
proc sgpanel data=plotdata;
	panelby panel / rows=1 onepanel;
	vbarparm response=y category=group;
	%let offset = 0.3;
	colaxis offsetMin=&offset offsetMax=&offset;
run;

title1 "Plot with different x-axes across panels using PROPORTIONAL";
title2 "Oops! The bars are not squeezed together!";
proc sgpanel data=plotdata;
	where not (panel = 1 and group = 'C');
	panelby panel / rows=1 onepanel proportional uniscale=row;
	vbarparm response=y category=group;
	%let offset = 0.3;
	colaxis offsetMin=&offset offsetMax=&offset;
run;

Plot with consistent x-axes -- looks goodPlot with consistent x-axes -- looks good

 

Plot with different x-axes -- offset does not workPlot with different x-axes -- offset does not work

 

In the 2nd plot, I tried changing the PANELBY statement to use LAYOUT=COLUMNLATTICE, but this did not solve my issue.

panelby panel / layout=columnlattice onepanel proportional uniscale=row;

 

Is there a workaround to squeeze the bars together when using PROPORTIONAL? Thanks for any suggestions.

 

I'm using SAS 9.4 M6 in SAS Studio 3.8.

4 REPLIES 4
quickbluefish
Barite | Level 11

This should get you pretty close - there might be some trick to also hide the tick marks for the 'phantom' columns to the left and right, but if not, there are certainly hacks or things you could do with proc template, probably.  

data plotdata;
call streaminit(123);
array T1 {4} $3 _temporary_ ('_A1', 'A1', 'B1', 'C1');
array T2 {5} $3 _temporary_ ('_A2', 'A2', 'B2', 'C2', 'D2');
panel=1;
do i=1 to dim(T1);
	group=T1[i];
	if i=1 or i=dim(T1) then y=0;
	else y=rand("uniform", 0, 100);
	output;
end;
panel=2;
do i=1 to dim(T2);
	group=T2[i];
	if i=1 or i=dim(T2) then y=0;
	else y=rand("uniform", 0, 100);
	output;
end;
keep panel group y;
run;

proc format;
value $fp
	"_A1", "_A2", "C1", "D2"='09'x
	;
run;

proc sgpanel data=plotdata;
	panelby panel / rows=1 onepanel proportional uniscale=row;
	vbarparm response=y category=group;
	%let offset = 0.3;
	colaxis 
		valuesformat=$fp.
		offsetMin=&offset offsetMax=&offset;
run;

quickbluefish_0-1770338338661.png

 

dmuenz
Obsidian | Level 7

Thanks, @quickbluefish, I like your idea! This doesn't give me as much control over the offset size as I'd like (I'm very picky about my graphs), but it's better than what I had. To be clear, in your code the OFFSETMIN/MAX options still do not work, so you could remove them from your COLAXIS statement and get the same result:

 

colaxis valuesformat=$fp.;

 

I'll keep this question open to see if other ideas pop up, but if not I'll accept your answer. Maybe I'll also report this as a bug to SAS.

Ksharp
Super User

That was supposed to be if you are using "proportional" option . You can not apply OFFSETMIN/MAX to the different the panel with using PROC SGPANEL.

1) You can plot these bar separated one by one and combine them together:

https://blogs.sas.com/content/graphicallyspeaking/2022/09/10/complex-layouts-using-the-sg-procedures...

 

2)You can change the bar width to make it look better:

title1 "Plot with different x-axes across panels using PROPORTIONAL";
title2 "Oops! The bars are not squeezed together!";
proc sgpanel data=plotdata;
	where not (panel = 1 and group = 'C');
	panelby panel / rows=1 onepanel proportional uniscale=row ;
	vbarparm response=y category=group /barwidth=0.4;
run;

 

3) Or make some dummy group values as quickbluefish did:

data plotdata;
	call streaminit(123);
	do panel = 1, 2;
	    group='_';y=0;output;
		do group = 'A', 'B', 'C';
			y = rand("Uniform", 0, 100);
			output;
		end;
		group='-';y=0;output;
	end;
run;


title1 "Plot with different x-axes across panels using PROPORTIONAL";
title2 "Oops! The bars are not squeezed together!";
proc sgpanel data=plotdata;
	panelby panel / rows=1 onepanel proportional uniscale=row ;
	vbarparm response=y category=group /grouporder=data nooutline;
	colaxis values=('_' 'A' 'B' 'C' '-') valuesdisplay=(' ' 'A' 'B' 'C' ' ');
run;

 

Ksharp_0-1770368916489.png

 

quickbluefish
Barite | Level 11

Also, in case you don't know, the reason the tick labels (A, B, ... ) in the plot I made are displayed that way (one character) when the underlying data has values like "A1", "B1"... is because I guess '09'x in the right side of the format is interpreted as a one character symbol, so everything is getting truncated to one character by the format $fp.  If you needed to display the whole name, you should be able to just add the other values to the format, e.g., like this:

proc format;
value $fp
  "_A1", "_A2", "C1", "D2" = '09'x
"A1" = "A1"
"B1" = "B1"
"A2" = "A2"
...
;

 And, unrelated, if you want to adjust the space between the bars, you can use the 'barwidth' option in the vbarparm statement.  A barwidth of 1 means no space between bars:

VBARPARM .... / barwidth=1;
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
  • 4 replies
  • 135 views
  • 0 likes
  • 3 in conversation