Data visualization with SAS programming

Split discretelegend items in GTL? (9.4)

New Contributor
Posts: 2

Split discretelegend items in GTL? (9.4)


A client wants to be able to either have a legenditem (discretelegend in gtl) continue on the next row if it takes up too much space, or break row if encountering a splitcharacter. As far as i can tell, this split behaviour is possible for axis labels, ticket values (discreet axis), and drawtext entries, but not for discrete legends. Is there any way to fix this? Below is some code that will show you the current workaround however it limits the number of columns to 1 and is hard-coded, the client wish to integrate this into a dynamic GUI solution. Working in SAS 9.4.

Example below



/* Example code that shows desired results (hard coded) */

data graph_data;
input Main_group $11. Sub_Group $50.;
Ursprunglig Skattehöjningar, låg- och medelinkomsttagare                                                     
Nuvarande   Skattehöjningar, låg- och medelinkomsttagare                                                     
Ursprunglig Skattehöjningar, höginkomsttagare                    
Nuvarande   Skattehöjningar, höginkomsttagare                                                                
Ursprunglig AMT (Alternative minimum tax)                                                                     
Nuvarande   AMT (Alternative minimum tax)                                                                     
Ursprunglig Arbetsgivaravgift                                                                                 
Nuvarande   Arbetsgivaravgift                                                                                 
Ursprunglig Förlängning av a-kassa                                                                             
Nuvarande   Förlängning av a-kassa                                                                             
Ursprunglig "The Sequester" (automatiska nedskärningar i offentliga utgifter)                                 
Nuvarande   "The Sequester" (automatiska nedskärningar i offentliga utgifter)                                   
Ursprunglig ”The Sequester” (automatiska nedskärningar i offentliga utgifter). Ännu ej genomförda åtstramningar.
Nuvarande   ”The Sequester” (automatiska nedskärningar i offentliga utgifter). Ännu ej genomförda åtstramningar.
Ursprunglig Annat                                                                                             
Nuvarande   Annat                                                                                             

data number;
input Value GraphStyleIndex;
1.0 1
0.0 1
0.3 2
0.2 2
0.7 3
0.0 3
0.65 4
0.65 4
0.2 5
0.0 5
0.8 6
0.0 6
0.0 10
0.8 10
0.4 7
0.3 7

data Diagram_A21;
merge graph_data number;

data Diagram_A21;
          set Diagram_A21;
          label Main_Group = '09'x;
    format  Main_Group $char100.;

proc template;
          define statgraph my_bars;
                   begingraph / pad=(left=43px right=53px bottom=0px);

        * Manual legend items to handle rowbreaks;
        legendItem type=marker name="item_1" /
              markerattrs=(color=CXA41D22 symbol=squarefilled)
              label="Skattehöjningar, låg och medelkomsttagare";

        legendItem type=marker name="item_2" /
              markerattrs=(color=CX0076BD symbol=squarefilled)
              label="Skattehöjningar, höginkomstagare";

        legendItem type=marker name="item_3" /
              markerattrs=(color=CXEEAF00 symbol=squarefilled)
              label="AMT (Alternitive minmum tax)";

        legendItem type=marker name="item_4" /
              markerattrs=(color=CXBCBEC0 symbol=squarefilled)

        legendItem type=marker name="item_5" /
              markerattrs=(color=CX537121 symbol=squarefilled)
              label="Förlängning av a-kassa";

        legendItem type=marker name="item_6" /
              markerattrs=(color=CX6A4976 symbol=squarefilled)
              label='"The Sequester" (automatiska nedskärningar i';

        legendItem type=marker name="item_6_1" /
              markerattrs=(color=white symbol=squarefilled)
              label='offentliga utgifter)';

        legendItem type=fill name="item_7" /
              markerattrs=(color=white symbol=squarefilled)
              label='"The Sequester" (automatiska nedskärningar i';

        legendItem type=marker name="item_7_1" /
              markerattrs=(color=white symbol=squarefilled)
              label='offentliga utgifter) Ännu ej genomförda';

        legendItem type=marker name="item_7_2" /
              markerattrs=(color=white symbol=squarefilled)

        legendItem type=marker name="item_8" /
              markerattrs=(color=CXDE750C symbol=squarefilled)

                             layout overlay /
                                       yaxisopts=(display=(tickvalues line) tickstyle=inside offsetmin=0 offsetmax=0 LINEAROPTS=(viewmin=0 viewmax=4.5 tickvaluelist=(0 0.5 1 1.5 2 2.5 3 3.5 4 4.5) tickvalueformat=commax3.1) griddisplay=on displaysecondary=(line ticks))
            y2axisopts=(display=(line ticks) tickstyle=inside) 
                                       xaxisopts=(display=(tickvalues label line) tickstyle=inside griddisplay=on LABELATTRS=(SIZE=25pt) displaysecondary=(line ticks))
            y2axisopts=(display=(line ticks) tickstyle=inside);         
                             barchart x=main_group y=value /
                             stat=mean group=Sub_Group name="b" index=GraphStyleIndex BARWIDTH=0.4;


                             discretelegend "item_1" "item_2" "item_3" "item_4" "item_5"
            "item_6" "item_6_1" "item_7" "item_7_1" "item_7_2" "item_8"
        / DISPLAYCLIPPED=true border=false HALIGN=LEFT valign=bottom;

ods listing;
ods graphics on / scale=off width=640px  height=735px imagename="Diagram A2" maxlegendarea=100 antialias=on imagefmt=png; 

proc sgrender data=Diagram_A21 template=my_bars;


Posts: 1,040

Re: Split discretelegend items in GTL? (9.4)

I would be interested to see what you have been able to make so far.  Since you are building a custom legend anyway using legend items, and using SAS 9.4, you could do this using GTL annotate.  It may be easier, and portable to other graphs.  The TEXT function in annotate supports splitting.

Update:  Prashant pointed out your data is included in the program, so I can run it.  Pretty cool usage of white chicklets for long labels.  You can also use LegendItem of TYPE=Text.

Yes, for future release, we can add text splitting to legends too.

New Contributor
Posts: 2

Re: Split discretelegend items in GTL? (9.4)

Hello, thanks you for your response - really like your blog!

I have been reading up on the gtl annotate and Im not sure it would work with what we are trying to do. The graphs are created by the clients from a graphical interface where they select labeltext, legendlocation, datasources etcetera. If I understand correctly annotate will simply print its contents to the graph but not influence it in any other way. The clients are used to the graph adapting to their choices, e.g a center/left/outside discretelegend will shift the y-axis to the right. Annotate would not do that. Not sure either how annotate handles the combination of legenditem symbols with the text entries and different combinations of rows & columns of entries. . We are thinking about limiting the number of legendcolumns to 1 (currently the user can select this) and assigning "/n" as a custom splitcharacter. Whenever encountering /n in a legenditem label string we divide it into several legenditems where the subsequent have white symbols giving the illusion of row breaks (as in the example). I will try using GTL annotate tomorrow but otherwise we will go with the less elegant solution.  

Posts: 1,040

Re: Split discretelegend items in GTL? (9.4)

FYI, if you really want X axis grid lines, you can also move them inbetween the bars.  Use:

xaxisopts=(display=(tickvalues label line) tickstyle=inside  griddisplay=on

LABELATTRS=(SIZE=25pt) displaysecondary=(line ticks) discreteopts=(ticktype=inbetween))

Post a Question
Discussion Stats
  • 3 replies
  • 2 in conversation