*! version 2.0 Fernando Rios-Avila September 2020
help f_able

Title

f_able -- Module for the estimation of marginal effects with transformed covariates

Syntax

Create new variable with label exp. The newly created variable is stored with format double.

fgen
newvar =exp

Replace contents of existing variable and change label

frep
oldvar
=exp

Declares which variables in the specification are "constructed/transformed" variables.

f_able [varlist] , nlvar(varlist) [auto]

Automatically detects which variables in a regression are "constructed/transformed" variables.

f_reg command depvar [indepvars] [if in] [weights], [command options]

Resets stored in e() to the original ones

f_able_reset

Makes the variance covariance matrix stored in e(V) symetric, when nonsymmetric warning appears

f_symev

Makes the variance covariance matrix stored in r(V) symetric, when nonsymmetric warning appears

f_symrv

newvar Stands for a new variable to be created with the format of choice. Its suggested to create them in double format.

oldvar Stands for the name of a variable already in the dataset.

exp stands for any expression to be used for creating or replacing the values of the variable. This will be used as the variable label.
if the expresion is longer than 75 characters, the expression will be stored as a note in that variable.

nlvar(varlist) is used to indicate all variables in the model that are constructed variables. They can also be declared as a varlist after f_able.
These variables must be present in the estimated model, and should be labelled accordingly. fgen and frep
are used to help with the proper variable labeling.

auto can be used to declare the set of covariates in the model, excluding the constructed variables. This
may facilitate the use of margins, without using options nochain or numerical. This is an experimental feature.

Description

f_able is a command that can be used to enable margins to correctly estimate
marginal effects when using transformed/constructed data.

Internally, this command adds information to e() that is later used by the estimation
predict command, so that constructed data is handled correctly.

The command f_able_reset is used to reset the information in e() to the values before
f_able was used.

The commands fgen and frep are used to create or replace variables storing the
expression used for their creation as labels. If the expression is longer than 75 characters,
it assigns the label "See note", and the note will contain the used expression.

When creating the new variables with fgen, they will be stored with double precision.

See Rios-Avila(2020) for brief discussion on the estimation of marginal effects, and how the command works.

Examples

. webuse dui, clear

Example 1

Replication of margins when using factor notation and interactions.

First, using factor notation

. reg citations fines c.fines#c.fines

. margins, dydx(fines)

Replicating this using f_able

. fgen fines2=fines^2

. reg citations fines fines2

. f_able, nlvar(fines2)

Margins need to include the option nochain

. margins, dydx(fines) nochain

Same in 1-step

. freg reg citations fines fines2

. margins, dydx(fines) nochain

Example 2

Using spline transformations. Quadratic spline, with 1 knot

. fgen fines3=max(fines-9.9,0)^2

Option 1

. reg citations fines fines2 fines3

. f_able, nlvar(fines2 fines3)

Option 2

. f_reg reg citations fines fines2 fines3

Estimating marginal effects

. margins, dydx(fines) nochain

Estimating marginal effects across various points of fines, and plotting.

. margins, dydx(fines) nochain at(fines=(7.5(.25)12)) plot

Estimating marginal means across various points of fines, and plotting.

. margins, nochain at(fines=(7.5(.25)12)) plot

Example 3

Using an inverse transformation excluding the original variable

. frep fines2=1/fines

. reg citations o.fines fines2

. f_able, nlvar(fines2)

. margins, dydx(fines) nochain

Example 4

Using other nonlinear estimators like poisson

. poisson citations c.fines c.fines#c.fines, robust

. margins, dydx(fines)

Replicating it with f_able

. frep fines2=fines^2

. poisson citations fines fines2, robust

. f_able, nlvar(fines2)

This will give incorrect results.

. margins, dydx(fines) nochain

Instead, one must use option numerical to force numerical derivatives

. margins, dydx(fines) nochain numerical

Example 5

Going back to the OLS model, I now estimate the equivalent to a Varying Coefficient models
making use of both factor notation and f_able.

I choose this particular problem because it shows some of the problems that may arise using f_able

. webuse dui, clear

. fgen fines2=fines^2

. fgen fines3=fines^3

. fgen fines4=max(fines-9.1,0)^3

. fgen fines5=max(fines-9.9,0)^3

. fgen fines6=max(fines-11.1,0)^3

. reg citations fines fines2 fines3 fines4 fines5 fines6 i.csize i.csize#c.(fines fines2 fines3 fines4 fines5 fines6)

. f_able fines2 fines3 fines4 fines5 fines6, auto

This may fail because of the complexity of the model

. margins, dydx(fines) nochain

One solution is to add the noestimcheck option

. margins, dydx(fines) nochain noestimcheck

Estimating margins across various values of fines

. margins, dydx(fines) nochain noestimcheck at(fines=(8(.5)11.5)) plot

. margins, nochain noestimcheck at(fines=(8(.5)11.5)) plot

The commands may shows no standard errors. One solution is to use f_symrv before plotting

. margins, dydx(fines) nochain noestimcheck at(fines=(8(.5)11.5))

. f_symrv

. marginsplot

. margins, nochain noestimcheck at(fines=(8(.5)11.5))

. f_symrv

. marginsplot

Example 6

One can also use post, and correct e(V) with f_symev

. margins, dydx(fines) nochain noestimcheck at(fines=(8(.5)11.5)) post

. f_symev

. margins

Example 7

Marginal effects for other variables in model will be the same with and without f_able, with small differences in point estimates

. qui:reg citations fines fines2 fines3 fines4 fines5 fines6 i.csize i.csize#c.(fines fines2 fines3 fines4 fines5 fines6)

. qui:f_able fines2 fines3 fines4 fines5 fines6, auto

. margins, dydx(csize) noestimcheck

. margins, dydx(csize) noestimcheck nochain

. f_able_reset

. margins, dydx(csize) noestimcheck

. margins, dydx(csize) noestimcheck nochain

But can still be corrected using f_symrv, and reported using _coef_table

. f_able, nlvar(fines2 fines3 fines4 fines5 fines6)

. margins, dydx(csize) noestimcheck nochain

. f_symrv

. matrix bts=r(b)

. matrix vcv=r(V)

. _coef_table, bmatrix(bts) vmatrix(vcv)

. f_able_reset

. margins, dydx(csize) noestimcheck

. f_symrv

. matrix bts=r(b)

. matrix vcv=r(V)

. _coef_table, bmatrix(bts) vmatrix(vcv)

Nevertheless one can still use this to estimate point estimates, without further manipulation

Example 8

Another use of f_able could be in combination with fractional polynomials

. webuse igg, clear

. fp <age>: regress sqrtigg <age>

As before, we create the new variables based on the selected model, and use f_able to enable margins

. fgen age1=age^-2

. fgen age2=age^2

. regress sqrtigg age1 age2 o.age

. f_able, nlvar(age1 age2)

. margins, dydx(age) nochain

It does require the option noestimcheck to get results for various points in the distribution of age

. margins, dydx(age) nochain noestimcheck at(age=(1(0.5)6)) plot

. margins, nochain noestimcheck at(age=(1(0.5)6)) plot

Example 9

now and even more complex, multiple equation model like mlogit

. webuse sysdsn1, clear

. mlogit insure age c.age#c.age male nonwhite i.site

. margins, dydx(age)

Using f_able

. fgen double age2=age^2

. mlogit insure age age2 male nonwhite i.site

. f_able, nlvar(age2)

. margins, dydx(age) nochain numerical

Example 10

and now using fp

. fp <age>, dim(3):mlogit insure <age> male nonwhite i.site

. drop age2

. fgen age2=age^2

. fgen age3=log(age)*age^2

. mlogit insure age age2 age3 male nonwhite i.site

. f_able, nlvar(age2 age3)

. margins, dydx(age) nochain numerical

Example 11

As shown before, the options nochain and numeric are not necessary
if "age" is not of interest (assumed fixed)

. margins, dydx( male nonwhite i.site)

. margins, dydx( male nonwhite i.site) nochain numerical

Example 12

And just for completeness we estimate the effects across various points of the age

. margins, dydx(age) nochain numerical at(age=(25(5)80)) plot

. margins, nochain numerical at(age=(25(5)80)) plot

Example 13

Using alternative syntax, and option auto

. webuse sysdsn1, clear

. mlogit insure age c.age#c.age male

. margins, dydx(*)

. fgen age2=age*age

. mlogit insure age age2 male

. f_able age2, auto

. margins, dydx(*)

References

Rios-Avila, F. 2021. Estimation of marginal effects for models with alternative variable transformations. Stata Journal 21: 81-96. https://doi.org/10.1177/1536867X211000005.

Acknowledgments

This program was inspired by some discussions with Enrique Pinzon who described with some detail the workings behind
npregress series, and behind margins.

All errors are my own.

Author

Fernando Rios-Avila

Levy Economics Institute of Bard College

Annandale-on-Hudson, NY

friosavi@levy.org

Also see

Help: margins, predict, f_spline, f_rcspline, _coef_table