Forest Plot with SAS 9.3

OK, I promise this is the last article on Forest Plots (at least for a while).

In the previous article on Subgrouped Forest Plot with Font Attributes, I discussed how to use bold text for subgroup headings.  I mentioned that increasing the font size would not work as it would misalign the subgroup values from the headings.

Clearly, the result shown in the link above is less than ideal, and I have not yet been able to come up with a better way to do this using SAS 9.2.   If you have a better solution, I am sure we all would be very interested to hear of it.

But with SAS 9.3, we can do better because we can use the new HighLowPlot statement.  This statement supports a LowLabel and/or HighLabel.  In this case, the label is drawn starting from the appropriate end of the plot line.  So, all the contortions needed for the MarkerCharacter solution with SAS 9.2 above can be avoided.

Forest Plot using SAS 9.3 HighLowPlot.  Here is the graph.  Click on it for a bigger view:

Note the following improvements in this graph:

  • The subgroup heading and values use the same font family as the rest of the columns.  It is not necessary to use a non-proportional font.
  • The subgroup headings use a bigger font size and bold weight.
  • The subgroup values are indented.
  • The error bars do not have serifs.

In this graph, we have used the HighLowPlot to draw the subgroup headings and values.   The actual drawing of the high low line itself is hidden by using line thickness of zero.  The other text strings are still drawn using ScatterPlot (with MarkerCharacter), but that too can be changed to HighLowPlot if we need left or right aligned strings.   The error bars for the Hazard Ratio are also drawn using the HighLowPlot.

With SAS9.3, the ScatterPlot itself also has a new option to draw DataLabels with DataLabelPosition of LEFT | RIGHT, etc.  So, we could have used that for these labels.  But there are some interesting interactions with axis offsets that need to be considered.  So, at this time, HighLowPlot is preferred.

GTL code snippet for the subgroup labels:

highlowplot y=obsid low=zero high=zero / highlabel=heading
    lineattrs=(thickness=0) labelattrs=(size=7 weight=bold);
highlowplot y=obsid low=zero high=one / highlabel=subgroup
    lineattrs=(thickness=0);

Forest Plot without horizontal bands:

Full SAS 9.3 Code:  ForestPlot_93

tags: Forest Plot, HighLabel, HighLowPlot, LowLabel

22 Comments

  1. Jeff Tomlinson
    Posted January 10, 2013 at 3:03 am | Permalink

    Hi Sanjay,

    At long last a SAS 9 way of making a forest plot with sub-group headers and indentation using a proportional font.

    Excellent!

    I've been banging my head against a wall trying to get a SG version of this for over a year. I had used PROC REPORT with included graphical elements each created individually, before settling on a much more straightforward PROC GPLOT/ANNOTATE solution.

    Now all I've got to do is to wait for SAS 9.3 to be available at my company.

    Kind regards
    -- Jeff

  2. Anish
    Posted January 31, 2013 at 9:51 pm | Permalink

    Hi Sanjay,
    Thank you very much for providing the code for the forest plot, its been incredibly useful! I was just wondering if there is any way to make the xaxis label of the plot dynamic so that it is centered around the Hazard ratio of 1 when the Low and High values change. Thanks.
    Kind regards,
    Anish

    • Sanjay Matange Sanjay Matange
      Posted February 1, 2013 at 12:50 am | Permalink

      At this time you could do this by turning off the display of the axis label and using two DRAWTEXT statement with DRAWSPACE of DATAVALUE and the appropriate anchor point. You could use the unicode symbol for "<-" and "->" for better results.

      DRAWTEXT textattrs=(size=7 weight=bold) "<---PCI Better" / drawspace=wallpercent widthunit=percent
      x=0 y=-4 width=100 anchor=topleft;
      DRAWTEXT textattrs=(size=7 weight=bold) "Medical Therapy Better--->" / drawspace=wallpercent widthunit=percent
      x=100 y=-4 width=100 anchor=topright;

      I will write up an example in the next blog post. With SAS 9.4, you will be able to use SGAnnotation.

      • Anish
        Posted May 6, 2013 at 2:33 am | Permalink

        Thanks a lot Sanjay!! Wish my brain worked half as well as yours :P . For one of my plots, I have a lower HR of 0.91 and an upper HR of 20 odd which makes the plot "squish" to the left. Would you be able to suggest a way to "unsquish" the plot? Thanks.
        Kind regards,
        Anish

  3. Khay
    Posted February 19, 2013 at 9:48 pm | Permalink

    Hi Sanjay,
    I want to create the following plots in SAS 9.3 - Funnel plot, Forest plot, ROC curve. I am doing Metaanalysis on diagnostic tests. THis is just what I need to graduate and I am running out of options as no one in my class knows how to do it. I did SAS in my Biostat class 2 years ago. My former prof has retired. A programmer offered his help but we both couldn't figure out the code. Could you please give me the correct code for the Forest Plot, Funnel Plot and ROC. My data includes author's name, laboratory test, sensitivity and specificity. Thank you so much for your help. -Khay

    • Sanjay Matange Sanjay Matange
      Posted February 28, 2013 at 3:06 pm | Permalink

      I have included code for many versions of the FOREST plot in previous posts in this blog. I am sure you can find one that is suitable to your need. Send me examples of the Funnel plot and ROC plot, with data, and I can help you.

  4. Juergen Loeffler
    Posted February 27, 2013 at 5:48 am | Permalink

    Re. Anish's question:
    I chose a similar but different approach: I created a second row in the lattice in which I added the two text labels in an entry statement, left and right aligned:
    entry textattrs=(family='Arial' size=7pt) halign=left "<---Control better" halign=right "Test better--->";
    But what I am wondering is if there is any way to get rid of the vertical white lines that separate the horizontal bands at the column borders? walldisplay=none does not seem to help.
    Kind regards,
    Juergen

  5. Khay
    Posted March 10, 2013 at 7:15 pm | Permalink

    Hi Sanjay,
    Thank you for your reply. Below is the sample data which I would like to create the Forest Plot and Funnel Plot in SAS 9.3. I found similar Forest plots from your previous posting but none has the same variables. I hope you can tell me the full code for this example. Thanks, Khay

    Author Assay Sensitivity Specificity
    Convert, M. et al RT-PCR Roche 1.00 0.855
    Chan, K.L. et al RT-PCR Roche 0.45 0.99
    Atkins, K.L. e al RT-PCR IDI GBS 0.868 0.952
    Davies, D.H. et al RT-PCR IDI GBS 0.939 0.959
    Uhl, J.R. et al RT-PCR -LC 1.00 0.969
    Uhl, J.R. et al RT-PCR -Compact 0.925 0.991
    Goodrich, J.S. et al RT-PCR- LC Roche 1.00 0.959
    Goodrich, J.S. et al RT-PCR -BD Cepheid 0.925 0.925

  6. David Carr
    Posted April 9, 2013 at 12:30 pm | Permalink

    Have implemented the above and got many laudits for an up-market graphic!
    However just read Breadhseet et al in Pharmaceutical Statistics (A course in constructing effective displays of data for pharmaceutical research personnel), and they call this a "grable", coz it is more table than graph!

  7. Natalie Bello
    Posted August 8, 2013 at 11:46 am | Permalink

    Thanks for the code. It works really well. I was wondering if there is some way to change the colors of the high low plot for the different subgroups. For example a red bar for females and a blue bar for males.

    • Sanjay Matange Sanjay Matange
      Posted August 8, 2013 at 12:58 pm | Permalink

      The HIGHLOW plot statemetn has a GROUP role. Assign your gender variable to it, and it should color the highlow plot line using the default GraphData1 and GraphData2 style elements. For LISTING style, that will be Blue and Red color shade. You can also use the DiscreteAttrMap to use the colors you want.

      Note, with SAS 9.4 (released last month) this will get even easier as you can use the new AXISTABLE to create the study name list which supports control of indentation and font attributes.

      • Natalie
        Posted August 9, 2013 at 11:54 am | Permalink

        Thanks Sanjay. The line colors changed perfectly, but the default style is now a dashed line for the grey and red, but solid blue. I've tried to change the linestyle to solid but keep getting errors. Any thoughts?

        Also I am plotting hazard ratios and wanted a log scale which I was able to do with the following change to the code:
        xaxisopts= ( type=log logopts=(base=e) label='Increasing Hazard----->'

        Thanks again for your help.

        • Sanjay Matange Sanjay Matange
          Posted August 9, 2013 at 12:03 pm | Permalink

          Set this option for the HighLow plot after the '/' LINEATTRS=(PATTERN=solid)

          • Natalie
            Posted August 9, 2013 at 12:28 pm | Permalink

            Perfect, thanks again.

  8. Reza
    Posted September 16, 2013 at 5:30 am | Permalink

    Dear Sanjay,
    Is it possible to add an option to this template for the central square to be plotted proportional to the sub-group size as commonly seen in meta-analysis ?
    Thank you for your articles !

    • Sanjay Matange Sanjay Matange
      Posted September 20, 2013 at 12:08 pm | Permalink

      Yes. With SAS 9.3, you can use the marker size role to set the sizes as a response variable.

  9. Anca Tilea
    Posted October 31, 2013 at 2:53 pm | Permalink

    Sanjay,
    Thank you for this blog! It has been my life-saver many times.
    I have a question: for the forestplot you show here, is it possible to move the x-axis info at the top of the plot?
    Is there some hidden magic in the xaxisopts options?

    Thank you in advance!
    Sincerely,
    Anca.

    • Sanjay Matange Sanjay Matange
      Posted October 31, 2013 at 3:04 pm | Permalink

      Yes, you can use X2AXIS instead, which is at the top of the graph. For the HIGHLOW and SCATTER plot statements in the 3rd column, associate each graph with the X2Axis using XAXIS=X2 option. Then, customize the X2Axis using the x2axisopts option on the Layout Overlay. You may need to adjust other things to get it looking right.

  10. Stephen
    Posted November 7, 2013 at 6:56 am | Permalink

    Hi Sanjay,

    The reference line at x=1 doesn't seem to quite line up with the axis on the bottom. Is there a way to fix this?

    Many thanks

    • Sanjay Matange Sanjay Matange
      Posted November 7, 2013 at 8:48 am | Permalink

      When mapping real world values to discrete pixels on the screen, a rounding error of 0.5 pixels can occur. So one item may round to 100 while another to 101. Subpixel rendering can sometimes fix this. For the graphs in the article, it seems very close, but discriminating eyes may disagree. Rendering at a higher resolution may help.

  11. Maca
    Posted March 4, 2014 at 3:58 pm | Permalink

    Hello Sanjay and everyone!

    I have found your blog extremely useful for my studies and work.

    I recently submitted a manuscript to a journal that included a forest plot generated from the code you provided here but the reviewers are asking us to shift the hazard ratio plots to the extreme right side of the graph. In other words, they want all text to be on the left side of the hazard ratio plots. I have tried unsuccessfully to manipulate your code to generate such a plot and was wondering if you could kindly assist. Your comments will be heartily appreciated.
    Kind regards,
    Maca

    • Maca
      Posted March 10, 2014 at 10:16 am | Permalink

      Hi Sanjay, just wanted to reach out to you once again for being extremely kind in assisting me with the above request. I am deeply appreciative for all your posts on this blog and the hands on assistance you provided me!

One Trackback

  1. [...] user, and I thought this would make for a good blog article.  Let us use the data in the article Forest Plot with SAS 9.3 to illustrate the possibilities.  We will use only the columns on the left and the hazard plot.  [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <p> <pre lang="" line="" escaped=""> <q cite=""> <strike> <strong>