Search code examples
sasdrawtext

How do I rotate the x-axis labels in a SAS SGPLOT graph so that they are perpendicular (at 90 degrees to x-axis)


Is it possible to rotate the x-axis labels in SAS SGPLOT so that they are perpendicular (at 90 degrees to x-axis)? The fitpolicy option rotates 45 degrees, but this is not exactly what I need.

SAS code:

ods pdf style = custom file='';
proc sgplot data = filename;
series x = date y = unemployment_rate_15_24 / lineattrs = (color = CX963634 thickness = 2 pattern=solid);
series x = date y = unemployment_rate_15_ / lineattrs = (color = CX538DD5 thickness = 2 pattern=solid);
xaxis type=time fitpolicy=rotatethin notimesplit interval=year offsetmax=0 label = ' ' values = ("28FEB1995"d to "28FEB2015"d by year);
yaxis label = ' ' values = (0 to 18 by 2);
x2axis display=(nolabel novalues);
keylegend / location = inside position = topright;
label unemployment_rate_15_24 = "Youth (15-24 years) unemployment rate";
label unemployment_rate_15_ = "Overall (15+ years) unemployment rate";
run;
ods pdf close;

I've also tried to use the Graph Template Language in SAS. Here's the equiavalent code written in GTL:

proc template;
define statgraph mysgplot;
begingraph;
layout overlay /
cycleattrs=true 
xaxisopts=(label=" " offsetmax=0 type=time timeopts=(tickvaluelist=(12842 13207 13573 13938 14303 14668 15034 15399 15764 16129 16495 16860 17225 17590 17956 18321 18686 19051 19417 19782 20147) viewmin=12842 viewmax=20147 tickvaluefitpolicy=rotatethin splittickvalue=false interval=year)) 
yaxisopts=(label=" " type=linear linearopts=(tickvaluelist=(0 2 4 6 8 10 12 14 16 18) viewmin=0 viewmax=18 )) 
x2axisopts=(display=(ticks line) type=auto);
seriesplot x='date'n y='unemployment_rate_15_24'n / primary=true lineattrs=( color=cx963634 pattern=1 thickness=2) legendlabel="Youth (15-24 years) unemployment rate" NAME="SERIES";
seriesplot x='date'n y='unemployment_rate_15_'n / lineattrs=( color=cx538dd5 pattern=1 thickness=2) legendlabel="Overall (15+ years) unemployment rate" NAME="SERIES1";
discretelegend "SERIES" "SERIES1" / location=inside halign=right valign=top;
endlayout;
endgraph;
end;
run;

proc sgrender data = filename template=mysgplot;
run;

Solution

  • I don't believe that it's possible to do that in SGPLOT without using annotation. They have a nice piece of code for doing that with annotation here.

    With GTL, in 9.4 they introduce TICKVALUEROTATION, which needs to be used in tandem with TICKVALUEFITPOLICY=ROTATE|ROTATEALWAYS and SPLITTICKVALUE=FALSE. See this:

    data testdata;
      call streaminit(7);
      do timevar = 12900 to 16900 by 500;
        age=10+rand('Normal',5,2);
        output;
      end;
      format timevar date9.;
    run;
    
    proc template;
    define statgraph mysgplot;
    begingraph;
    layout overlay /
    cycleattrs=true 
    xaxisopts=(label=" " offsetmax=0 type=time 
        timeopts=(tickvaluerotation=VERTICAL TICKVALUEFITPOLICY=rotatealways splittickvalue=false) )
    yaxisopts=(label=" " type=linear linearopts=(tickvaluelist=(0 2 4 6 8 10 12 14 16 18) viewmin=0 viewmax=18 )) 
    x2axisopts=(display=(ticks line) type=auto);
    seriesplot x=timevar y=age
        / lineattrs=( color=cx538dd5 pattern=1 thickness=2) legendlabel="Overall (15+ years) unemployment rate" NAME="SERIES1";
    discretelegend "SERIES" "SERIES1" / location=inside halign=right valign=top;
    endlayout;
    endgraph;
    end;
    run;
    
    proc sgrender data = testdata template=mysgplot;
    run;
    

    I slightly simplify your axis to make sure it works properly, but I think most of your axis statements are okay.

    In 9.3 or earlier, I think you're stuck with annotation or 45 degrees. Or seeing if you can convince a SCATTERPLOT to draw outside of the axes. Or perhaps using a SERIESPLOT and a SCATTERPLOT to draw your own axes, but that seems a bit over the top.

    Here's what the above code looks like: Rendered Image