Announcement

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

  • transformed margins (and marginsplot)?

    The -margins- command uses a normal approximation for computing confidence intervals (which is fine for many situations), but in case of non-linear models (such as logistic regression) the bounds of the confidence intervals can become lower 0 or larger 1. I would like to have logit transformed confidence intervals for predictions (similarly as with -proportions-).

    Jeff Pitblado provided the .ado -transform_margins- (available via -install transform_margins, from(http://www.stata.com/users/jpitblado)- ) that allows this (and by the way can easily transform proportions into percentages), see https://stats.stackexchange.com/ques...rgins-in-stata .

    This works well as long as I have only one predictor: In that case the confidence intervals using -transform_margins- are comparatively close to the confidence intervals produced by -proportions- and -ci proportions-:

    Example:
    Code:
    . install transform_margins, from(http://www.stata.com/users/jpitblado)
    
    . sysuse auto
    (1978 automobile data)
    
    . recode rep78 (1/3=0) (4/5=1), gen(rep78_d)
    (69 differences between rep78 and rep78_d)
    
    .
    . qui logit rep78_d i.foreign
    
    . margins foreign
    
    Adjusted predictions                                        Number of obs = 69
    Model VCE: OIM
    
    Expression: Pr(rep78_d), predict()
    
    ------------------------------------------------------------------------------
                 |            Delta-method
                 |     Margin   std. err.      z    P>|z|     [95% conf. interval]
    -------------+----------------------------------------------------------------
         foreign |
       Domestic  |   .2291667   .0606646     3.78   0.000     .1102662    .3480671
        Foreign  |   .8571429   .0763604    11.22   0.000     .7074793    1.006806
    ------------------------------------------------------------------------------
    
    .
    . qui margins foreign, predict(xb)
    
    . transform_margins 100*invlogit(@)
    ----------------------------------------------
                 |         b         ll         ul
    -------------+--------------------------------
         foreign |
       Domestic  |  22.91667   13.16886   36.82027
        Foreign  |  85.71429   63.86495   95.32031
    ----------------------------------------------
    
    .
    . proportion rep78_d, over(foreign)
    
    Proportion estimation                          Number of obs = 69
    
    -----------------------------------------------------------------
                    |                                   Logit
                    | Proportion   Std. err.     [95% conf. interval]
    ----------------+------------------------------------------------
    rep78_d@foreign |
        0 Domestic  |   .7708333   .0606646      .6289563    .8696994
         0 Foreign  |   .1428571   .0763604      .0458191    .3664757
        1 Domestic  |   .2291667   .0606646      .1303006    .3710437
         1 Foreign  |   .8571429   .0763604      .6335243    .9541809
    -----------------------------------------------------------------
    
    . ci proportions rep78_d if foreign==0, agresti
    
                                                                Agresti–Coull    
        Variable |        Obs  Proportion    Std. err.       [95% conf. interval]
    -------------+---------------------------------------------------------------
         rep78_d |         48    .2291667    .0606646         .131484    .3669869
    
    . ci proportions rep78_d if foreign==1, agresti
    
                                                                Agresti–Coull    
        Variable |        Obs  Proportion    Std. err.       [95% conf. interval]
    -------------+---------------------------------------------------------------
         rep78_d |         21    .8571429    .0763604        .6451855    .9586438
    
    . ci proportions rep78_d if foreign==1, wilson
    
                                                                    Wilson       
        Variable |        Obs  Proportion    Std. err.       [95% conf. interval]
    -------------+---------------------------------------------------------------
         rep78_d |         21    .8571429    .0763604        .6536394    .9501899
    However, this methods fails if I add additional predictors to the model, in this case the predicted proportions using -margins- and applying -transform_margins- will differ:
    Code:
    . qui logit rep78_d i.foreign mpg
    
    . margins foreign
    
    Predictive margins                                          Number of obs = 69
    Model VCE: OIM
    
    Expression: Pr(rep78_d), predict()
    
    ------------------------------------------------------------------------------
                 |            Delta-method
                 |     Margin   std. err.      z    P>|z|     [95% conf. interval]
    -------------+----------------------------------------------------------------
         foreign |
       Domestic  |   .2547349   .0670069     3.80   0.000     .1234038     .386066
        Foreign  |   .8189145    .096934     8.45   0.000     .6289273    1.008902
    ------------------------------------------------------------------------------
    
    .
    . qui margins foreign, predict(xb)
    
    . transform_margins 100*invlogit(@)
    ----------------------------------------------
                 |         b         ll         ul
    -------------+--------------------------------
         foreign |
       Domestic  |    24.694   14.12082   39.53907
        Foreign  |  82.70865   57.52516   94.41136
    ----------------------------------------------
    a) Is there any way to solve this problem (or is the difference of the predicted proportions/percentages acceptable)?

    b) If this is possible, is there an easy way (such as with -marginsplot-) to plot the predicted proportions (or percentages) with confidence intervals after having transformed the margins?

  • #2
    -transform_margin- is setting mpg equal to the mean. Compare
    Code:
    . sysuse auto,clear
    (1978 automobile data)
    
    . recode rep78 (1/3=0) (4/5=1), gen(rep78_d)
    (69 differences between rep78 and rep78_d)
    
    . qui logit rep78_d i.fore mpg
    
    . margins i.foreign, atmeans
    
    Adjusted predictions                                        Number of obs = 69
    Model VCE: OIM
    
    Expression: Pr(rep78_d), predict()
    At: 0.foreign = .6956522 (mean)
        1.foreign = .3043478 (mean)
        mpg       = 21.28986 (mean)
    
    ------------------------------------------------------------------------------
                 |            Delta-method
                 |     Margin   std. err.      z    P>|z|     [95% conf. interval]
    -------------+----------------------------------------------------------------
         foreign |
       Domestic  |     .24694   .0654946     3.77   0.000     .1185729    .3753071
        Foreign  |   .8270865   .0920714     8.98   0.000     .6466299    1.007543
    ------------------------------------------------------------------------------
    
    . qui margins i.fore, predict(xb)  atmeans
    
    . transform_margins 100*invlogit(@)
    ----------------------------------------------
                 |         b         ll         ul
    -------------+--------------------------------
         foreign |
       Domestic  |    24.694   14.12082   39.53907
        Foreign  |  82.70865   57.52516   94.41136
    ----------------------------------------------
    -transform_margin- does have an option to save the matrix of results. Or you could extract them from r(table) and transform:
    Code:
    capture frame change default
    capture frame drop results
    
    sysuse auto,clear
    recode rep78 (1/3=0) (4/5=1), gen(rep78_d)
    qui logit rep78_d i.fore mpg
    qui margins i.foreign, atmeans
    marginsplot, name(gr1,replace)
    qui margins i.fore, predict(xb)  atmeans
    matrix t = r(table)
    
    frame create results foreign b  ul ll 
    frame post results (0) (t[1,1]) (t[5,1]) (t[6,1])
    frame post results (1) (t[1,2]) (t[5,2]) (t[6,2])
    frame change results
    
    foreach i in  b ul ll {
        replace `i' = invlogit(`i')
    }
    list 
    
    twoway connected b foreign , lc(black) mc(black)  || rcap ul ll foreign , lc(black)  /// 
        || , xlabel(0 "Domestic" 1 "Foreign") xtitle("") legend(off) ytitle(Pr(rep78_d))
    frame change default

    Comment


    • #3
      Excellent! Thank you!

      Comment


      • #4
        George Hoffman : In your post https://www.statalist.org/forums/for...06#post1736206 (06 Dec 2023) you state:
        there is an undocumented command _coef_table with undocumented citype(logit) option that will produce the appropriately-bounded CI's after a margins command.
        _coef_table, citype(logit) cititle(Logistic)
        I tried to use _coef_table, citype(logit) after margins (as in #1 or #2) but simply got the results table of the logit command, not "appropriately-bounded CI's". Can you give us an example?
        Last edited by Dirk Enzmann; 16 Feb 2024, 20:02.

        Comment


        • #5
          if you add citype(logit) to the margins command, it will produce CI's bounded by (0,1). however, marginsplot following that margins command does not plot the bounded margins. i had poointed out this limitation in the wishlist thread and suggested an corresponding option for marginsplot. to date, i do not think there is a solution. i hope this is clear - and let m eknow if you find a solution!
          thx

          Comment

          Working...
          X