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

Hi All,

This is my first time at here and i have stacked a problem regarding GTL (Graphical Template language) from last couple of days.

-Major problem is that while using same formatted value (say for example: "Pos" for y-axis=0.2,1.2.. ) , BAR is overlapping on the Graph

-i have also tried with TICKVALUELIST on Y-AXIS but it seems SCATTERPLOT after BAR-CHART is not working on OVERLAY and generated warning

-For better understanding, i have given the code and output hereby

Output:

-From the attached output (test.png); you will see where Formatted Values is repeated at Y-Axis is overlapping

Code:

  PROC FORMAT;

    VALUE trtsdf

    0.2="pos"

    0.4="unc"

    0.6="neg"

    0.8="x 200 mg"

    1.2="pos"

    1.4="unc"

    1.6="neg"

    1.8="x 400 mg"

    ;

    VALUE trtpf

    0.2=" 12 (4.67%)"

    0.4=" 11 (8.03%)"

    0.6=" 13 (23.31%)"

    0.8=" 61 (  100%)"

    1.2="  8 (5.69%)"

    1.4=" 10 (26.61%)"

    1.6="  8 (76.69%)"

    1.8=" 51 (  100%)"

  QUIT;

   PROC template;

    DEFINE STATGRAPH gtplot;

    BEGINGRAPH;

    LAYOUT OVERLAY / XAXISOPTS=(label=" "

                     linearopts=(tickvaluesequence=(start=-5 end=0 increment=1)))

                     YAXISOPTS=(label="Treatment / Dose")

                     Y2AXISOPTS=(label="N(%)");

     BARCHART y=estimate x=paramn  / GROUP=paramn BARWIDTH=0.4  NAME="bar" ORIENT=horizontal

          FILLATTRS=(COLOR = LIGHTGREY) DATATRANSPARENCY=0.7;

     SCATTERPLOT x=estimate  y=paramn  / GROUP=paramn XERRORLOWER=eval(estimate-standard)

     ERRORBARATTRS=(thickness=1)

     LEGENDLABEL="Results" NAME="SCATTER"

     MARKERATTRS=(color=black size=0);

     BARCHART y=estimate x=paramn1 / GROUP=paramn BARWIDTH=0.4 PRIMARY=no NAME="bar1"

                                     ORIENT=horizontal YAXIS=y2

                                     FILLATTRS=(COLOR = LIGHTGREY) DATATRANSPARENCY=0.7 ;

     ENDLAYOUT;

    ENDGRAPH;

    END;

  RUN;

  PROC SGRENDER DATA=uni_api TEMPLATE="gtplot";

    format paramn trtsdf. paramn1 trtpf.;

  RUN;

  

-Waiting for your kind Reply and thanks in advance

Sami


test.png
1 ACCEPTED SOLUTION

Accepted Solutions
Jay54
Meteorite | Level 14

Needle plots does not supoport orient=horizontal.  You are using SAS 9.2, so, maybe a vector plot could be made to work (with arrowheads). Vector plot supports only numeric variables.  With SAS 9.3, you can use the horizontal HighLow plot instead.

View solution in original post

14 REPLIES 14
Jay54
Meteorite | Level 14

It is easier to help if you attach your data so we can run your program..  If data is confidential, provide some sample data in program.

Sami
Obsidian | Level 7

Hi Sanjay,

Can you please just run the code to produce the data set then run this previous attached code:

proc sql;

   create table uni_api

   (paramn num(8), paramn1 num(8), estimate num(8),standard num(8));

   insert into uni_api

   values (0.2, 0.2, -3.0, 0.3)

   values (0.4, 0.4, -2.8, 0.4)

   values (0.6, 0.6, -3.1, 0.2)

   values (0.8, 0.8, -3.4, 0.4)

   values (1.2, 1.2, -2.7, 0.6)

   values (1.4, 1.4, -2.9, 0.3)

   values (1.6, 1.6, -3.3, 0.2)

   values (1.8, 1.8, -3.1, 0.1);

quit;

Best Regards

Sami

Vince28_Statcan
Quartz | Level 8

TICKVALUELIST and TICKVALUEFORMAT can be worked to get the left axis values formatted appropriately (you remove the paramn trtsdf. from the format statement and use that as value for tickvalueformat). The issue is that if you do this, the scatterplot no longer alligns with the barchart as the barchart MUST have a category variable as X axis and thus there's no concept of distance between .8 and 1.2

Since the first graph you've defined needs category variables, the left axis gets defined as a discrete axis and because of formats pointing to the same values, you create 8 charts.

The most simple fix is to change your format trtsdf to make all of the labels distinct. You might be able to play with truncation of labels on the graph to create a long format like 0.2="pos                       1" and truncate the end to mimic your desired output.

Otherwise, you can change the data and the tick values so that you can line up a numeric left Y axis perfectly with a categorical (spread evenly) right Y axis. This can be seen by the code example below :

Alternatively, I assume you could've added a data point of missing values for 1 and formated it as "" to create a space inside your graph retaining the .2/.4/.6/.8 patterns. I put to bold the changes I made.


proc sql;
   create table uni_api
   (paramn num(8), paramn1 num(8), estimate num(8),standard num(8));
   insert into uni_api
   values (0.25, 0.25, -3.0, 0.3)
   values (0.5, 0.5, -2.8, 0.4)
   values (0.75, 0.75, -3.1, 0.2)
   values (1, 1, -3.4, 0.4)
   values (1.25, 1.25, -2.7, 0.6)
   values (1.5, 1.5, -2.9, 0.3)
   values (1.75, 1.75, -3.3, 0.2)
   values (2.0, 2.0, -3.1, 0.1);
quit;

  PROC FORMAT;
    VALUE trtsdf
    0.25="pos"
    0.5="unc"
    0.75="neg"
    1.0="x 200 mg"
    1.25="pos"
    1.5="unc"
    1.75="neg"
    2.0="x 400 mg"
    ;
    VALUE trtpf
   0.25=" 12 (4.67%)"
    0.5=" 11 (8.03%)"
    0.75=" 13 (23.31%)"
    1.0=" 61 (  100%)"
    1.25="  8 (5.69%)"
    1.5=" 10 (26.61%)"
    1.75="  8 (76.69%)"
    2.0=" 51 (  100%)"
;
  QUIT;

   PROC template;
    DEFINE STATGRAPH gtplot;
    BEGINGRAPH;
    LAYOUT OVERLAY / XAXISOPTS=(label=" "
                     linearopts=(tickvaluesequence=(start=-5 end=0 increment=1)))
                     YAXISOPTS=(type=linear label="Treatment / Dose" linearopts=(tickvaluelist=(0.25 0.5 0.75 1.0 1.25 1.5 1.75 2.0) tickvalueformat=trtsdf.) )
                     Y2AXISOPTS=(label="N(%)");

     BARCHART y=estimate x=paramn1 / GROUP=paramn BARWIDTH=0.4  NAME="bar" ORIENT=horizontal
          FILLATTRS=(COLOR = LIGHTGREY) DATATRANSPARENCY=0.7 YAXIS=y2;

     SCATTERPLOT x=estimate  y=paramn  / GROUP=paramn XERRORLOWER=eval(estimate-standard)
     ERRORBARATTRS=(thickness=1)
     LEGENDLABEL="Results" NAME="SCATTER"
     MARKERATTRS=(color=black size=0);

     BARCHART y=estimate x=paramn1 / GROUP=paramn BARWIDTH=0.4 PRIMARY=no NAME="bar1"
                                     ORIENT=horizontal YAXIS=y2
                                     FILLATTRS=(COLOR = LIGHTGREY) DATATRANSPARENCY=0.7 ;
     ENDLAYOUT;
    ENDGRAPH;
    END;
  RUN;

  PROC SGRENDER DATA=uni_api TEMPLATE="gtplot";
    format /* paramn trtsdf. */ paramn1 trtpf.;
  RUN;

Hope this was useful, I've learned a lot myself trying to solve this puzzle -_-. Sadly, I lost the help page that clearly states that if you attempt to overlay graphs for which the axis' are not compatible, you can get unexpected results.

If there exists a bar-making plot that can use numeric points and a width instead of categorical data, you could then get more generic in terms of how you set our paramn value ticks but I couldn't find any in the documentation.(maybe its achiveable with histogramparm with very painful handling of negative values).

Vince

Jay54
Meteorite | Level 14

For the last part of your question about a bar-making plot with numeric axis, for Vertical bar, you can use a NEEDLE plot instead of BARCHART.  With SAS 9.3 and higher, you can use a HIGHLOW plot.  This has a LINE and BAR version, for both vertical and horizontal orientations.  Just set the min value to zero.  For interval axis, width can be set in pixels.  This article shows usage of a HIGHLOW plot for making custom box plots.

Sami
Obsidian | Level 7

Dear Vince,

Thanks but your code was helpful but while i run with actual data , it back to same problem , for Format: i have duplicate value (please have a look below Bold marked unlined), it is overlapping again!

VALUE trtpf

   0.25=" 12 (4.67%)"

0.5=" 11 (8.03%)"
0.75=" 13 (23.31%)"
1.0=" 61 (  100%)"
1.25="  8 (5.69%)"
1.5=" 10 (26.61%)"
1.75="  8 (5.69%)"
2.0=" 51 (  100%)"

;

  QUIT;



data_null__
Jade | Level 19

does this modificantion to your modification of the OPs program work to obtain the desired result?

PROC template;
  
DEFINE STATGRAPH gtplot;
      BEGINGRAPH;
        
LAYOUT OVERLAY /
           
XAXISOPTS=(label=" " linearopts=(tickvaluesequence=(start=-5 end=0 increment=1)))
           
YAXISOPTS=(type=linear label="Treatment / Dose" linearopts=(tickvaluelist=(0.25 0.5 0.75 1.0 1.25 1.5 1.75 2.0) tickvalueformat=trtsdf.))
           
Y2AXISOPTS=(label="N(%)"
            discreteopts=
            (
           TICKdisplaylist=(
"12(4.67%)" "11(8.03%)" "13(23.31%)" "61(100%)" "8(5.69%)" "10(26.61%)" "8(5.69%)" "51(100%)" ))
               );
            BARCHART y=estimate x=paramn1 / GROUP=paramn BARWIDTH=0.4  NAME="bar" ORIENT=horizontal
              
FILLATTRS=(COLOR = LIGHTGREY) DATATRANSPARENCY=0.7 YAXIS=y2;
            SCATTERPLOT x=estimate  y=paramn  / GROUP=paramn XERRORLOWER=eval(estimate-standard)
              
ERRORBARATTRS=(thickness=1)
              
LEGENDLABEL="Results" NAME="SCATTER"
              
MARKERATTRS=(color=black size=0);
            BARCHART y=estimate x=paramn1 / GROUP=paramn BARWIDTH=0.4 PRIMARY=no NAME="bar1"
              
ORIENT=horizontal YAXIS=y2
              
FILLATTRS=(COLOR = LIGHTGREY) DATATRANSPARENCY=0.7;
        
ENDLAYOUT;
     
ENDGRAPH;
  
END;

  
source gtplot;
run;
PROC SGRENDER DATA=uni_api TEMPLATE="gtplot";
*format /* paramn trtsdf. */ paramn1 trtpf.;
RUN
;
Jay54
Meteorite | Level 14

Is this what you are looking for?

UNI_API.png

You have repeated values (pos, unc and neg) on the trtsdf format.  That causes those values to overlap. Also, adding a "hidden' bar chart on the Y axis (transparency=1) forces a character axis on Y so the Scatter gets forced to character too.

Sami
Obsidian | Level 7

Dear Sanjay,

First of all thanks for the answer. But i am not clear about your instruction.

I am using SAS 9,2 and If you can show me a dummy code on sample data it will be helpful. Again using needle plot, i have found no option to make it Horizontal. Again it will really help if you could show me some code .Again for Y2-Axis if duplicate values occurs, it is overlapping (please have a look below Bold marked on Format values):

-Finally i want to need some suggestion, this graph is really possible with SAS , if not then i could declare to Pharmaceutical Company that this sort of graph is not possible using SAS

VALUE trtpf

   0.25=" 12 (4.67%)"

0.5=" 11 (8.03%)"
0.75=" 13 (23.31%)"
1.0=" 61 (  100%)"
1.25="  8 (5.69%)"
1.5=" 10 (26.61%)"
1.75="  8 (5.69%)"

2.0=" 51 (  100%)"

;

Thanks a lot

Sami

Jay54
Meteorite | Level 14

You did not reply if the graph I included was what you are looking for.  If not, attach an image/sketch of the graph you would like to see.  Then we can determine if it is possible or not.  What I attached earlier can be created using SAS 9.2 with (mostly) your code.

Sami
Obsidian | Level 7

Hi Sanjay,

No really , because i have already explain why because in real data there are some duplicate values at Y2-AXIS like below (at points 1.25 and 1.75) then code failure:

VALUE trtpf
0.25=" 12 (4.67%)"
0.5=" 11 (8.03%)"
0.75=" 13 (23.31%)"
1.0=" 61 (  100%)"
1.25=" 8 (5.69%)"
1.5=" 10 (26.61%)"
1.75=" 8 (5.69%)"
2.0=" 51 (  100%)"
Vince28_Statcan
Quartz | Level 8

Hi DN,

I could not find any documentation about TICKDISPLAYLIST in SAS9.2 help and an online google search over :SAS gets a forum post dating from jan 2012 that you had initiated about this particular option.

However, when I try to run the code, SAS gets a critical error and shuts down. I suspect it is because it is an option that is only applicable within LINEAROPTS= and not DISCRETEOPTS= but that's merely my guess.

Or maybe it only is for the X-axis which is why I had asked if any other graph type could achieve similar box results naturally with numeric instead of category data. In particular, I also found this with TYPE= documentation for axis/overlay

DISCRETE
Use a DISCRETE axis if possible. The data for discrete axes can be character
or numeric. For an X or X2 axis, you can add a DISCRETEOPTS=(
) option list to customize this axis type. DISCRETEOPTS= is not supported on a Y
or Y2 axis.

Nevermind that, It was an issue with ods settings since Friday. It does indeed solve the issue DN. I am actually surprised to see it is supported despite the cute warning in the documentation that I did not strikethrough though. The only issue with this approach is that it is less generic than a format. That is, there would need to be a recompiled proc template each time the right-axis values change whereas a format-based approach does not. Sadly discrete axis seem to have very little support for layout overlay, let alone documented support!

----------

Sami,

The issue is that groups are formed according to the formated variables. My code example solved the problem if only the left axis had duplicate values because it applied formatting after axis creation. I can't seem to find any tool for discrete Y-axis that can support options like tickvalueformat or the like.

There aren't any format related tools like NOTSORTED + preloadfmt for, say, proc tabulate that could help you create 2 distinct grouping when they have identical formats. So really, the issue boils down to having formatted values overlap on a discrete Y-axis.

As per Sanjay's reply to my first post, if you could use the NEEDLE chart instead of BARCHART to create the horizontal bars exactly how you want it, then you could specify that even the Y2 axis is of TYPE=LINEAR, you could use the same LINEAROPTS= for TICKVALUEFORMAT and achieve the desired results as then the formats would only replace the values after axis creation. With this approach, you could have a generic template transferable accross different data (diff number of ticks, tick spacing etc and could forward the template with some documentation on how to set the data file to collegues for example).

If DN solution fulfills your requirements though, then there is no justification to learn how to mimic barchart using needles plot. Glad to see your issue was resolved.

Vince

Sami
Obsidian | Level 7

Vince,

As my problem is solved as per code proposed by DN, i am not going to try Needle plot at the moment.

I will remind this help from all of you.

Sami

Jay54
Meteorite | Level 14

Needle plots does not supoport orient=horizontal.  You are using SAS 9.2, so, maybe a vector plot could be made to work (with arrowheads). Vector plot supports only numeric variables.  With SAS 9.3, you can use the horizontal HighLow plot instead.

Sami
Obsidian | Level 7

The code given by data_null_ is worked. Thanks a lot.

But also cordial thanks to Sanjay and Vince.

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
  • 14 replies
  • 3416 views
  • 6 likes
  • 4 in conversation