Data visualization with SAS programming

SGRENDER DiscreteLegend values

Accepted Solution Solved
Reply
Super Contributor
Posts: 543
Accepted Solution

SGRENDER DiscreteLegend values

Hi,

I am creating a stack bar plot using PROC TEMPLATE and SGRENDER.

However, I noticed that the legend values are in the alphabetical order, while I would like them to be in a the 'natural" order.

I.e., White, Black, Other not White, Other, Black OR Black, Other, White.

Basically, is there a way to control the values of the legend?

I tried using numeric values associated with my race group, but then I don't want to display 1,2,3 in the legend.

When I format the 1,2,3 to represent White, Black, Other...the legend values are once again alphabetized.

Thank you!

data clusterbarstack;

    length cluster $9 stack $5;

    input year cluster $ stack $ pct num_stack;

    label pct="Patients (%)";

datalines;

2010 A White 90 1

2010 A Black 8 2

2010 A Other 2 3

2010 B White 85 1

2010 B Black 15 2

2010 B Other 0 3

2010 C White 50 1

2010 C Black 45 2

2010 C Other 5 3

2011 A White 92 1

2011 A Black 7 2

2011 A Other 1 3

2011 B White 85 1

2011 B Black 12 2

2011 B Other 3 3

2011 C White 51 1

2011 C Black 40 2

2011 C Other 9 3

;

run;

proc template;

  define statgraph delete;

  DYNAMIC _WIDTH _HEIGHT

            _XAXIS _YAXIS _CLUSTER _STACK

            _YSTART _YEND _YINC _XSTART _XEND _XINC _YFMT _XFMT _YLO _YHI _XLO _XHI;

    begingraph / designwidth=_WIDTH designheight=_HEIGHT;

      layout gridded;

        layout datalattice columnvar=_XAXIS / headerlabeldisplay=value columnheaders=bottom border=false

                                              columngutter=14

                                              rowaxisopts=(offsetmin=0 offsetmax=0 display=(ticks tickvalues label) displaysecondary=none)

                                               row2axisopts=(offsetmin=0 offsetmax=0 display=none)

                                               columnaxisopts=(display=(line ticks tickvalues));

               layout prototype / cycleattrs=true walldisplay=none;

                barchart x=_CLUSTER y=_YAXIS / name="leg" group=_STACK GROUPORDER = deSCENDING ;

            endlayout;

        endlayout;

        discretelegend "leg" /location=outside /*VALIGN = BOTTOM;**/ across=1 halign=right valign=top opaque=true border=false sortorder=ASCENDINGFORMATTED

;

       endlayout;

     endgraph;

  end;

run;

proc sgrender data=clusterbarstack template=delete;

    DYNAMIC _WIDTH="2400px" _HEIGHT="1200px"

            _XAXIS="year" _YAXIS="pct" _CLUSTER="cluster"

/*            _STACK="stack";*/

            _STACK="num_stack";

run;

proc format;

    value race 1 = "White" 2 = "Black" 3 = "Other";

run;

*apply format;

proc sgrender data=clusterbarstack template=delete;

    DYNAMIC _WIDTH="2400px" _HEIGHT="1200px"

            _XAXIS="year" _YAXIS="pct" _CLUSTER="cluster"

/*            _STACK="stack";*/

            _STACK="num_stack";

            format num_stack race.;

run;


Accepted Solutions
Solution
‎07-22-2014 06:47 AM
Contributor
Posts: 24

Re: SGRENDER DiscreteLegend values

I did this using attrmap as I had a character variable and wanted a specific order. code snippet below.


  discreteattrmap name="colorbysign" / ignorecase=true;

value "PD " /
    fillattrs=GraphData1(color=red )
       markerattrs=GraphData1(color=red )
       lineattrs=GraphData1(color=red );;

    value "SD " /
    fillattrs=GraphData1(color=blue )
       markerattrs=GraphData1(color=blue )
       lineattrs=GraphData1(color=blue );  ; 

    value "PR " /
    fillattrs=GraphData1(color=orange )
       markerattrs=GraphData1(color=orange )
       lineattrs=GraphData1(color=orange ); ;

    value "CR " /
    fillattrs=GraphData1(color=green )
       markerattrs=GraphData1(color=green  )
       lineattrs=GraphData1(color=green );;

    value "NE " /
    fillattrs=GraphData1(color=grey )
       markerattrs=GraphData1(color=grey )
       lineattrs=GraphData1(color=grey ); ;  

  enddiscreteattrmap;

    legenditem type=line name="PD" / LABEL='PD' lineattrs=GraphData1(color=red THICKNESS=10)
                   labelattrs=(size=9 family="Arial") ;
    legenditem type=line name="SD" / LABEL='SD' lineattrs=GraphData1(color=blue THICKNESS=10)
          labelattrs=(size=9 family="Arial");;
    legenditem type=line name="PR" / LABEL='PR' lineattrs=GraphData1(color=orange THICKNESS=10)
             labelattrs=(size=9 family="Arial")     ;
    legenditem type=line name="CR" / LABEL='CR' lineattrs=GraphData1(color=green THICKNESS=10)
          labelattrs=(size=9 family="Arial");;
    legenditem type=line name="NE" / LABEL='NE' lineattrs=GraphData1(color=grey THICKNESS=10)
          labelattrs=(size=9 family="Arial");;

discreteattrvar attrvar=signvar var=_var attrmap="colorbysign"; 

      discretelegend "PD" "SD" "PR" "CR" "NE" / title=_label titleattrs=(size=9 family="Arial") BORDER=false;

View solution in original post


All Replies
Super User
Posts: 11,134

Re: SGRENDER DiscreteLegend values

Some example data would help. Also which version of SAS as the capabilities in SG graphics have changed in each recent release? If you're running a SAS 9.2 and get solutions requiring SAS 9.4 it will likely not help.

Super Contributor
Posts: 543

Re: SGRENDER DiscreteLegend values

There is example data, right after I wrote thank you..

I am using SAS 9.3

Anca

SAS Super FREQ
Posts: 1,145

Re: SGRENDER DiscreteLegend values

Normally, legend items are in the order reported by each plot.  However, as you have set SORTORDER on the DiscreteLegend, the entries will be in the order you have set.

Super Contributor
Posts: 543

Re: SGRENDER DiscreteLegend values

Understood,

however, with or without the SORTORDER option, the legend values can only be ORDERED based on the alphabetic values - descending or ascending.

Can one modified the values of the legend to be in some very specific order - once again, not alphabetically.

Anca

Super User
Posts: 11,134

Re: SGRENDER DiscreteLegend values

A dirty version would be to create a numeric variable with values in the order you want AND a custom format for the text. Most of these procedures will use the order of the value but display the formatted value unless you specify to sort by the formatted value.

Super Contributor
Posts: 543

Re: SGRENDER DiscreteLegend values

I am doing that,

but unless I apply a format like this:

proc format;

    value race 1 = "1.White" 2 = "2.Black" 3 = "3.Other";

run;

where I sneak a digit for my preferred format.

So, bottom line is that the values cannot be ordered specifically.

Anca.

SAS Super FREQ
Posts: 925

Re: SGRENDER DiscreteLegend values

If you set GROUPORDER=DATA on the BARCHART and remove the sort order on the legend, you should get the legend in natural order.

SAS Super FREQ
Posts: 1,145

Re: SGRENDER DiscreteLegend values

Plots will normally report group values in the order they are encountered in the data.  So, if you put them in the order you want, that should be the order in the legend.  There is no way to request a custom order in the legend.  Only alphabetical sorts are supported by sortorder.  Using attr maps or index, you can put groups in your order, and still get the colors you want.

Super Contributor
Posts: 543

Re: SGRENDER DiscreteLegend values

Sanjay,

I was afraid I may have to use the attr maps - which I used once for a very specific example.

Do you think you could provide some example code?

Thank you.

Anca.

SAS Super FREQ
Posts: 1,145

Re: SGRENDER DiscreteLegend values

Anca, sometimes, i put dummy observations with the group values in the order i want at the front of the data with missing values for other columns.  This ensures the groups I want are in the data in the order I want.  The missing values ensures the obs are not drawn.  This is also a good way to get all group values into the legend even when some of them may not be in the data today.

Solution
‎07-22-2014 06:47 AM
Contributor
Posts: 24

Re: SGRENDER DiscreteLegend values

I did this using attrmap as I had a character variable and wanted a specific order. code snippet below.


  discreteattrmap name="colorbysign" / ignorecase=true;

value "PD " /
    fillattrs=GraphData1(color=red )
       markerattrs=GraphData1(color=red )
       lineattrs=GraphData1(color=red );;

    value "SD " /
    fillattrs=GraphData1(color=blue )
       markerattrs=GraphData1(color=blue )
       lineattrs=GraphData1(color=blue );  ; 

    value "PR " /
    fillattrs=GraphData1(color=orange )
       markerattrs=GraphData1(color=orange )
       lineattrs=GraphData1(color=orange ); ;

    value "CR " /
    fillattrs=GraphData1(color=green )
       markerattrs=GraphData1(color=green  )
       lineattrs=GraphData1(color=green );;

    value "NE " /
    fillattrs=GraphData1(color=grey )
       markerattrs=GraphData1(color=grey )
       lineattrs=GraphData1(color=grey ); ;  

  enddiscreteattrmap;

    legenditem type=line name="PD" / LABEL='PD' lineattrs=GraphData1(color=red THICKNESS=10)
                   labelattrs=(size=9 family="Arial") ;
    legenditem type=line name="SD" / LABEL='SD' lineattrs=GraphData1(color=blue THICKNESS=10)
          labelattrs=(size=9 family="Arial");;
    legenditem type=line name="PR" / LABEL='PR' lineattrs=GraphData1(color=orange THICKNESS=10)
             labelattrs=(size=9 family="Arial")     ;
    legenditem type=line name="CR" / LABEL='CR' lineattrs=GraphData1(color=green THICKNESS=10)
          labelattrs=(size=9 family="Arial");;
    legenditem type=line name="NE" / LABEL='NE' lineattrs=GraphData1(color=grey THICKNESS=10)
          labelattrs=(size=9 family="Arial");;

discreteattrvar attrvar=signvar var=_var attrmap="colorbysign"; 

      discretelegend "PD" "SD" "PR" "CR" "NE" / title=_label titleattrs=(size=9 family="Arial") BORDER=false;

Super Contributor
Posts: 543

Re: SGRENDER DiscreteLegend values

PERFECTION!

THANK YOU!

SAS Super FREQ
Posts: 1,145

Re: SGRENDER DiscreteLegend values

Note:  With SAS 9.4M1 onwards, GTL and SGRENDER also support Data Set Attribute Maps, just like SG.  Now, you can define common attribute maps outside your template, and use them with any template without having to change the template itself by using the DATTRMAP option on the SGRENDER proc statement and the new DATTRVAR statement.  See example in blog article:  Group order in GTL - Graphically Speaking

Super Contributor
Posts: 543

Re: SGRENDER DiscreteLegend values

Thanks Sanjay!

🔒 This topic is solved and locked.

Need further help from the community? Please ask a new question.

Discussion stats
  • 14 replies
  • 1200 views
  • 3 likes
  • 5 in conversation