Usage and examples

Every form of metest, from the help file, with output

metest [exp] [, options]
metest list, pwcompare [options]

exp refers to marginal effects by the # shown in the mecompare table, or by their coefficient names, combined with +, -, *, /, parentheses, or =. A bare number is always an ME number; a literal number is written with a leading # (#2 is the number two, 2 is the second marginal effect). Non-whole numbers are always literals. list lists the marginal effects to compare pairwise, by ME # (1 2 3), as a range (1/3), or by name.

The examples below are the ones in the help file, run in order.

Setup: fit and store two models, then calculate the marginal effects

sysuse nlsw88, clear
(NLSW, 1988 extract)
drop if missing(union, married, age, race, wage)
(368 observations deleted)
logit union i.married age i.race, vce(robust)
Iteration 0:  Log pseudolikelihood = -1046.6242  
Iteration 1:  Log pseudolikelihood = -1038.8701  
Iteration 2:  Log pseudolikelihood = -1038.8354  
Iteration 3:  Log pseudolikelihood = -1038.8354  

Logistic regression                                     Number of obs =  1,878
                                                        Wald chi2(4)  =  15.82
                                                        Prob > chi2   = 0.0033
Log pseudolikelihood = -1038.8354                       Pseudo R2     = 0.0074

------------------------------------------------------------------------------
             |               Robust
       union | Coefficient  std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
     married |
    Married  |     -0.176      0.114   -1.549   0.121       -0.399       0.047
         age |      0.011      0.018    0.637   0.524       -0.024       0.046
             |
        race |
      Black  |      0.372      0.120    3.093   0.002        0.136       0.608
      Other  |      0.553      0.439    1.260   0.208       -0.307       1.412
             |
       _cons |     -1.570      0.711   -2.207   0.027       -2.964      -0.176
------------------------------------------------------------------------------
est store m1
logit union i.married age i.race wage, vce(robust)
Iteration 0:  Log pseudolikelihood = -1046.6242  
Iteration 1:  Log pseudolikelihood = -1016.7478  
Iteration 2:  Log pseudolikelihood = -1016.3517  
Iteration 3:  Log pseudolikelihood = -1016.3517  

Logistic regression                                     Number of obs =  1,878
                                                        Wald chi2(5)  =  59.14
                                                        Prob > chi2   = 0.0000
Log pseudolikelihood = -1016.3517                       Pseudo R2     = 0.0289

------------------------------------------------------------------------------
             |               Robust
       union | Coefficient  std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
     married |
    Married  |     -0.119      0.116   -1.029   0.303       -0.345       0.108
         age |      0.013      0.018    0.705   0.481       -0.023       0.048
             |
        race |
      Black  |      0.492      0.122    4.025   0.000        0.252       0.732
      Other  |      0.483      0.482    1.002   0.316       -0.462       1.427
             |
        wage |      0.084      0.012    6.819   0.000        0.060       0.108
       _cons |     -2.356      0.739   -3.189   0.001       -3.803      -0.908
------------------------------------------------------------------------------
est store m2
mecompare age i.married, models(m1 m2)
Predicting: Pr(union)
Marginal effects and cross-model differences (N_m1=1878) (N_m2=1878)

                                 |  ME #   Estimate  Robust SE      P>|z|
---------------------------------+---------------------------------------
age + 1 (centered)               |                                       
                              m1 |     1      0.002      0.003      0.524
                              m2 |     2      0.002      0.003      0.480
                      Difference |     3     -0.000      0.001      0.689
---------------------------------+---------------------------------------
married                          |                                       
            Married - Single     |                                       
                              m1 |     4     -0.033      0.021      0.126
                              m2 |     5     -0.021      0.021      0.308
                      Difference |     6     -0.011      0.004      0.003

A single marginal effect, by number and by name

metest 1
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                              m1 |     0.002      0.003      0.524 
metest age:m1
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                              m1 |     0.002      0.003      0.524 

The cross-model difference, three equivalent ways

Note that mecompare already reports it as ME 3.

metest 1 - 2
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                         m1 - m2 |    -0.000      0.001      0.689 
metest 3
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                      Difference |    -0.000      0.001      0.689 
metest _b[age:m1] - _b[age:m2]
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                         m1 - m2 |    -0.000      0.001      0.689 

A ratio and an average

Note the # on the divisor of the average, which makes it the number two rather than ME 2.

metest 1 / 2
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                         m1 / m2 |     0.910      0.254      0.000 
metest (1 + 2) / #2
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                   (m1 + m2) / 2 |     0.002      0.003      0.501 

Scaling by a literal value

10 times the effect for a change in age:

metest 1 * #10
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                         m1 * 10 |     0.021      0.033      0.524 

Equality tests, including a joint test and two constraints at once

metest 1 = 2
Tests of equality

                                 |      chi2         df     pvalue 
---------------------------------+--------------------------------
age                              |                                
                         m1 = m2 |     0.161      1.000      0.689 
metest 1 = 2 = 3
Tests of equality

                                 |      chi2         df     pvalue 
---------------------------------+--------------------------------
age                              |                                
            m1 = m2 = Difference |     0.645      2.000      0.725 
metest (1 = 2) (4 = 5)
Tests of equality

                                 |      chi2         df     pvalue 
---------------------------------+--------------------------------
  (age~1 = age~2)(mar~1 = mar~2) |     9.216      2.000      0.010 

Building up a table

Estimates and equality tests are shown in separate tables.

metest, clear
metest 1 - 2
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                         m1 - m2 |    -0.000      0.001      0.689 
metest 4 - 5, add
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                         m1 - m2 |    -0.000      0.001      0.689 
---------------------------------+--------------------------------
married                          |                                
                         m1 - m2 |    -0.011      0.004      0.003 
metest 1 = 2, add
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                         m1 - m2 |    -0.000      0.001      0.689 
---------------------------------+--------------------------------
married                          |                                
                         m1 - m2 |    -0.011      0.004      0.003 

Tests of equality

                                 |      chi2         df     pvalue 
---------------------------------+--------------------------------
age                              |                                
                         m1 = m2 |     0.161      1.000      0.689 

Redisplayed at any point, with a title, by typing metest on its own:

metest, title("Age and marriage")
Age and marriage

                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
age                              |                                
                         m1 - m2 |    -0.000      0.001      0.689 
---------------------------------+--------------------------------
married                          |                                
                         m1 - m2 |    -0.011      0.004      0.003 

Age and marriage

                                 |      chi2         df     pvalue 
---------------------------------+--------------------------------
age                              |                                
                         m1 = m2 |     0.161      1.000      0.689 

All six statistics, and a label of your own

metest 1 - 2, stat(all)
             |  estimate         se     zvalue     pvalue         ll         ul 
-------------+-----------------------------------------------------------------
age          |                                                                 
     m1 - m2 |    -0.000      0.001     -0.401      0.689     -0.001      0.001 
metest 1 - 2, rownames("Age effect, m1 vs m2")
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
            Age effect, m1 vs m2 |    -0.000      0.001      0.689 

Pairwise comparisons of marginal effects

Whether the effect of marriage differs across three ages:

mecompare i.married, models(m1) covariates(age=(35 40 45))
Predicting: Pr(union)
Marginal effects (N_m1=1878)

                                 |  ME #   Estimate  Robust SE      P>|z|
---------------------------------+---------------------------------------
married                          |                                       
            Married - Single     |                                       
                          age=35 |     1     -0.032      0.021      0.127
                          age=40 |     2     -0.033      0.022      0.126
                          age=45 |     3     -0.034      0.022      0.126
metest 1 2 3, pwcompare
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
                    ME 2 vs ME 1 |    -0.001      0.002      0.552 
                    ME 3 vs ME 1 |    -0.002      0.003      0.550 
                    ME 3 vs ME 2 |    -0.001      0.002      0.547 
metest 1/3, pwcompare rownames("age 35" "age 40" "age 45") mcompare(bonferroni)
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
                age 40 vs age 35 |    -0.001      0.002      1.000 
                age 45 vs age 35 |    -0.002      0.003      1.000 
                age 45 vs age 40 |    -0.001      0.002      1.000 

NOTE: p-values (and CIs) are Bonferroni-adjusted for the 3 comparisons.

Options

Option Purpose
statistics(list) Statistics to display: estimate, se, zvalue, pvalue, ll, ul, or all. The default is estimate se pvalue. Ignored for equality tests, which report the test statistic, its degrees of freedom, and the p-value. stats() is a synonym.
allstats Same as statistics(all).
pwcompare Compares the listed marginal effects pairwise: each later effect in the list minus each earlier one, in the order margins, pwcompare uses. List the effects by ME #, as a range, or by name: metest 1 2 3, pwcompare or metest 1/3, pwcompare. The rows are labeled ME 2 vs ME 1 and so on, or from rownames().
mcompare(method) Adjusts the p-values (and confidence intervals, when shown) of the pwcompare rows for multiple comparisons; method is bonferroni or sidak.
add Adds the result as another row of the saved table rather than starting a new one. save is a synonym.
clear Clears the saved table before running; metest, clear on its own clears it without running anything.
rownames(string) Labels the row. A : in the label puts what comes before it on a row of its own, with the rest indented underneath, which is how several rows are grouped under one heading. A label longer than 32 characters (after any heading) is shortened to 32. With pwcompare, give one label per listed effect, as in rownames("age 35" "age 40" "age 45"); e.g., one row will read age 40 vs age 35. Labels of up to 14 characters are shown in full, and longer ones are shortened so the row fits 32 characters. label() is a synonym.
decimals(#) Decimal places; the default is 3.
width(#) Width of each statistic column; the default is 9.
labwidth(#) Width of the label column; the maximum is 32. twidth() is a synonym.
title(string) Title above the table.
notable Suppresses the table.
details Shows the underlying nlcom or test output.
level(#) Confidence level for ll and ul.

Results accumulate in the matrix _metest (estimates) and _metest_test (equality tests). metest is r-class: after an expression it returns r(estimate), r(se), r(zvalue), r(pvalue), r(ll), and r(ul); after an equality test, r(chi2) (or r(F)), r(df), and r(pvalue). After pwcompare, r(table) holds the rows of the comparisons.

Use after other commands

metest also works after other estimation commands: a number refers to the nth coefficient in e(b), in the order of matrix list e(b), and coefficient names work as usual.

sysuse nlsw88, clear
(NLSW, 1988 extract)
regress wage age ttl_exp grade
      Source |       SS           df       MS      Number of obs   =     2,244
-------------+----------------------------------   F(3, 2240)      =    132.71
       Model |  11221.4453         3  3740.48178   Prob > F        =    0.0000
    Residual |  63132.8852     2,240  28.1843237   R-squared       =    0.1509
-------------+----------------------------------   Adj R-squared   =    0.1498
       Total |  74354.3305     2,243  33.1495009   Root MSE        =    5.3089

------------------------------------------------------------------------------
        wage | Coefficient  Std. err.      t    P>|t|     [95% conf. interval]
-------------+----------------------------------------------------------------
         age |     -0.101      0.037   -2.735   0.006       -0.174      -0.029
     ttl_exp |      0.271      0.025   10.819   0.000        0.222       0.320
       grade |      0.641      0.045   14.106   0.000        0.552       0.730
       _cons |     -0.061      1.570   -0.039   0.969       -3.140       3.019
------------------------------------------------------------------------------
metest 1 - 2
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
                   age - ttl_exp |    -0.372      0.047      0.000 
metest 1 / 2
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
                   age / ttl_exp |    -0.374      0.136      0.006 
metest 1 = 2 = 3
Tests of equality

                                 |         F         df     pvalue 
---------------------------------+--------------------------------
           age = ttl_exp = grade |    88.241      2.000      0.000 
metest abs(1) - abs(2)
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
         abs(age) - abs(ttl_exp) |    -0.170      0.042      0.000 
metest min(1,2)
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
                min(age,ttl_exp) |    -0.101      0.037      0.006 
metest _b[age] * #10
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
                        age * 10 |    -1.011      0.370      0.006 

After margins, post, a number refers to a row of the margins table. E.g., the difference in two predicted probabilities, averaging over observed values, in the Health and Retirement Study 2020; this replicates mecompare collegeB:

use "https://tdmize.github.io/data/data/cda_hrs", clear
(cda_hrs.dta | Health & Retirement Study 2020)
drop if missing(cogB, marstatB, collegeB, woman, age)
(761 observations deleted)
logit cogB i.collegeB i.marstatB i.woman c.age
Iteration 0:  Log likelihood = -2466.5782  
Iteration 1:  Log likelihood = -2311.9677  
Iteration 2:  Log likelihood = -2282.8575  
Iteration 3:  Log likelihood = -2282.3938  
Iteration 4:  Log likelihood = -2282.3924  
Iteration 5:  Log likelihood = -2282.3924  

Logistic regression                                     Number of obs = 14,962
                                                        LR chi2(4)    = 368.37
                                                        Prob > chi2   = 0.0000
Log likelihood = -2282.3924                             Pseudo R2     = 0.0747

---------------------------------------------------------------------------------------
                 cogB | Coefficient  Std. err.      z    P>|z|     [95% conf. interval]
----------------------+----------------------------------------------------------------
             collegeB |
bachelor's or higher  |     -1.458      0.157   -9.269   0.000       -1.766      -1.150
                      |
             marstatB |
   currently married  |     -0.586      0.092   -6.401   0.000       -0.766      -0.407
                      |
                woman |
               woman  |     -0.221      0.091   -2.428   0.015       -0.400      -0.043
                  age |      0.048      0.004   12.085   0.000        0.040       0.056
                _cons |     -5.926      0.310  -19.128   0.000       -6.533      -5.318
---------------------------------------------------------------------------------------
margins collegeB, post
Predictive margins                                      Number of obs = 14,962
Model VCE: OIM

Expression: Pr(cogB), predict()

---------------------------------------------------------------------------------------
                      |            Delta-method
                      |     Margin   std. err.      z    P>|z|     [95% conf. interval]
----------------------+----------------------------------------------------------------
             collegeB |
       no bachelor's  |      0.048      0.002   23.986   0.000        0.044       0.052
bachelor's or higher  |      0.012      0.002    6.758   0.000        0.008       0.015
---------------------------------------------------------------------------------------
metest 2 - 1
                                 |  estimate         se     pvalue 
---------------------------------+--------------------------------
       1_collegeB - 0bn_collegeB |    -0.036      0.003      0.000 

For risk ratios, use the rratios option of mecompare, which tests each ratio against 1. metest would test a risk ratio against a null of 0, which is not appropriate for risk ratios.

Omitted (o.) coefficients are skipped when numbering, so check the numbers with matrix list e(b). After some commands test reports F rather than chi-squared; run metest, clear before accumulating results from a model of the other kind.

Back to top