Announcement

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

  • Updated version of -ipdmetan- on SSC, plus an -ipdover- example comparing effects with reference categories

    With thanks as ever to Kit Baum, an updated version of the ipdmetan package is now available for download from SSC (ssc install ipdmetan, or adoupdate ipdmetan if already installed). The package description from SSC is given below.

    This version (1.07) includes the following bug-fixes and additions:

    Bug fixes:
    - Fixed bug preventing use of nohet option
    - Fixed bug in implementation of "empirical Bayes" random-effects estimator
    - forestplot no longer uses char(160) to represent blank (non-breaking) space due to differences in character mapping across systems
    - Fixed bug in forestplot relating to varnames in lcols() and rcols() not having variable labels (the “must specify at least one of target or maxwidth” error)
    - Now correctly parses “...if varname=="label":lblname...” syntax

    Changes/additions:
    - Added cumulative IPD meta-analysis functionality
    - Added Kenward-Roger random-effects estimator, using an expression for the two-stage model derived from their paper (Biometrics 1997; 53: 983-97)
    - Improvements to aspect ratio and text sizing in forestplot, including saving important "dimensions" in r() and optionally saving them to a matrix to be applied to subsequent plots

    I am also happy to be able to draw your attention to the current issue of the Stata Journal, where you can find an article discussing ipdmetan and forestplot in more detail (Vol. 15, No. 2, pp. 369-96).

    One addition which I have not yet had the time to implement is the creation of forestplots of “prognostic” subgroup effects -- that is, where the outcome in each level of a subgroup is compared to a reference (baseline) category. The current implementation only allows the effect of a treatment variable to be plotted within each subgroup level. Since I have had so many requests for this functionality, below is an example of a “hack” which can be used to achieve this effect in the meantime. I hope this will prove useful.

    Many thanks,

    David.

    David Fisher
    Statistician
    MRC Clinical Trials Unit at UCL
    e-mail: [email protected]


    SSC DESCRIPTION

    A set of routines for conducting two-stage individual participant meta-analysis, and associated functionality. The main routine, ipdmetan, loops over a series of categories, fits the desired model to the data within each, and generates pooled effects, heterogeneity statistics etc, as appropriate. Various random-effects subroutines are available, and aggregate data may be included from an external dataset. The routine forestplot is a stand-alone, re-written and extended version of the graphics routine within the existing SSC command metan. ipdover allows ipdmetan to be used outside of the meta-analytic context, for example for creating a forestplot of a series of (potentially overlapping) subgroups within a single study. admetan allows ipdmetan to be run on aggregate data only, if currently in memory, as a direct alternative to metan. Finally, petometan is an extension of the built-in command sts test for performing meta-analysis on binary or time-to-event data using the Peto (log-rank) method.


    *********************

    EXAMPLE CODE FOR COMPARING OUTCOMES WITHIN SUBGROUPS TO A REFERENCE CATEGORY

    Code:
    * Load data
    use "http://fmwww.bc.edu/repec/bocode/i/ipdmetan_example", clear
    stset tcens, fail(fail)
     
    * Generate indicator vars for each level of "stage"
    qui tab stage, gen(stage)
     
    * Run -ipdover- repeatedly to save the different parts we need
    * (N.B. the first run uses "stcox trt" simply to create the desired structure in the saved dataset; the actual coefficients are not ultimately used)
    ipdover, over(stage) over(trialid) hr nosubgroup nooverall nograph saving(stage_all, replace) : stcox trt
    ipdover, over(trialid) hr nooverall nograph poolvar(2.stage) saving(stage2, replace) rcols((sum) stage1 stage2) : stcox i.stage
    ipdover, over(trialid) hr nooverall nograph poolvar(3.stage) saving(stage3, replace) rcols((sum) stage3) : stcox i.stage
     
    * Now load the saved datasets and assemble
    use stage_all, clear
    drop if _USE==1
    append using stage2 stage2 stage3, gen(dataid)
     
    * Sort out arrangement of trials and covariate levels
    replace _BY = _LEVEL if dataid > 0
    replace _LEVEL = dataid if dataid > 0
    replace _LABELS = "Stage I" if _LEVEL == 1
    replace _LABELS = "Stage II" if _LEVEL == 2
    replace _LABELS = "Stage III" if _LEVEL == 3
     
    * Sort out numbers of patients
    replace _NN = stage1 if dataid == 1
    replace _NN = stage2 if dataid == 2
    replace _NN = stage3 if dataid == 3
    drop stage1 stage2 stage3
     
    * Replace effect size with null in reference category
    * (N.B. I couldn't do this directly because -ipdover- would complain that there was "no data")
    replace _ES = 0 if dataid == 1
    replace _seES = 0 if dataid == 1
    replace _LCI = 0 if dataid == 1
    replace _UCI = 0 if dataid == 1
     
    * Manually generate "effect size" string, including for reference category
    gen str estText = string(exp(_ES), "%10.2f") + " (" + string(exp(_LCI), "%10.2f") + ", " + string(exp(_UCI), "%10.2f") + ")" if _USE == 1
    replace estText = "1.00 (Reference)" if _LEVEL == 1
    label var estText "Haz. ratio (95% CI)"
     
    * Sort data and produce forestplot
    sort _BY _USE _LEVEL
    forestplot, hr nostat nowt rcols(estText _NN)
    Click image for larger version

Name:	forestplot july2015.png
Views:	1
Size:	38.5 KB
ID:	1301388

  • #2
    Updated version of -ipdmetan- on SSC; now has nearly all the functionality of -metan-


    Happy Friday, Statalisters!

    With thanks as ever to Kit Baum, an update of the ipdmetan package is now available for download from SSC (ssc install ipdmetan, or adoupdate ipdmetan if already installed). The package description from SSC is given below.


    This is such a major update that I've up-versioned the package to v2.0. There are various improvements and a few minor bug fixes; but the bulk of what's new relates to incorporating the "four-element" and "six-element" syntaxes of metan into both admetan and ipdmetan/ipdover. In other words, admetan can now handle cell-count data (#a #b #c #d) and mean difference data (n, mean, SD by treatment arm) and can use methods such as Mantel-Haenszel and Standardised Mean Differences. Furthermore, ipdmetan/ipdover can also now handle data of this type, using an alternative syntax which uses collapse to form the appropriate aggregated data. Overall, the vast majority of metan functionality is now replicated within admetan, making this effectively the first update to the ever-popular metan package since September 2010. (In particular, admetan is far more likely to run successfully in resource-limited environments than metan; I've seen a couple of examples where users have hit the upper limit of permitted variables due to metan being inefficient with tempvars.)

    Sadly, the time spent doing this has meant that I've still not gotten around to implementing some previously-requested functionalities, such as forest plots of prognostic subgroup effects and better continuity-correction options. However, now that this structural update is complete, I'll aim to get some of these done fairly soon.


    Other notable additions/improvements:

    - cumulative and "influence" meta-analysis, where the latter removes one study at a time from the overall calculation to assess that study's influence
    - predictive distributions; this has long been available in metan but is now also available in ipdmetan/admetan
    - more control over formatting in forest plots, e.g. x-axis leading zeros, string justification, buffering between data columns, line breaks in column headings.

    The main omissions in admetan functionality relative to metan are the first(), firststats(), second() and secondstats() options which allowed, for instance, both fixed- and random-effects estimates to be shown in the same forest plot. I will consider adding these in a future update, but note that the way forestplot is set up means that, with a bit of additional work, these features and many others may be recreated by saving, loading and manipulating the forest plot dataset (or "results set"). The admetan help file, which recreates the examples given in the metan help file, demonstrates one way to recreate the functionality of first(), firststats(), second() and secondstats().


    Lastly, if I may, I will take the opportunity to promote my recent-published article in BMJ Research Methods & Reporting on the subject of treatment-covariate interactions and subgroups, and why a "within-trials only" or "deft" approach is preferable. One way of implementing this approach is to use ipdmetan with the interaction option.


    Many thanks,

    David.



    ============================================

    SSC DESCRIPTION

    IPDMETAN: A set of routines for conducting two-stage individual participant meta-analysis, aggregate (summary) data meta-analysis, and for creating high-quality forest plots. The two-stage routine, ipdmetan, loops over a series of categories, fits the desired model to the data within each, and generates pooled effects, heterogeneity statistics etc, as appropriate; aggregate data may also be included from an external dataset. The aggregate-data routine, admetan, carries over much of the functionality of the existing SSC command metan, but with a wider range of random-effects and variance-correction models. There is also an “immediate” version, admetani. The routine forestplot is a stand-alone, re-written and extended version of the graphics routine within the existing SSC command metan. ipdover allows ipdmetan to be used outside of the meta-analytic context, for example for creating a forest plot of a series of (potentially overlapping) subgroups within a single study.
    Last edited by David Fisher; 12 May 2017, 02:55. Reason: added reference to recent article

    Comment


    • #3
      Hi Alexander,

      Thanks for your message; sorry you're having trouble.

      Does the error message say "Error in ipdmetan" or similar? If so, could you tell me the complete error message? (that is, everything in red).

      Also, are you familiar with Stata's debugging commands "set trace on" and "set tracedepth #"? If so, could you copy-and-paste a few (say 10) of the lines immediately preceding the error, so I can see exactly where it occurred?

      Is there anything "extreme" about the calc_2 variable? e.g. does it contain a very small subgroup? Does it vary within the observations set up for survival analysis (i.e. stset)?

      Thanks,

      David.

      Comment


      • #4
        Updated version of -ipdmetan- on SSC

        With thanks as ever to Kit Baum, version 2.1 of the ipdmetan package is now available for download from SSC (ssc install ipdmetan, or adoupdate ipdmetan if already installed).

        A reminder that admetan (part of this package) now does pretty much everything metan does, plus a whole lot more!

        This is mostly a bug-fixing update, ironing out some problems which slipped through the net in v2.0 (including the issue raised by Alexander Rodriguez in previous posts in this thread).

        Just to note that if you are, or have been, making use of: (a) the "sensitivity" random-effects model with user-specified I-squared; or (b) the returned statistic r(Isq), that admetan now takes in and returns I-squared values on the percentage scale; that is, values between 0 and 100. This mirrors the behaviour of metan and metaan. Apologies for any confusion this may cause.

        Finally: Just to mention admetani, which is a new quasi-immediate version of admetan which works on directly-inputted values or existing matrices. The intended use cases are: (a) performing quick-and-dirty meta-analyses of a small number of studies whose results are to hand but which are not stored in the dataset in memory; and (b) performing meta-analyses based on beta-coefficients & covariance matrices from previously-run regression commands or from margins (as such, there may be some overlap with commands such as marginsplot and coefplot, but I've not explored these possibilities in detail yet).

        Many thanks,

        David.



        Comment


        • #5
          Lastly, if I may, I will take the opportunity to promote my recent-published article in BMJ Research Methods & Reporting on the subject of treatment-covariate interactions and subgroups, and why a "within-trials only" or "deft" approach is preferable. One way of implementing this approach is to use ipdmetan with the interaction option.
          Dear David,

          Can you provide an example how to implement "def" approach using ipdmetan and generate plots like Fig 2 in this published article?

          Best,

          Shixiang
          Last edited by Shixiang Wang; 04 Jul 2018, 21:06.

          Comment


          • #6
            For the benefit of Forum readers: Shixiang has emailed me directly with a sample of his data, and I have given some help.
            However, I agree that the BMJ paper does not make it clear how the plots were generated, especially in the context of aggregate data. I shall aim to include an example of this sort in the documentation of the next update of admetan/ipdmetan.
            Thanks,
            David.


            Comment


            • #7
              Hi again,

              The next of update of admetan / ipdmetan is now available; see https://www.statalist.org/forums/for...alysis-command. I haven’t included a BMJ-style example (as requested by Shixiang Wang above) in the command documentation, as I’d already spent too long on the code and wanted to make it available. So instead, here is a “bonus” example.

              Data are taken from Analysis 8.2 of the Cochrane review “Services for reducing duration of hospital care for acute stroke patients” (Fearon et al 2012), available at: https://www.cochranelibrary.com/cdsr...0443.pub3/full (as this is available Open Access, I’m assuming it’s ok to recreate it here, but do let me know if otherwise!)

              Code:
              * Example generated by -dataex-. To install: ssc install dataex
              clear
              input byte(trial carer) int n1 float(mean1 sd1) int n0 float(mean0 sd0)
               1 1  24 19.5 20.21  25 37.4 25.35
               4 1  38 44.4 25.48  38 42.8 45.05
               7 1 116 30.7 32.26 101 43.1    44
               8 1   6 25.6 33.64   7   56 43.12
               9 1  58  9.8  5.32  56   12  7.07
              10 1  24 18.2 22.05  22 33.8 36.05
              11 1  18 19.7 13.75  15 23.4  14.6
              12 1  30 12.6  6.59  27 33.5 30.97
              14 1  20 22.2  34.1  11 28.3  50.4
               1 2  18 22.7 21.44  19 34.1 22.73
               4 2  21 37.5 32.89  16 65.4 48.97
               7 2  49 37.9 34.68  62 38.4 32.88
               8 2   4 48.5 42.79   4   15  7.87
              10 2  20 25.8 27.33  20 33.9 35.21
              11 2  24 31.5 18.26  25 40.1 23.26
              12 2  12 15.9  7.48  14   21   9.8
              14 2  11 25.9  23.8  15 32.9  39.5
              end
              label values trial TRIAL
              label def TRIAL 1 "Adelaide 2000", modify
              label def TRIAL 4 "Belfast 2004", modify
              label def TRIAL 7 "London 1999", modify
              label def TRIAL 8 "Manchester 2001", modify
              label def TRIAL 9 "Montreal 2000", modify
              label def TRIAL 10 "Newcastle 1997", modify
              label def TRIAL 11 "Oslo 2000", modify
              label def TRIAL 12 "Stockholm 1998", modify
              label def TRIAL 14 "Trondheim 2004", modify
              label values carer CARER
              label def CARER 1 "Carer present", modify
              label def CARER 2 "No carer", modify
              label var trial "Trial name"
              label var carer "subgroup"

              Our first task is to create a dummy observation representing the missing “No carer” category for the Montreal trial:
              Code:
              expand 2 if trial=="Montreal 2000":TRIAL
              replace carer = 2 in L
              foreach v of varlist n1-sd0 {
                   replace `v' = . in L
              }
              sort carer trial

              Now we can proceed to create the left-hand plot of Figure 2 of the BMJ paper, saving the “dimensions” in a matrix to be applied later to the right-hand plot:
              Code:
              graph drop _all
              admetan n1 mean1 sd1 n0 mean0 sd0, wmd ovwt by(trial) study(carer) nooverall nosubgroup keepall keeporder ///
              forestplot(nostats nowt favours("Favours" "ESD" " " # "Favours" "no ESD" " ") xlabel(-50 0 50, force) astext(35) savedims(A) name(fig2a))

              Creating the right-hand plot is a little trickier. We begin by analysing the interactions. For each trial, the interaction is formed from two effect estimates, one from each subgroup. We could use generate and replace to form the difference in effect sizes and the sum of their variances; or we could take a short-cut using ipdmetan and vwls (see help vwls to see what this is doing):
              Code:
              ipdmetan, study(trial) keepall keeporder effect("Diff. in mean diffs.") saving(fig2b, replace) nogr ///
                   : vwls _ES ib1.carer, sd(_seES)

              Next, we load the “forestplot results set” and use expand to pad out the data to match the structure of the left-hand plot. (This can be tricky to envisage, and may involve some trial-and-error.) Finally, we create the right-hand plot, applying the same “dimensions” as in the left-hand plot:
              Code:
              use fig2b, clear
              gen toexpand = 1 + 3*inlist(_USE, 1, 2) + 2*(_USE==5)      // 2 new obs per trial, plus 1 for overall
              local oldN = _N
              expand toexpand, gen(expand)
              replace _USE = 6 * (1 - (_n > `oldN' & !mod(_n, 3))) if expand
              replace _WT = . if _USE==0
              sort _STUDY _USE
              forestplot, useopts interaction usedims(A) nonames ///
                   favours("Favours greater effect" "of ESD with" "carer present" # "Favours greater effect" "of ESD with" "no carer present", fp(40)) ///
                   xlabel(-50 0 50, force) name(fig2b)

              Finally, we use graph combine:
              Code:
              graph combine fig2a fig2b, imargin(zero) xsize(4)

              I hope this is useful to the community.

              Thanks,

              David.

              Comment


              • #8
                This thread is rather old, but I can't find a more recent one where I've announced any updates for ipdmetan specifically (i.e. not bundled together with metan), so here goes:


                With thanks as ever to Kit Baum, an updated version of the ipdmetan package is now available for download from SSC (ssc install ipdmetan, or adoupdate ipdmetan if already installed). The package description from SSC is given below.

                This version (4.03) includes various minor bug fixes, and changes so as to work more effectively with the latest version of metan.

                The biggest additionis the ability to use prefix commands, and in particular mi estimate, post. I myself am not an expert in the field of MI, so would welcome any comments or feedback. To clarify: the imputation procedure is applied independently to each set of trial data, and the relevant estimate of effect (+ SE) is retrieved. The meta-analysis pooling and presentation then proceeds as for any other two-stage analysis.

                Note that you must use the post option to mi estimate, or ipdmetan will be unable to retrieve the relevant effect estimate.

                Many thanks,

                David.

                Comment

                Working...
                X