Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Forest plot for subgroup analyses

    Hi Listers,

    I am running a series of subgroup analysis for specific demographics; all very exploratory so I would like to present the results as a Forest plot. I am using metan but the final plot could do with some tweaking. Here is an example using Stata available data.

    I would like to 1) remove the title on the top left corner "name and subgroup"; 2) indent the groups, indepent "47-54" and 55+" in relation to the word Age; 3) remove the 5 for the last row of the graph and just have it read All participants; 4) is there any way to specify the xscale as I could not get it to work.

    Any suggestions on how to achieve this in metan; or perhaps a better way?

    Code:
    * 1. Load data
    
    sysuse cancer, clear
    stset studytime, failure(died)
    
    recode drug (2/3=2)
    
    * 2. Initialize postfile
    tempname memhold
    tempfile results
    postfile `memhold' str20(name) str20(subgroup) hr lci uci using `results', replace
    
    tab age
    
    capture drop agecat
    egen agecat = cut(age), at(47, 55, 68)
    la de agecatlb 47 "47-54" 55 "55+", modify
    la val agecat agecatlb
    tab age agecat
    set seed 1245
    g sex = runiform()>=0.5
    tab sex
    la de sexlb 0 "Male" 1 "Female", modify
    la val sex sexlb
    
    * 3. Run Cox models for age
    levelsof agecat, local(a_levels)
    foreach a in `a_levels' {
       local aname : label (agecat) `a'
       stcox i.drug if agecat == `a'
       matrix b = r(table)
    
       post `memhold' ("Age") ("`aname'") (b[1,2]) (b[5,2]) (b[6,2])
    }
    
    * 4. Run Cox models for sex
    * Note: drug effect within each sex
    levelsof sex, local(s_levels)
    foreach s in `s_levels' {
        local sname : label (sex) `s'
        stcox i.drug if sex == `s'
        matrix b = r(table)
        post `memhold' ("Sex") ("`sname'") (b[1,2]) (b[5,2]) (b[6,2])
    }
    
    *5 - Cox for all participants
        stcox i.drug 
        matrix b = r(table)
            matrix list b
        post `memhold' ("ALL") (" ") (b[1,2]) (b[5,2]) (b[6,2])
    
    postclose `memhold'
    
    * 5. Load and Prep for Plotting
    use `results', clear
    
    metan hr lci uci, label(namevar=subgroup) by(name) ///
     nosub nooverall  xtitle("HR") effect(HR) xline(1)
    Click image for larger version

Name:	forest.jpg
Views:	2
Size:	19.4 KB
ID:	1784785
    Attached Files

  • #2
    Laura, a very simple solution would be to manually implement the changes via graph editor, record the changes and apply the command post-hoc via gr_edit.

    Comment


    • #3
      Hi Tiago Pereira thanks for your suggestions. I have tried but for some reason I am unable to select specific parts of the figure while in editing mode. Any suggestion?

      Comment


      • #4
        Originally posted by Laura Myles View Post
        I would like to 1) remove the title on the top left corner "name and subgroup"; 2) indent the groups, indepent "47-54" and 55+" in relation to the word Age; 3) remove the 5 for the last row of the graph and just have it read All participants; 4) is there any way to specify the xscale as I could not get it to work.


        I don't use metan, but since you provided a reproducible example and have not resolved your problem, I thought I would give it a try. Your first and last questions are covered in the documentation. To indent the labels, I modify the label names in the data.

        Code:
        * 1. Load data
        
        sysuse cancer, clear
        stset studytime, failure(died)
        
        recode drug (2/3=2)
        
        * 2. Initialize postfile
        tempname memhold
        tempfile results
        postfile `memhold' str20(name) str20(subgroup) hr lci uci using `results', replace
        
        tab age
        
        capture drop agecat
        egen agecat = cut(age), at(47, 55, 68)
        la de agecatlb 47 "47-54" 55 "55+", modify
        la val agecat agecatlb
        tab age agecat
        set seed 1245
        g sex = runiform()>=0.5
        tab sex
        la de sexlb 0 "Male" 1 "Female", modify
        la val sex sexlb
        
        * 3. Run Cox models for age
        levelsof agecat, local(a_levels)
        foreach a in `a_levels' {
           local aname : label (agecat) `a'
           stcox i.drug if agecat == `a'
           matrix b = r(table)
        
           post `memhold' ("Age") ("`aname'") (b[1,2]) (b[5,2]) (b[6,2])
        }
        
        * 4. Run Cox models for sex
        * Note: drug effect within each sex
        levelsof sex, local(s_levels)
        foreach s in `s_levels' {
            local sname : label (sex) `s'
            stcox i.drug if sex == `s'
            matrix b = r(table)
            post `memhold' ("Sex") ("`sname'") (b[1,2]) (b[5,2]) (b[6,2])
        }
        
        *5 - Cox for all participants
            stcox i.drug 
            matrix b = r(table)
                matrix list b
            post `memhold' ("ALL") (" ") (b[1,2]) (b[5,2]) (b[6,2])
        postclose `memhold'
        
        * 5. Load and Prep for Plotting
        use `results', clear
        
        replace subgroup= "`=uchar(28)'    `=uchar(28)'" + subgroup
        
        metan hr lci uci, label(namevar=subgroup) by(name) ///
         nosub nooverall  xtitle("HR") effect(HR) xline(1) ///
        labtitle("") forestplot(xlab(-.5 -.25 0 .25 .5 , force))

        Click image for larger version

Name:	Graph.png
Views:	1
Size:	30.0 KB
ID:	1784918



        Comment


        • #5
          Thank you so much Andrew Musau . I had not appreciated how to use the -forestplot- option to set the xlabel!

          Comment


          • #6
            Hi Laura Myles
            Apologies for not having seen your post earlier this year.
            In case it is still helpful, I am suggesting some code below. Note that I have plotted the HRs on the ratio scale, by first taking the natural logarithm and then using a log scale on the x-axis, with re-exponentiated values.
            Best wishes,
            David.

            Code:
            * 5. Load and Prep for Plotting
            use `results', clear
            gen lnhr=ln(hr)
            gen lnlci=ln(lci)
            gen lnuci=ln(uci)
            replace subgroup= "`=uchar(28)'    `=uchar(28)'" + subgroup
            metan lnhr lnlci lnuci, hr label(namevar=subgroup) labtitle("") by(name) nosub noov clear
            drop if _USE==0 & _BY==3
            replace _LABELS="All participants" if _USE==1 & _BY==3
            label variable _LABELS "Subgroup"
            replace _USE=5 if _USE==1 & _BY==3
            forestplot, hr nowt xlabel(.015625 "1/64" .125 "1/8" 1) favours(Favours Other # Favours Placebo, fp(.25))
            Click image for larger version

Name:	Laura Myles.png
Views:	1
Size:	58.5 KB
ID:	1786004

            Last edited by David Fisher; 05 May 2026, 03:37.

            Comment

            Working...
            X