Expands formula macros
Create macros within formulas and expand them with character vectors or other formulas.
xpd(fml, ..., lhs, rhs, data = NULL)
fml |
A formula containing macros variables. Each macro variable must start with two dots. The macro variables can be set globally using |
... |
Definition of the macro variables. Each argument name corresponds to the name of the macro variable. It is required that each macro variable name starts with two dots (e.g. |
lhs |
If present then a formula will be constructed with |
rhs |
If present, then a formula will be constructed with |
data |
Either a character vector or a data.frame. This argument will only be used if a macro of the type |
In xpd
, the default macro variables are taken from getFixest_fml
. Any value in the ...
argument of xpd
will replace these default values.
The definitions of the macro variables will replace in verbatim the macro variables. Therefore, you can include multi-part formulas if you wish but then beware of the order of the macros variable in the formula. For example, using the airquality
data, say you want to set as controls the variable Temp
and Day
fixed-effects, you can do setFixest_fml(..ctrl = ~Temp | Day)
, but then feols(Ozone ~ Wind + ..ctrl, airquality)
will be quite different from feols(Ozone ~ ..ctrl + Wind, airquality)
, so beware!
It returns a formula where all macros have been expanded.
In a formula, the dot square bracket (DSB) operator can: i) create manifold variables at once, or ii) capture values from the current environment and put them verbatim in the formula.
Say you want to include the variables x1
to x3
in your formula. You can use xpd(y ~ x.[1:3])
and you'll get y ~ x1 + x2 + x3
.
To summon values from the environment, simply put the variable in square brackets. For example: for(i in 1:3) xpd(y.[i] ~ x)
will create the formulas y1 ~ x
to y3 ~ x
depending on the value of i
.
You can include a full variable from the environment in the same way: for(y in c("a", "b")) xpd(.[y] ~ x)
will create the two formulas a ~ x
and b ~ x
.
The DSB can even be used within variable names, but then the variable must be nested in character form. For example y ~ .["x.[1:2]_sq"]
will create y ~ x1_sq + x2_sq
. Using the character form is important to avoid a formula parsing error.
In all fixest
estimations, this special parsing is enabled, so you don't need to use xpd
.
Limitations: the use of multiple square brackets within a single variable is not implemented. For example, the following will not work xpd(y ~ ..x, ..x = x.[1:3]_.[1:3])
.
You can catch several variable names at once by using regular expressions. To use regular expressions, you need to enclose it in the dot-dot function: ..("regex")
. For example, ..("Sepal")
will catch both the variables Sepal.Length
and Sepal.Width
from the iris
data set. In a fixest
estimation, the variables names from which the regex will be applied come from the data set. If you use xpd
, you need to provide either a data set or a vector of names in the argument data
.
Note that the dot square bracket operator (DSB, see before) is applied before the regular expression is evaluated. This means that ..("x.[3:4]_sq")
will lead, after evaluation of the DSB, to ..("x3_sq|x4_sq")
. It is a handy way to insert range of numbers in a regular expression.
setFixest_fml
to set formula macros.
# Small examples with airquality data data(airquality) # we set two macro variables setFixest_fml(..ctrl = ~ Temp + Day, ..ctrl_long = ~ poly(Temp, 2) + poly(Day, 2)) # Using the macro in lm with xpd: lm(xpd(Ozone ~ Wind + ..ctrl), airquality) lm(xpd(Ozone ~ Wind + ..ctrl_long), airquality) # You can use the macros without xpd() in fixest estimations a = feols(Ozone ~ Wind + ..ctrl, airquality) b = feols(Ozone ~ Wind + ..ctrl_long, airquality) etable(a, b, keep = "Int|Win") # Using .[] base = setNames(iris, c("y", "x1", "x2", "x3", "species")) i = 2:3 z = "species" lm(xpd(y ~ x.[2:3] + .[z]), base) # No xpd() needed in feols feols(y ~ x.[2:3] + .[z], base) # # You can use xpd for stepwise estimations # # Note that for stepwise estimations in fixest, you can use # the stepwise functions: sw, sw0, csw, csw0 # -> see help in feols or in the dedicated vignette # we want to look at the effect of x1 on y # controlling for different variables base = iris names(base) = c("y", "x1", "x2", "x3", "species") # We first create a matrix with all possible combinations of variables my_args = lapply(names(base)[-(1:2)], function(x) c("", x)) (all_combs = as.matrix(do.call("expand.grid", my_args))) res_all = list() for(i in 1:nrow(all_combs)){ res_all[[i]] = feols(xpd(y ~ x1 + ..v, ..v = all_combs[i, ]), base) } etable(res_all) coefplot(res_all, group = list(Species = "^^species")) # # You can use macros to grep variables in your data set # # Example 1: setting a macro variable globally data(longley) setFixest_fml(..many_vars = grep("GNP|ployed", names(longley), value = TRUE)) feols(Armed.Forces ~ Population + ..many_vars, longley) # Example 2: using ..("regex") to grep the variables "live" feols(Armed.Forces ~ Population + ..("GNP|ployed"), longley) # Example 3: same as Ex.2 but without using a fixest estimation # Here we need to use xpd(): lm(xpd(Armed.Forces ~ Population + ..("GNP|ployed"), data = longley), longley) # # You can also put numbers in macros # res_all = list() for(p in 1:3){ res_all[[p]] = feols(xpd(Ozone ~ Wind + poly(Temp, ..p), ..p = p), airquality) } etable(res_all) # # lhs and rhs arguments # # to create a one sided formula from a character vector vars = letters[1:5] xpd(rhs = vars) # Alternatively, to replace the RHS xpd(y ~ 1, rhs = vars) # To create a two sided formula xpd(lhs = "y", rhs = vars) # # Dot square bracket operator # # You can create multiple variables at once xpd(y ~ x.[1:5] + z.[2:3]) # You can summon variables from the environment var = "a" xpd(y ~ x.[var]) # ... the variables can be multiple vars = LETTERS[1:3] xpd(y ~ x.[vars]) # You can have "complex" variable names but they must be nested in character form xpd(y ~ .["x.[vars]_sq"]) # DSB can be used within regular expressions re = c("GNP", "Pop") xpd(Unemployed ~ ..(".[re]"), data = longley) # => equivalent to ..("GNP|Pop")
Please choose more modern alternatives, such as Google Chrome or Mozilla Firefox.