Dear Forum,

In the context of factor variables in a logit model (calculated using Stata 15.1), I'm trying to better understand the differences between the ratio of predictive margins and the semi-elasticity calculated for the same model and the same group contrast.

Background: After calculating both average marginal effects (margins, dydx) and average semi-elasticities (margins, eydx) for a factor variable of interest in my logit model, I presented the predictive margins for the groups of the factor variable graphically. To facilitate interpretation of these graphs, I also wanted to add the relative differences between groups of the factor in terms of predictive margins. In the context of this exercise, l would have expected that the relative differences in predictive margins should be more or less the same as the semi-elasticity for the same contrast. However, I noticed that this seems to be only sometimes the case, and although the differences are rather small for my data, I wanted to better understand the differences between the two.

Here's my question: My interpretation is that the ratio of predictive margins and the semi-elasticity are exactly the same if the elasticity is a small ( lower than 1?), whereas the semi-elasticity (eydx) may deviate rather substantially if the relative difference is larger. Is this because the ratio of marginal predictions relies basically on the difference of two logged averages, whereas the average semi-elasticity first logarithmizes and only then averages...? It seems to me that the differences between the two can be quite substantial, so I was wondering what to make of that (see also the example below), but perhaps I'm missing something more basic.

Here's an example, where I calculate the relative difference between predictive margins for factor foreign and compare it to 1) results from "margins, eydx" and 2) the same semi-elasticity calculated by hand using "predict":

Code:
sysuse auto, clear
recode price (min/7000=0) (7000/max=1),gen(expensive)
gen foreign_orig=foreign // save the original values of "foreign" in "foreign_orig"
local xvars1 i.foreign
local xvars2 i.foreign c.weight c.length // the adjusted model produces a greater ratio for the groups of "foreign"
local version  unadj adj

forvalues i=1/2 {
    local vers: word `i' of `version'
    
* average semi-elasticity (eydx) using margins
    logit expensive `xvars`i''
    estpost margins, eydx(foreign) //6.302874 (unadj: 0.3493756)
    est sto eydx_`vers'
    
    
 * average semi-elasticity by hand using predict
    logit expensive `xvars`i''
    replace foreign=0
    predict yhat_x0_`vers' , pr
    sum yhat_x0_`vers'

    replace foreign=1
    predict yhat_x1_`vers', pr
    sum yhat_x1_`vers'

    gen semiel_`vers'=ln(yhat_x1_`vers')-ln(yhat_x0_`vers')
    sum semiel_`vers'
    scalar meansemiel_`vers'=exp(r(mean))
    
   * ratio of marginal predictions (using margins)
    replace foreign=foreign_orig // reset foreign to original values
    logit expensive i.foreign `xvars`i''
    estpost margins foreign

    scalar reldiffmargins_`vers'=exp(log(_b[1.foreign])-log(_b[0.foreign]))
    scalar reldiffmargins2_`vers'=_b[1.foreign]/_b[0.foreign] // added just to check it's the same as the above
}   

*** comparing results between models:

*unadjusted model: semi-elasticity = ratio of margins
est tab eydx_unadj, eform //   1.4181818
di meansemiel_unadj // 1.4181819
di reldiffmargins_unadj //  1.4181818

*adjusted model: semi-elasticity != ratio of margins
est tab eydx_adj, eform //    546.13934
di meansemiel_adj // 546.13932
di reldiffmargins_adj //  4.9585363

Any comments, corrections or advice on how to think of these issue in terms of which one is the more meaningful/useful comparison is greatly appreciated.

Best,
Irene