BookmarkSubscribeRSS Feed
snoopy369
Barite | Level 11

I'm making a 100% Stacked Bar Chart with an axistable below it (to avoid labeling the bars which gets messy).  By default, the order of the two are opposing; the bar chart puts the lower number on the bottom while the axistable puts the lower number on top.  I was hoping to be able to reorder the axis table by reversing the Y axis for that table, but unfortunately don't seem to be able to (I'm guessing the axistable isn't even using the Y axis, for obvious reasons).

I figured out two workarounds, but neither is optimal for my particular usage.  One is to reverse the Y axis on the *barchart*, which does make the two match; but I prefer lower numbers on bottom.  The second is to sort the dataset by the two variables but descending the second variable; in combination with reversing the Y axis on the barchart, this makes it look correct as long as I have the same categories exactly for each bar, which my data should.  However, that sort itself is undesirable for the effects it has on my other charts, and I can't afford to re-sort the data twice for every set of charts as I'm making a few hundred thousand slides in total.

Is there a way to reverse the axistable, or am I stuck with one of the workarounds above (or a different/better one?)

The below code shows my example and a couple of workarounds.

proc template;

define statgraph test;

dynamic pctval;

begingraph/datacolors=(cxFF0000 cx00FF00 cx0000FF cxFFFF00 cxFF00FF cx00FFFF cxBBBBBB cx555555)

  datacontrastcolors=(cxFF0000 cx00FF00 cx0000FF cxFFFF00 cxFF00FF cx00FFFF cxBBBBBB cx555555);

  layout lattice/columnweights=preferred

                rowweights=preferred

                columndatarange=union

                columns=1 ;

  layout overlay/ /*yaxisopts=(reverse=1)*/ xaxisopts=(display=none);   *WORKAROUND 1 and 2 - uncomment yaxisopts;

  barchart x=sex y=pctval/group=age;

  endlayout;

  layout overlay / walldisplay=none xaxisopts=( display=none griddisplay=off offsetmin=.1 offsetmax=.1)

            yaxisopts=(display=(tickvalues) offsetmin=.2 offsetmax=0 reverse=1)

                     ;

         AxisTable x=sex value=pctval/

            class="age" colorGroup=age Display=(Label);

  endlayout;

  endlayout;

endgraph;

end;

quit;

proc tabulate data=sashelp.class;

where age le 15;

class sex age;

tables sex,age*rowpctn;

ods output table=classpct(keep=sex age pct:);

run;

/*  WORKAROUND 2 - uncomment this sort.

proc sort data=classpct;

by sex descending age ;

run;

*/

proc sgrender data=classpct template=test;

dynamic pctval='pctn_10';

run;

Thanks!

7 REPLIES 7
Jay54
Meteorite | Level 14

In your specific case, where group and class variable are nuumeric, you can use GROUPORDER=descending on the bar chart to reverse the order.  But, in general for such a case, we likely need an option to set (or at least reverse) the "Class" order on the AxisTable.

Still, it is good to see a question on the new SAS 9.4 statement. Smiley Happy

barchart x=sex y=pctval/group=age grouporder=descending;

snoopy369
Barite | Level 11

Thanks, Sanjay.  That seems to be effectively identical to reversing the Y axis from my point of view, no? (ie, it makes the barchart reverse, rather than the axistable reverse which is my preference).  I would look forward to seeing that option in a future release for the axis table Smiley Happy  Enjoying 9.4 GTL quite a lot, lots of useful new stuff in there.

9.3 used a scatterplot for the axistable, didn't it?  Is that something that could be easily used and reordered?

snoopy369
Barite | Level 11

Hmm, actually a BlockPlot.  Starting from Leroy Bessler's example where I saw this first (http://www.mwsug.org/proceedings/2012/DV/MWSUG-2012-DV13.pdf page 35 or so):

proc sgplot data=sashelp.stocks tmplout="c:\temp\test.txt";

where date ge '01JAN2005'd;

vline date / response=close group=stock

markers markerattrs=(size=7 symbol=circlefilled)

lineattrs=(thickness=3 pattern=solid)

datalabel=close

datalabelattrs=(family='Albany AMT/Bold' size=10 PT weight=Bold)

datalabelpos=bottom;

keylegend / noborder

titleattrs=(family='Albany AMT/Bold' size=12 PT)

valueattrs=(family='Albany AMT/Bold' size=12 PT);

yaxis display=(nolabel noticks noline) grid

offsetmin=0.05 /* space between top of datalabel table & bottom of plot area */

valueattrs=(family='Albany AMT/Bold' size=12 PT);

xaxis display=(nolabel noticks noline) grid

valueattrs=(family='Albany AMT/Bold' size=12 PT) values=(1 to 12 by 1);

format close 5.;

run;


That takes me to this template code:

proc template;

define statgraph sgplot;

dynamic _ticklist_;

begingraph /;

EntryTitle " " /;

layout overlay / xaxisopts=( griddisplay=on display=( tickvalues ) TickValueAttrs=( Size=12pt Family="Albany AMT/Bold") type=discrete discreteopts=( tickValueList=_ticklist_ ) ) yaxisopts=( griddisplay=on display=( tickvalues ) offsetmin=0.05 TickValueAttrs=( Size=12pt Family="Albany AMT/Bold") type=auto ) x2axisopts=(type=Discrete discreteOpts=(tickValueList=_ticklist_));

   SeriesPlot X=Date Y=_Sum1_Close_ / primary=true Group=Stock display=(markers) Markerattrs=( Symbol=CIRCLEFILLED Size=7) Lineattrs=( Pattern=1 Thickness=3) LegendLabel="Close (Sum)" NAME="VLINE";

    innermargin / align=bottom;

   blockplot x=Date block=_Sum1_Close_ / class="Stock" display=(label values)

  valueHalign=center repeatedValues=true valueFitPolicy=shrink LabelAttrs=GraphValueText

  LabelAttrs=GraphDataText( Family="Albany AMT/Bold" Size=10 Weight=bold )

  ValueAttrs=GraphDataText( Family="Albany AMT/Bold" Size=10 Weight=bold );

    endinnermargin;

   DiscreteLegend "VLINE" / Location=Outside TitleAttrs=( Size=12pt Family="Albany AMT/Bold") ValueAttrs=( Size=12pt Family="Albany AMT/Bold") Border=false;

endlayout;

endgraph;

end;

run;

The blockplot unfortunately doesn't look like it has reverse options either, nor does it reverse with the y-axis reversing.

Jay54
Meteorite | Level 14

Since sorting the original data could have other side effects, it may be better to use the option.

Yes, you can still use SCATTERPLOT with MARKERCHARACTER option to do your table, but then you cannot use the PREFERRED option for RowWeights.  Also, you can color the values, but not the labels.

BLOCKPLOT could work, but you cannot color the values.

snoopy369
Barite | Level 11

Thanks.

Also, as an aside, AXISTABLE's DISPLAY option is slightly quirky.  DISPLAY=NONE is invalid in this context, and while I realize DISPLAY=STANDARD is probably roughly equivalent to that if you require the value labels, it would be nice if NONE was a synonym for that if nothing else - it was confusing to eventually realize I had to use DISPLAY=STANDARD which I basically never use.  Smiley Wink

Jay54
Meteorite | Level 14

You should not have to use DISPLAY=Standard.  It is the default.

snoopy369
Barite | Level 11

Sure, but I wanted to use DISPLAY=NONE and kept getting errors Smiley Happy  I'm just suggesting including it, even if it does nothing, just to avoid people being confused by the inconsistency with most of the other plot types.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 7 replies
  • 2212 views
  • 3 likes
  • 2 in conversation