knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) library(dplyr) library(ggplot2) library(magrittr) library(rlang) library(tidyr) library(MacroGrowth)
The R
package MacroGrowth
provides sophisticated tools for fitting macroeconomic
growth models to data.
MacroGrowth
has several desirable features for macroeconomic modelers:
The functions in this package were developed for and used first in Heun et al. [-@Heun:2017].
MacroGrowth
supports the following macroeconomic growth models:
In the above equations:
In the CES model, the elasticity of substitution between the ($x_1$, $x_2$) pair and $x_3$ is given by $\sigma = \frac{1}{1 + \rho}$. The elasticity of substitution between $x_1$ and $x_2$ is given by $\sigma_1 = \frac{1}{1 + \rho_1}$.
The Linex model is usually presented with $a_0$ (as above) and $c_t$ coefficients. $c_t$ is the ratio of Linex fitted coefficients, given by $c_t = \frac{a_1}{a_0}$.
The starting point for any fitting process is macroeconomic data.
For this vignette, we'll use a subset of the UK macroeconomic data
from Heun et al. [-@Heun:2017].
The data frame EconUK
is included in the MacroGrowth
package.
library(dplyr) library(ggplot2) library(magrittr) library(rlang) library(tidyr) library(MacroGrowth) head(EconUK)
The EconUK
data frame contains indexed
GDP, capital, labor, and two types of energy data
(primary exergy and useful exergy).
All economic and energy data series are indexed by ratio to an initial year (1960),
such that all quantities are 1 in 1960.
Time is indexed by difference to the initial year, such that 1960 is year 0.
The prefix i
indicates an indexed variable.
iK
is indexed capital stock,
iL
is indexed labor,
iXp
is indexed primary exergy, and
iXu
is indexed useful exergy.
The functions in MacroGrowth
can fit indexed or non-indexed data.
When data are indexed as shown in the EconUK
data frame,
the fitted value of the $\theta$ parameter is expected to be close to 1.
When data are not indexed, the $\theta$ parameter will likely be far from 1,
because $\theta$ assumes the task of unit conversion
from factors of production in various functional forms
(on the right side of the economic model)
to economic output
(on the left side of the economic model).
To fit a model to macroeconomic data, use one of the *Model
functions
in the MacroGrowth
pacakge.
To fit a single-factor model, use the sfModel
function.
sffit <- sfModel(formula = iGDP ~ iK + iYear, data = EconUK) sffit
The sfModel
function produces an SFmodel
object.
In all *Model
functions,
a formula of the form y ~ x1 + x2 + x3 + t
communicates the roles of the factors of production to the fitting function.
The components of the formula are:
~
character,+
and positioned to the right of the ~
character,
and +
character, and
always positioned as the rightmost item in the formula. For models with fewer than 3 factors of production,
some of x1
, x2
, and x3
can be omitted.
In the above example,
formula = iGDP ~ iK + iYear
indicates that
the model is to be fitted with
indexed GDP (iGDP) as the response variable,
indexed capital stock (iK) as the only factor of production, and
indexed time (iYear) as the time variable.
The coefficients of the fitted model can be recovered with the naturalCoef
function.
naturalCoef(sffit)
Similar functions can be used for the other model types.
To fit the Cobb-Douglas model to the UK's capital stock and labor data,
use the cdModel
function.
cdfit <- cdModel(formula = iGDP ~ iK + iL + iYear, data = EconUK) cdfit
The cdModel
function produces a CDEmodel
object.
In the above example, iGDP ~ iK + iL + iYear
indicates that
the model is to be fitted with
indexed GDP (iGDP) as the response variable,
indexed capital stock (iK) and indexed labor (iL) as the factors of production, and
indexed year (iYear) as the time variable.
The coefficients of the model can be recovered with the naturalCoef
function.
naturalCoef(cdfit)
For the CES production function, use the cesModel
function
with two or three factors of production.
cesfit <- cesModel(formula = iGDP ~ iK + iL + iYear, data = EconUK) naturalCoef(cesfit)
The cesModel
function produces a cesModel
object.
Note that output elasticities ($\alpha_1$, $\alpha_2$, and $\alpha_3$)
are calculated by the naturalCoef
function.
Equations for the output elasticities are given in Appendix B
of Heun et al. [-@Heun:2017].
Also note that the cesModel
function repeatedly calls
the excellent cesEst
function from the micEconCES
pacakge.
For more details on the cesEst
function,
see Henningsen and Henningsen [-@Henningsen:2011td].
For more details on the fitting algorithm employed by cesModel
,
see Heun et al. [-@Heun:2017].
For the Linex model, there must be three factors of production. The first factor of production ($x_1$) must be capital stock. The second factor of production ($x_2$) must be labor. The third factor of production ($x_3$) must be an energy variable.
linexfit <- linexModel(formula = iGDP ~ iK + iL + iXp + iYear, data = EconUK) naturalCoef(linexfit)
The linexModel
function produces a LINEXmodel
object.
In the Linex model, output elasticities are a function of time.
To recover the output elasticities from the Linex model,
use the fortify
function.
$\alpha$, $\beta$, and $\gamma$ are output elasticities
for capital, labor, and energy, respectively.
head(fortify(linexfit))
Linex model output elasticities are given by Equation 9 in Warr and Ayres [-@Warr:2012cg].
By default the original economic data are saved
as an attribute of the model object.
Data can be recovered with the getData
function.
head(getData(cdfit))
To not save original economic data with the model object,
set the save.data
argument of the various *Model
functions to FALSE
.
The fitted values of the response variable ($y$) can be recovered with the yhat
function.
The yhat
function gives values of the response variable
on the natural (not logarithmic) scale.
yhat(cdfit)
Residuals for any model can be recovered by the resid
function.
The resid
function gives residuals in log space
(where the model was fitted).
resid(cdfit)
The sum of squared errors (SSE) for any model can be calculated by the following code.
sum(resid(cdfit)^2)
Most *Model
fitting functions have the capability to account for boundaries and constraints.
Constrained fitting behavior is controlled by the constrained
argument to the *Model
functions.
The simplest fitting function (sfModel
)
provides an option to constrain the fit with $m = 1$,
thereby assuming a Cobb-Douglas-type model where the output elasticity
is constrained to the economically-meaningful value.
By default, the single-factor model sets constrained = FALSE
.
sfModel(formula = iGDP ~ iK + iYear, data = EconUK) %>% naturalCoef() sfModel(formula = iGDP ~ iK + iYear, data = EconUK, constrained = TRUE) %>% naturalCoef()
The cdModel
function always assumes constant returns to scale and
fits with $\displaystyle\sum_i \alpha_i = 1$.
By default, constrained = TRUE
, thereby assuring that $0 \le \alpha_i \le 1$.
To demonstrate fitting with constraints,
we first use the cdModel
function to fit the first 10 years (1960--1969) of EconUK
and find $\alpha_2 < 0$.
cdModel(formula = iGDP ~ iK + iL + iXu + iYear, data = EconUK %>% filter(Year < 1970), constrained = FALSE) %>% naturalCoef()
If, on the other hand, we use the default setting for the constrained
argument,
the best fit is found with $\alpha_2 = 0$ and different values for \alpha_1
and \alpha_3
.
cdModel(formula = iGDP ~ iK + iL + iXu + iYear, data = EconUK %>% filter(Year < 1970)) %>% naturalCoef()
Constraints on the CES model are considerably more complicated than constraints on single-factor or Cobb-Douglas models.
When constrained = TRUE
, the cesModel
function restricts
fitted parameters to the following economically-meaningful regions:
The default value of constrained
for the cesModel
function is TRUE
.
To demonstrate, we fit the CES model unconstrained
with capital (iK
) and useful exergy (iXu
) as the factors of production
for the years 1980--1989
to find that $\rho_1$ is beyond the economically meaningful boundary.
cesModel(formula = iGDP ~ iK + iXu + iYear, data = EconUK %>% filter(Year >= 1980 & Year < 1990), constrained = FALSE) %>% naturalCoef()
If, instead, we use the default value for constrained
(TRUE
),
we obtain fitted parameters that fall within the economically-meaningful region
or on the boundary of the economically-meaningful region,
even if the quality of the fit is worse.
cesModel(formula = iGDP ~ iK + iXu + iYear, data = EconUK %>% filter(Year >= 1980 & Year < 1990)) %>% naturalCoef()
The process for constrained fitting by the cesModel
function is described in detail
in Heun et al. [-@Heun:2017].
In short, the full CES model and 20 boundary models are compared.
The model with the smallest sum of squared errors (SSE) is returned by the cesModel
function.
Models with larger SSE are stored as a list in the model.attempts
attribute of the cesModel
object
returned by the cesModel
function.
To retrieve the rejected boundary models, use the attr
function.
attr(cesfit, "model.attempts")[[1]] %>% naturalCoef()
The economically-meaningful region for Linex model parameters $a_0$ and $a_1$ is all real numbers.
Thus, fitted parameter constraints have no meaning for the linexModel
function, and
constrained
is not an argument to the linexModel
function.
Bootstrapping is a statistical technique for estimating the precision of parameter estimates by exploring the distribution of estimates in many resampled data sets. Each resampled data set is a randomized version of the original sample data to which the desired analysis method can be applied.
The coefficients from the fit to a resampled time series (the "resample coefficients") will be different from the coefficients obtained from the fit to historical data (the "base coefficients") and form a "resample distribution". When these resample coefficients are highly variable, it is an indication that the data do not determine the parameter estimates very precisely. Even when the residuals are small and the model produces fitted values that track the observed data closely, it may still be difficult to estimate some or all of the model parameters precisely. Lack of precision can stem from a number of factors, including a poor model fit, low model sensitivity to one or more parameters, correlation among parameter estimates, variability unexplained by the predictors in the model, etc.
To perform bootstrap resampling in the EconGrowth
package,
a model object must first be obtained by calling one of the *Model
functions.
For this example, we'll use the cdfit
object obtained above.
The resampledFits
function performs the resampling.
cdfits_rs <- resampledFits(model = cdfit, method = "wild", n = 5, seed = 123)
The resampledFits
function returns a list with two named members: coeffs
and models
.
coeffs
is a data frame with n + 1
rows.
The first row contains fitted coefficients for the original model and has a method
of orig
.
The remaining rows contain fitted coefficients for the resample fits,
each with a different value for the index
variable, and
each with the method
specified in the function call.
cdfits_rs$coeffs
models
is a list containing the model object for each resample fit.
# Original fit cdfits_rs$models[[1]] %>% naturalCoef() # First resampled model cdfits_rs$models[[2]] %>% naturalCoef() # Last resampled model cdfits_rs$models[[6]] %>% naturalCoef()
The resampledFits
function knows about models fitted with any of the *Model
functions.
resampledFits(model = sffit, method = "wild", n = 5)[["coeffs"]] resampledFits(model = cesfit, method = "wild", n = 5)[["coeffs"]] resampledFits(model = linexfit, method = "wild", n = 5)[["coeffs"]]
Graphs comparing fitted and historical values are often helpful for visualizing model performance. The following code provides an example using the Cobb-Douglas model fitted above.
bind_cols(EconUK, yhat(cdfit) %>% as.data.frame() %>% set_names("yhat")) %>% ggplot() + # Add historical data as points geom_point(mapping = aes(x = Year, y = iGDP), shape = 1) + # Add the fitted model as a line geom_line(mapping = aes(x = Year, y = yhat))
For the purposes of displaying resampled results from the three-factor-of-production Cobb-Douglas model, fitted output elasticies ($\alpha_i$) can be shown in a ternary plot.
triData <- cdModel(formula = iGDP ~ iK + iL + iXu + iYear, data = EconUK) %>% resampledFits(method = "wild", n = 100, seed = 123) %>% extract2("coeffs") triData %>% filter(method == "wild") %>% triPlot(mapping = aes(x = alpha_1, y = alpha_2, z = alpha_3), alpha = 0.3) + geom_point(data = triData %>% filter(method == "orig"), mapping = aes(x = alpha_1, y = alpha_2, z = alpha_3), color = "red", alpha = 1, size = 3, stat = "triangle")
The MacroGrowth
package provides functions that
streamline both
fitting processes (with *Model
functions) and
bootstrap resampling (with the resampledFits
function)
for several macroeconomic growth models.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.