BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
mnithinshetty
Obsidian | Level 7

Hi,

I am trying to produce a graph from sgpnel. Please see the attatched to see desired output.

the requirement is to display the N count below the X axis. I am finding a major challenge to do annotation in sgpanel output.

Initially, I displayed N count along the X axis using colaxistable statement in proc sgpanel procedure. but this option will provide us N count inside the graph area, which customer don't want now.

1) Are we able to do annotations to get N count below X axis in sgpanel procedure. 

Please let me know if you need more information.

Any input will help me.

Thanks in advance.

 

1 ACCEPTED SOLUTION

Accepted Solutions
BrunoMueller
SAS Super FREQ

Thinking about it again, to take advantage of LAYOUT LATTICE you can also use the annotate facility to create the N entries outside. See below for an example, it uses the same data for plotting additionally also an annotate dataset is create to draw the N values (in red).

 


/*
 * make SGanno macro available
 */
%sganno

data anno_a;
  set group_a_stat end=eod;

  %SGTEXT(
    id="GROUP_A"
    , label=cats(value_a_n)
    , xc1=group_a
    , x1space="datavalue"
    , y1=-7.5
    , y1space="wallpercent"
    , textcolor="red"
    )
    if eod = 1 then do;
    %SGTEXT(
      id="GROUP_A"
      , label="label"
      , x1=0
      , x1space="wallpercent"
      , y1=-7.5
      , y1space="wallpercent"
      , anchor="right"
      , border="true"
      , widthunit="percent"
      , width=150
      )
  end;
run;

data anno_b;
  set group_b_stat end=eod;

  %SGTEXT(
    id="GROUP_B"
    , label=cats(value_b_n)
    , xc1=group_b
    , x1space="datavalue"
    , y1=-7.5
    , y1space="wallpercent"
    , textcolor="red"
    )
    if eod = 1 then do;
    %SGTEXT(
      id="GROUP_B"
      , label="label"
      , x1=0
      , x1space="wallpercent"
      , y1=-7.5
      , y1space="wallpercent"
      , anchor="right"
      , border="true"
      , textcolor=""
      , widthunit="percent"
      , width=150
      )
  end;
run;

data anno;
  set anno_a anno_b;
run;

/*
 * create your own GTL
 */
proc template;
  define statgraph two_vbox;
    dynamic _ticklist_;
    begingraph / ;
      layout lattice / columns=2  rowdatarange=union columndatarange=unionall ;
        column2headers;
          entry "Group A colum2headers";
          entry "Group B colum2headers";
        endcolumn2headers;
        layout overlay / 
          pad=(bottom=5pct)
          xaxisopts=(type=Discrete discreteOpts=(sortOrder=ascendingFormatted)
          display=(line ticks tickvalues))
          
        ;
          entry "Group A layout" / valign=top;
          BoxPlot X=group_a Y=value_a / primary=true LegendLabel="value_a" NAME="VBOXa";
          annotate / id="GROUP_A";
        endlayout;
        layout overlay / 
          xaxisopts=(type=Discrete discreteOpts=(sortOrder=ascendingFormatted)  display=(line ticks tickvalues))
          
        ;
          entry "Group A layout" / valign=top;
          BoxPlot X=group_b Y=value_b / primary=true LegendLabel="value_b" NAME="VBOXb";
          annotate / id="GROUP_B";
        endlayout;
      endlayout;
    endgraph;
  end;
run;

proc sgrender data=group_combined template=two_vbox sganno=anno;
run;

View solution in original post

5 REPLIES 5
BrunoMueller
SAS Super FREQ
How many groups do you typically have? The ones you named group A, group B.
mnithinshetty
Obsidian | Level 7

I have two treatments.

BrunoMueller
SAS Super FREQ

Since the COLAXISTABLE does not support a LOCATION= option to have it outside and SGPANEL does not support annotate with data, one way is to use the Graph Template Language (GTL) and draw the two groups individually. This also means you have to prepare the data for the two groups using different variable names and combine them into the one data set for Proc SGENDER. Find below a code example, as you can see it is more effort. It is not complete, you will need to make some changes, but it is a start.

 

/*
 * data for group a
 */
data group_a;
  set sashelp.cars;
  where origin = "Europe";
  group_a = type;
  value_a = invoice;
  keep group_a value_a;
run;

/*
 * data for axistable
 */
proc means data=group_a nway noprint;
  class group_a;
  var value_a;
  output out=group_a_stat(drop=_freq_ _type_)  median=  n=/autoname;
run;

/*
 * data for group b
 */
data group_b;
  set sashelp.cars;
  where origin = "USA";
  group_b = type;
  value_b = invoice;
  keep group_b value_b;
run;

/*
 * data for axistable
 */
proc means data=group_b nway noprint;
  class group_b;
  var value_b;
  output out=group_b_stat(drop=_freq_ _type_)  median=  n=/autoname;
run;

/*
 * combine data vertical
 */
data group_combined;
  set group_a group_a_stat group_b group_b_stat;
run;

/*
 * check GTL for individual graph
 */
proc sgplot data=group_combined tmplout="c:\temp\sgplot_gtl.sas";
  vbox value_a / category=group_a;
  xaxistable value_a_n / x=group_a;
run;

ods graphics / width=1200 height=900;
ods path
  (prepend) work.template (update)
;

/*
 * create your own GTL
 */
proc template;
  define statgraph two_vbox_axis_outside;
    dynamic _ticklist_;
    begingraph / collation=binary;
      layout lattice / columns=2  rowdatarange=union;
        layout lattice / columnweights=preferred rowweights=preferred columndatarange=union  columns=1;;
          layout overlay / xaxisopts=(type=Discrete  display=(line ticks tickvalues));
            entry "Group A" ;
            BoxPlot X=group_a Y=value_a / primary=true LegendLabel="value_a" NAME="VBOXa";
          endlayout;
          Layout Overlay /  xaxisopts=(discreteOpts=(sortOrder=ascendingFormatted)) xaxisopts=(type=Discrete discreteOpts=(tickValueList=_ticklist_ tickvaluefitpolicy=SplitRotate tickValueListPolicy=Union)) walldisplay=none xaxisopts=(display=none griddisplay=off displaySecondary=none) x2axisopts=(display=none griddisplay=off displaySecondary=none);
            AxisTable Value=value_a_N X=group_a / labelPosition=min Display=(Label) label="my label" labeljustify=right;
          endlayout;
        endlayout;
        layout lattice / columnweights=preferred rowweights=preferred columndatarange=union  columns=1;;
          layout overlay / xaxisopts=(discreteOpts=(sortOrder=ascendingFormatted)) xaxisopts=(type=Discrete discreteOpts=(tickValueList=_ticklist_ tickvaluefitpolicy=SplitRotate tickValueListPolicy=Union)) x2axisopts=(discreteOpts=(sortOrder=ascendingFormatted)) x2axisopts=(type=Discrete discreteOpts=(tickValueList=_ticklist_ tickvaluefitpolicy=SplitRotate tickValueListPolicy=Union));
            entry "Group B";
            BoxPlot X=group_b Y=value_b / primary=true LegendLabel="value_b" NAME="VBOXb";
          endlayout;
          Layout Overlay /  xaxisopts=(discreteOpts=(sortOrder=ascendingFormatted)) xaxisopts=(type=Discrete discreteOpts=(tickValueList=_ticklist_ tickvaluefitpolicy=SplitRotate tickValueListPolicy=Union)) walldisplay=none xaxisopts=(display=none griddisplay=off displaySecondary=none) x2axisopts=(display=none griddisplay=off displaySecondary=none);
            AxisTable Value=value_b_N X=group_b / labelPosition=min Display=(Label) ;
          endlayout;
        endlayout;
      endlayout;
    endgraph;
  end;
run;

proc sgrender data=group_combined template=two_vbox_axis_outside;
run;

 

 

BrunoMueller
SAS Super FREQ

Thinking about it again, to take advantage of LAYOUT LATTICE you can also use the annotate facility to create the N entries outside. See below for an example, it uses the same data for plotting additionally also an annotate dataset is create to draw the N values (in red).

 


/*
 * make SGanno macro available
 */
%sganno

data anno_a;
  set group_a_stat end=eod;

  %SGTEXT(
    id="GROUP_A"
    , label=cats(value_a_n)
    , xc1=group_a
    , x1space="datavalue"
    , y1=-7.5
    , y1space="wallpercent"
    , textcolor="red"
    )
    if eod = 1 then do;
    %SGTEXT(
      id="GROUP_A"
      , label="label"
      , x1=0
      , x1space="wallpercent"
      , y1=-7.5
      , y1space="wallpercent"
      , anchor="right"
      , border="true"
      , widthunit="percent"
      , width=150
      )
  end;
run;

data anno_b;
  set group_b_stat end=eod;

  %SGTEXT(
    id="GROUP_B"
    , label=cats(value_b_n)
    , xc1=group_b
    , x1space="datavalue"
    , y1=-7.5
    , y1space="wallpercent"
    , textcolor="red"
    )
    if eod = 1 then do;
    %SGTEXT(
      id="GROUP_B"
      , label="label"
      , x1=0
      , x1space="wallpercent"
      , y1=-7.5
      , y1space="wallpercent"
      , anchor="right"
      , border="true"
      , textcolor=""
      , widthunit="percent"
      , width=150
      )
  end;
run;

data anno;
  set anno_a anno_b;
run;

/*
 * create your own GTL
 */
proc template;
  define statgraph two_vbox;
    dynamic _ticklist_;
    begingraph / ;
      layout lattice / columns=2  rowdatarange=union columndatarange=unionall ;
        column2headers;
          entry "Group A colum2headers";
          entry "Group B colum2headers";
        endcolumn2headers;
        layout overlay / 
          pad=(bottom=5pct)
          xaxisopts=(type=Discrete discreteOpts=(sortOrder=ascendingFormatted)
          display=(line ticks tickvalues))
          
        ;
          entry "Group A layout" / valign=top;
          BoxPlot X=group_a Y=value_a / primary=true LegendLabel="value_a" NAME="VBOXa";
          annotate / id="GROUP_A";
        endlayout;
        layout overlay / 
          xaxisopts=(type=Discrete discreteOpts=(sortOrder=ascendingFormatted)  display=(line ticks tickvalues))
          
        ;
          entry "Group A layout" / valign=top;
          BoxPlot X=group_b Y=value_b / primary=true LegendLabel="value_b" NAME="VBOXb";
          annotate / id="GROUP_B";
        endlayout;
      endlayout;
    endgraph;
  end;
run;

proc sgrender data=group_combined template=two_vbox sganno=anno;
run;
mnithinshetty
Obsidian | Level 7
Thank you so much for the reply.:) I will try this method and let you know

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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
  • 5 replies
  • 1587 views
  • 2 likes
  • 2 in conversation