| Title: | Analysis of Metafrontier Models for Efficiency and Productivity |
|---|---|
| Description: | Implements metafrontier production function models for estimating technical efficiencies and technology gaps for firms operating under different technologies. Supports both stochastic frontier analysis (SFA) and data envelopment analysis (DEA) based metafrontiers. Includes the deterministic metafrontier of Battese, Rao, and O'Donnell (2004) <doi:10.1023/B:PROD.0000012454.06094.29>, the stochastic metafrontier of Huang, Huang, and Liu (2014) <doi:10.1007/s11123-014-0402-2>, and the metafrontier Malmquist productivity index of O'Donnell, Rao, and Battese (2008) <doi:10.1007/s00181-007-0119-4>. Additional features include panel SFA with time-varying inefficiency, bootstrap confidence intervals for technology gap ratios, latent class metafrontier estimation via the EM algorithm, Murphy-Topel corrected standard errors, and 'ggplot2' visualisation methods. |
| Authors: | Erik Enstad [aut, cre] (ORCID: <https://orcid.org/0009-0006-1053-3849>) |
| Maintainer: | Erik Enstad <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.2.2 |
| Built: | 2026-05-23 09:04:37 UTC |
| Source: | https://github.com/iik1/metafrontier |
Generic function that extracts the components needed by
metafrontier from a pre-fitted frontier model.
Methods are provided for sfaR, frontier, and
Benchmarking objects, as well as plain lists with the
required fields.
as_metafrontier_model(x, ...)as_metafrontier_model(x, ...)
x |
a fitted frontier model object. |
... |
additional arguments passed to methods. |
A list with components: coefficients, efficiency,
X, y, sigma_v, sigma_u, logLik,
hessian, n, dist.
# Using a named list: mod <- as_metafrontier_model(list( coefficients = c("(Intercept)" = 2, log_x1 = 0.5, log_x2 = 0.3), efficiency = runif(50, 0.7, 1), X = matrix(rnorm(150), 50, 3), y = rnorm(50, 5) )) str(mod)# Using a named list: mod <- as_metafrontier_model(list( coefficients = c("(Intercept)" = 2, log_x1 = 0.5, log_x2 = 0.3), efficiency = runif(50, 0.7, 1), X = matrix(rnorm(150), 50, 3), y = rnorm(50, 5) )) str(mod)
Autoplot Method for Bootstrap TGR Objects
## S3 method for class 'boot_tgr' autoplot(object, which = c("distribution", "ci"), ...)## S3 method for class 'boot_tgr' autoplot(object, which = c("distribution", "ci"), ...)
object |
a |
which |
character. |
... |
additional arguments. |
A ggplot object.
if (requireNamespace("ggplot2", quietly = TRUE)) { sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") boot <- boot_tgr(fit, R = 50, seed = 1, progress = FALSE) ggplot2::autoplot(boot) }if (requireNamespace("ggplot2", quietly = TRUE)) { sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") boot <- boot_tgr(fit, R = 50, seed = 1, progress = FALSE) ggplot2::autoplot(boot) }
Autoplot Method for Malmquist Meta Objects
## S3 method for class 'malmquist_meta' autoplot(object, which = c("decomposition", "tgr_evolution", "mpi_trend"), ...)## S3 method for class 'malmquist_meta' autoplot(object, which = c("decomposition", "tgr_evolution", "mpi_trend"), ...)
object |
a |
which |
character. Which plot:
|
... |
additional arguments. |
A ggplot object.
if (requireNamespace("ggplot2", quietly = TRUE)) { panels <- lapply(1:3, function(t) { sim <- simulate_metafrontier(n_groups = 2, n_per_group = 30, seed = 42 + t) sim$data$time <- t sim$data$id <- seq_len(nrow(sim$data)) sim$data }) pdata <- do.call(rbind, panels) malm <- malmquist_meta(log_y ~ log_x1 + log_x2, data = pdata, group = "group", time = "time") ggplot2::autoplot(malm, which = "decomposition") }if (requireNamespace("ggplot2", quietly = TRUE)) { panels <- lapply(1:3, function(t) { sim <- simulate_metafrontier(n_groups = 2, n_per_group = 30, seed = 42 + t) sim$data$time <- t sim$data$id <- seq_len(nrow(sim$data)) sim$data }) pdata <- do.call(rbind, panels) malm <- malmquist_meta(log_y ~ log_x1 + log_x2, data = pdata, group = "group", time = "time") ggplot2::autoplot(malm, which = "decomposition") }
Creates diagnostic and summary plots for metafrontier objects using ggplot2.
## S3 method for class 'metafrontier' autoplot( object, which = c("tgr", "efficiency", "decomposition", "frontier"), ... )## S3 method for class 'metafrontier' autoplot( object, which = c("tgr", "efficiency", "decomposition", "frontier"), ... )
object |
a |
which |
character. Which plot to produce:
|
... |
additional arguments (currently unused). |
A ggplot object.
if (requireNamespace("ggplot2", quietly = TRUE)) { sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") ggplot2::autoplot(fit, which = "tgr") ggplot2::autoplot(fit, which = "decomposition") }if (requireNamespace("ggplot2", quietly = TRUE)) { sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") ggplot2::autoplot(fit, which = "tgr") ggplot2::autoplot(fit, which = "decomposition") }
Computes bootstrap confidence intervals for TGR estimates from a fitted metafrontier model. Supports both parametric (residual resampling) and nonparametric (case resampling) bootstraps.
boot_tgr( object, R = 999, type = c("parametric", "nonparametric"), level = 0.95, ci_type = c("percentile", "bca"), seed = NULL, progress = TRUE, ncores = 1L, ... )boot_tgr( object, R = 999, type = c("parametric", "nonparametric"), level = 0.95, ci_type = c("percentile", "bca"), seed = NULL, progress = TRUE, ncores = 1L, ... )
object |
a |
R |
integer. Number of bootstrap replications (default 999). |
type |
character. |
level |
numeric. Confidence level (default 0.95). |
ci_type |
character. |
seed |
optional integer seed for reproducibility. |
progress |
logical. Show progress bar (default |
ncores |
integer. Number of CPU cores for parallel bootstrap
(default 1, sequential). Requires the |
... |
additional arguments passed to |
An object of class "boot_tgr" containing:
R x n matrix of bootstrapped TGR values
original TGR estimates
n x 2 matrix of observation-level confidence intervals
data frame of group-level mean TGR intervals
number of successful replications
requested number of replications
bootstrap type used
CI type used
confidence level
sim <- simulate_metafrontier(n_groups = 2, n_per_group = 100, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") boot <- boot_tgr(fit, R = 50, seed = 1) print(boot) confint(boot)sim <- simulate_metafrontier(n_groups = 2, n_per_group = 100, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") boot <- boot_tgr(fit, R = 50, seed = 1) print(boot) confint(boot)
Computes Wald-type confidence intervals for the metafrontier coefficients using the variance-covariance matrix from the stochastic metafrontier.
## S3 method for class 'metafrontier' confint( object, parm, level = 0.95, correction = c("none", "murphy-topel"), ... )## S3 method for class 'metafrontier' confint( object, parm, level = 0.95, correction = c("none", "murphy-topel"), ... )
object |
a |
parm |
a character or integer vector of parameter names or indices. If missing, all frontier coefficients are used. |
level |
the confidence level (default 0.95). |
correction |
character. Passed to |
... |
additional arguments (currently unused). |
A matrix with columns for the lower and upper bounds.
sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") confint(fit) # With Murphy-Topel correction (requires numDeriv): confint(fit, correction = "murphy-topel")sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") confint(fit) # With Murphy-Topel correction (requires numDeriv): confint(fit, correction = "murphy-topel")
Extracts technical efficiency scores from a fitted metafrontier
model. Returns either group-specific efficiency (),
metafrontier efficiency (), or the
technology gap ratio ().
efficiencies(object, ...) ## S3 method for class 'metafrontier' efficiencies(object, type = c("meta", "group", "tgr"), ...)efficiencies(object, ...) ## S3 method for class 'metafrontier' efficiencies(object, type = c("meta", "group", "tgr"), ...)
object |
a fitted |
... |
additional arguments (currently unused). |
type |
character. The type of efficiency to return:
|
The fundamental metafrontier decomposition is:
where is efficiency relative to the group frontier
(returned by type = "group") and is the
technology gap ratio (returned by type = "tgr").
A numeric vector of efficiency scores of length
nobs(object).
technology_gap_ratio, metafrontier
set.seed(42) sim <- simulate_metafrontier(n_groups = 2, n_per_group = 100) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") # Group-level efficiency te <- efficiencies(fit, type = "group") # Metafrontier efficiency te_star <- efficiencies(fit, type = "meta") # Verify decomposition: TE* = TE x TGR tgr <- efficiencies(fit, type = "tgr") all.equal(te_star, te * tgr)set.seed(42) sim <- simulate_metafrontier(n_groups = 2, n_per_group = 100) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") # Group-level efficiency te <- efficiencies(fit, type = "group") # Metafrontier efficiency te_star <- efficiencies(fit, type = "meta") # Verify decomposition: TE* = TE x TGR tgr <- efficiencies(fit, type = "tgr") all.equal(te_star, te * tgr)
Estimates a metafrontier model where group membership is unobserved, using an EM algorithm to jointly estimate class membership probabilities, class-specific frontier parameters, and the metafrontier.
latent_class_metafrontier( formula, data, n_classes = 2, dist = c("hnormal", "tnormal", "exponential"), meta_type = c("deterministic", "stochastic"), n_starts = 10, max_iter = 200, tol = 1e-06, seed = NULL, control = list(), ... )latent_class_metafrontier( formula, data, n_classes = 2, dist = c("hnormal", "tnormal", "exponential"), meta_type = c("deterministic", "stochastic"), n_starts = 10, max_iter = 200, tol = 1e-06, seed = NULL, control = list(), ... )
formula |
a |
data |
a data frame. |
n_classes |
integer. Number of latent classes (default 2). |
dist |
distribution of the inefficiency term. |
meta_type |
metafrontier type for Stage 2. |
n_starts |
integer. Number of random initializations (default 10). The best is selected by log-likelihood. |
max_iter |
integer. Maximum EM iterations (default 200). |
tol |
numeric. Convergence tolerance on marginal LL (default 1e-6). |
seed |
optional integer seed. |
control |
list of control parameters for the optimiser. |
... |
additional arguments. |
The EM algorithm iterates between:
E-step: compute posterior class membership probabilities for each observation using Bayes' rule
M-step: update class-specific frontier parameters via weighted MLE, and update class proportions
Multiple random starts (n_starts) are used to avoid local optima.
The run with the highest marginal log-likelihood is selected.
After convergence, observations are assigned to classes via MAP
(maximum a posteriori), and a standard metafrontier is fitted on the
MAP classes.
An object of class "lc_metafrontier" containing:
MAP class assignment per observation
n x C matrix of posterior probabilities
class mixing proportions
list of class-specific parameter vectors
list of class-specific model summaries
the fitted metafrontier object on MAP classes
marginal log-likelihood at convergence
Bayesian Information Criterion
number of classes
number of EM iterations used
sim <- simulate_metafrontier(n_groups = 2, n_per_group = 80, seed = 42) lc <- latent_class_metafrontier( log_y ~ log_x1 + log_x2, data = sim$data, n_classes = 2, n_starts = 3, seed = 123 ) print(lc) summary(lc) coef(lc, which = "meta") efficiencies(lc, type = "tgr")sim <- simulate_metafrontier(n_groups = 2, n_per_group = 80, seed = 42) lc <- latent_class_metafrontier( log_y ~ log_x1 + log_x2, data = sim$data, n_classes = 2, n_starts = 3, seed = 123 ) print(lc) summary(lc) coef(lc, which = "meta") efficiencies(lc, type = "tgr")
Computes the metafrontier Malmquist total factor productivity (TFP) index and its three-way decomposition into technical efficiency change (TEC), technology gap change (TGC), and metafrontier technical change (TC*) for panel data, following O'Donnell, Rao, and Battese (2008).
malmquist_meta( formula = NULL, data = NULL, group = NULL, time = NULL, method = c("dea", "sfa"), dist = c("hnormal", "tnormal", "exponential"), orientation = c("output", "input"), rts = c("crs", "vrs", "drs", "irs"), control = list(), ... )malmquist_meta( formula = NULL, data = NULL, group = NULL, time = NULL, method = c("dea", "sfa"), dist = c("hnormal", "tnormal", "exponential"), orientation = c("output", "input"), rts = c("crs", "vrs", "drs", "irs"), control = list(), ... )
formula |
an object of class |
data |
a data frame containing all variables, plus the grouping and time variables. |
group |
a character string naming the column in |
time |
a character string naming the column in |
method |
character. |
dist |
character. Distribution of the inefficiency term
when |
orientation |
character. |
rts |
character. Returns to scale assumption:
|
control |
a list of control parameters for the SFA optimiser. |
... |
additional arguments (currently unused). |
The metafrontier Malmquist TFP index decomposes productivity change into three components:
where:
: technical
efficiency change relative to the group frontier
: technology gap change,
capturing whether a group's frontier is catching up to or
falling behind the metafrontier
: metafrontier technical change, measuring
the shift of the global production possibility frontier
Computation uses DEA-based distance functions. For each
consecutive pair of periods , eight sets of LP
problems are solved: within-group and pooled efficiencies at
each period, plus cross-period evaluations for the geometric
mean formulation of technical change.
Balanced panel assumption: Firms are matched across
periods by position within each group. The data should contain
a balanced panel (the same firms observed in every period) with
consistent ordering. If group sizes differ across periods,
only the first min(n_s, n_t) firms per group are paired
and unmatched observations are silently dropped.
An object of class "malmquist_meta", a list
with components:
data frame with columns: id,
group, period_from, period_to,
MPI (metafrontier Malmquist TFP index),
TEC (technical efficiency change),
TGC (technology gap change),
TC (metafrontier technical change)
data frame with the within-group
Malmquist index decomposition: MPI_group,
EC_group, TC_group
data frame with the metafrontier
Malmquist index: MPI_meta, EC_meta,
TC_meta
data frame with technology gap ratios at each
period endpoint: id, group,
period_from, period_to, TGR_from
(TGR at the start period), TGR_to (TGR at the
end period), and TGC (technology gap change,
TGR_to / TGR_from)
the matched function call
the orientation used
the returns to scale assumption
group labels
time periods
O'Donnell, C.J., Rao, D.S.P. and Battese, G.E. (2008). Metafrontier frameworks for the study of firm-level efficiencies and technology ratios. Empirical Economics, 34(2), 231–255. doi:10.1007/s00181-007-0119-4
# Simulate panel data for 2 groups, 3 time periods set.seed(42) panels <- lapply(1:3, function(t) { sim <- simulate_metafrontier( n_groups = 2, n_per_group = 30, tech_gap = c(0, 0.3 + 0.05 * t), sigma_u = c(0.2, 0.3), seed = 42 + t ) sim$data$time <- t sim$data$id <- seq_len(nrow(sim$data)) sim$data }) panel_data <- do.call(rbind, panels) # Compute metafrontier Malmquist index malm <- malmquist_meta( log_y ~ log_x1 + log_x2, data = panel_data, group = "group", time = "time" ) summary(malm)# Simulate panel data for 2 groups, 3 time periods set.seed(42) panels <- lapply(1:3, function(t) { sim <- simulate_metafrontier( n_groups = 2, n_per_group = 30, tech_gap = c(0, 0.3 + 0.05 * t), sigma_u = c(0.2, 0.3), seed = 42 + t ) sim$data$time <- t sim$data$id <- seq_len(nrow(sim$data)) sim$data }) panel_data <- do.call(rbind, panels) # Compute metafrontier Malmquist index malm <- malmquist_meta( log_y ~ log_x1 + log_x2, data = panel_data, group = "group", time = "time" ) summary(malm)
Estimates group-specific frontiers and a metafrontier that envelops all group technologies. Supports both SFA-based (parametric) and DEA-based (nonparametric) approaches, with deterministic (Battese, Rao, and O'Donnell, 2004) or stochastic (Huang, Huang, and Liu, 2014) metafrontier estimation.
metafrontier( formula = NULL, data = NULL, group = NULL, method = c("sfa", "dea"), meta_type = c("deterministic", "stochastic"), dist = c("hnormal", "tnormal", "exponential"), orientation = c("output", "input"), rts = c("crs", "vrs", "drs", "irs"), models = NULL, panel = NULL, panel_dist = c("bc92", "bc95"), type = c("radial", "directional"), direction = c("proportional", "output", "input"), control = list(), ... )metafrontier( formula = NULL, data = NULL, group = NULL, method = c("sfa", "dea"), meta_type = c("deterministic", "stochastic"), dist = c("hnormal", "tnormal", "exponential"), orientation = c("output", "input"), rts = c("crs", "vrs", "drs", "irs"), models = NULL, panel = NULL, panel_dist = c("bc92", "bc95"), type = c("radial", "directional"), direction = c("proportional", "output", "input"), control = list(), ... )
formula |
an object of class |
data |
a data frame containing all variables in the formula
and the grouping variable. Ignored if |
group |
a character string naming the column in |
method |
character. The frontier estimation method for
group-specific models: |
meta_type |
character. The method for estimating the
metafrontier: |
dist |
character. Distribution of the one-sided inefficiency
term in SFA models. One of |
orientation |
character. For DEA: |
rts |
character. Returns to scale for DEA: |
models |
an optional named list of pre-fitted group-specific
frontier models (objects from sfaR, frontier, or
Benchmarking). If provided, |
panel |
an optional list with components |
panel_dist |
character. Panel SFA model: |
type |
character. For DEA: |
direction |
character. Direction vector for DDF:
|
control |
a named list of control parameters passed to
|
... |
additional arguments passed to the group-level estimation functions. |
The metafrontier framework decomposes efficiency relative to a global technology into two components:
where is efficiency relative to the group frontier and
is the technology gap ratio measuring how close the
group frontier is to the metafrontier.
The deterministic metafrontier (Battese, Rao, and O'Donnell, 2004)
is estimated by solving a linear program that minimises the total
envelope overshoot subject to the constraint that the metafrontier
envelops all group frontiers. BRO (2004) originally proposed a
constrained least-squares (QP) formulation; the LP yields the
tightest envelope and is solved via lpSolveAPI, with a QP
fallback via constrOptim() when the LP is infeasible.
The stochastic metafrontier (Huang, Huang, and Liu, 2014) replaces
this with a second-stage SFA, providing a distributional framework
for inference on the TGR.
Note on standard errors (stochastic metafrontier):
The stochastic metafrontier is a two-stage estimator. Stage 2 treats
the fitted group frontier values as data, so the reported standard
errors, confidence intervals, and variance-covariance matrix do not
account for estimation uncertainty from Stage 1 (the
generated-regressor problem; see Murphy and Topel, 1985). Use
vcov(fit, correction = "murphy-topel") or bootstrap-based
confidence intervals via boot_tgr for corrected
inference.
Note on frontier orientation (SFA path):
The SFA estimation path assumes a production frontier
(). Cost frontiers ()
are not currently supported via the SFA path. The DEA path supports
both orientation = "output" and orientation = "input".
An object of class "metafrontier" (with subclass
"metafrontier_sfa" or "metafrontier_dea"),
containing:
the matched function call
list of fitted group-specific models
estimated metafrontier parameters
list of group-specific coefficient vectors
technology gap ratios for each observation
group-specific technical efficiency
metafrontier technical efficiency (TE* = TE x TGR)
log-likelihoods of group models
number of observations per group and total
group labels
estimation method used
metafrontier type used
convergence status
Battese, G.E., Rao, D.S.P. and O'Donnell, C.J. (2004). A metafrontier production function for estimation of technical efficiencies and technology gaps for firms operating under different technologies. Journal of Productivity Analysis, 21(1), 91–103. doi:10.1023/B:PROD.0000012454.06094.29
Huang, C.J., Huang, T.-H. and Liu, N.-H. (2014). A new approach to estimating the metafrontier production function based on a stochastic frontier framework. Journal of Productivity Analysis, 42(3), 241–254. doi:10.1007/s11123-014-0402-2
O'Donnell, C.J., Rao, D.S.P. and Battese, G.E. (2008). Metafrontier frameworks for the study of firm-level efficiencies and technology ratios. Empirical Economics, 34(2), 231–255. doi:10.1007/s00181-007-0119-4
# Simulate metafrontier data set.seed(42) sim <- simulate_metafrontier(n_groups = 2, n_per_group = 100) # Estimate deterministic SFA metafrontier (BRO 2004) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", method = "sfa", meta_type = "deterministic") summary(fit) # Technology gap ratios tgr <- technology_gap_ratio(fit) summary(tgr)# Simulate metafrontier data set.seed(42) sim <- simulate_metafrontier(n_groups = 2, n_per_group = 100) # Estimate deterministic SFA metafrontier (BRO 2004) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", method = "sfa", meta_type = "deterministic") summary(fit) # Technology gap ratios tgr <- technology_gap_ratio(fit) summary(tgr)
Produces diagnostic and summary plots for a fitted metafrontier model.
## S3 method for class 'metafrontier' plot(x, which = c("tgr", "efficiency", "decomposition", "frontier"), ...)## S3 method for class 'metafrontier' plot(x, which = c("tgr", "efficiency", "decomposition", "frontier"), ...)
x |
a |
which |
character. Type of plot to produce:
|
... |
additional graphical parameters passed to base plotting functions. |
Invisibly returns x.
set.seed(42) sim <- simulate_metafrontier(n_groups = 2, n_per_group = 100) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") plot(fit, which = "tgr") plot(fit, which = "decomposition")set.seed(42) sim <- simulate_metafrontier(n_groups = 2, n_per_group = 100) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") plot(fit, which = "tgr") plot(fit, which = "decomposition")
Tests the null hypothesis that all groups share a common frontier (i.e., the metafrontier coincides with all group frontiers) against the alternative that group-specific frontiers differ. Uses a likelihood ratio test.
poolability_test(object, ...)poolability_test(object, ...)
object |
a fitted |
... |
additional arguments (currently unused). |
The LR statistic is:
where is the log-likelihood of the pooled (single
frontier) model and are the group-specific
log-likelihoods. Under H0, the statistic follows a chi-squared
distribution with degrees of freedom equal to
, where is the
total number of parameters across all group-specific models and
is the number of parameters in the pooled model.
For groups each with frontier parameters plus
distributional parameters, this equals
where includes
frontier coefficients, , and
(and for truncated-normal).
A list of class "htest" with components:
the LR test statistic
degrees of freedom
p-value of the test
description of the test
set.seed(42) sim <- simulate_metafrontier(n_groups = 2, n_per_group = 200, tech_gap = c(0, 0.5)) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") poolability_test(fit)set.seed(42) sim <- simulate_metafrontier(n_groups = 2, n_per_group = 200, tech_gap = c(0, 0.5)) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") poolability_test(fit)
Computes predicted frontier values at given input levels using either the metafrontier or a group-specific frontier.
## S3 method for class 'metafrontier' predict(object, newdata = NULL, type = c("meta", "group"), ...)## S3 method for class 'metafrontier' predict(object, newdata = NULL, type = c("meta", "group"), ...)
object |
a |
newdata |
an optional data frame of new inputs. If omitted, the training data predictions are returned. |
type |
character. |
... |
additional arguments (currently unused). |
A numeric vector of predicted frontier values.
sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") pred <- predict(fit) # Out-of-sample prediction: newdata <- data.frame(log_x1 = c(1, 2), log_x2 = c(1.5, 2.5)) predict(fit, newdata = newdata)sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") pred <- predict(fit) # Out-of-sample prediction: newdata <- data.frame(log_x1 = c(1, 2), log_x2 = c(1.5, 2.5)) predict(fit, newdata = newdata)
Print a Metafrontier Object
## S3 method for class 'metafrontier' print(x, ...)## S3 method for class 'metafrontier' print(x, ...)
x |
a |
... |
additional arguments (currently unused). |
Invisibly returns x.
sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") print(fit)sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") print(fit)
Select Number of Latent Classes via BIC
select_n_classes(formula, data, n_classes_range = 2:5, ...)select_n_classes(formula, data, n_classes_range = 2:5, ...)
formula |
formula. |
data |
data frame. |
n_classes_range |
integer vector of class counts to try. |
... |
additional arguments passed to
|
Fits latent class metafrontier models for each value in
n_classes_range and returns BIC values. The optimal
number of classes minimises BIC.
A data frame with columns n_classes, BIC,
and marginal_ll.
sim <- simulate_metafrontier(n_groups = 2, n_per_group = 80, seed = 42) bic_table <- select_n_classes( log_y ~ log_x1 + log_x2, data = sim$data, n_classes_range = 2:3, n_starts = 3, seed = 42 ) print(bic_table)sim <- simulate_metafrontier(n_groups = 2, n_per_group = 80, seed = 42) bic_table <- select_n_classes( log_y ~ log_x1 + log_x2, data = sim$data, n_classes_range = 2:3, n_starts = 3, seed = 42 ) print(bic_table)
Generates synthetic data from a known metafrontier data-generating process. Useful for Monte Carlo simulations, package testing, and teaching.
simulate_metafrontier( n_groups = 2L, n_per_group = 100L, n_inputs = 2L, beta_meta = NULL, tech_gap = NULL, sigma_u = NULL, sigma_v = 0.2, seed = NULL )simulate_metafrontier( n_groups = 2L, n_per_group = 100L, n_inputs = 2L, beta_meta = NULL, tech_gap = NULL, sigma_u = NULL, sigma_v = 0.2, seed = NULL )
n_groups |
integer. Number of technology groups (default 2). |
n_per_group |
integer or integer vector. Number of observations
per group. If a single value, the same number is used for all
groups. If a vector, must be of length |
n_inputs |
integer. Number of input variables (default 2). |
beta_meta |
numeric vector. Metafrontier coefficients
(including intercept). Length must be |
tech_gap |
numeric vector of length |
sigma_u |
numeric vector of length |
sigma_v |
numeric. Standard deviation of the symmetric noise term. Default: 0.2. |
seed |
integer or |
A list with components:
a data frame with columns log_y, log_x1,
log_x2, ..., group, and the true underlying values
a list of the true parameters used for generation
sim <- simulate_metafrontier(n_groups = 3, n_per_group = 200, sigma_u = c(0.2, 0.4, 0.3)) str(sim$data) table(sim$data$group) # The true metafrontier coefficients sim$params$beta_metasim <- simulate_metafrontier(n_groups = 3, n_per_group = 200, sigma_u = c(0.2, 0.4, 0.3)) str(sim$data) table(sim$data$group) # The true metafrontier coefficients sim$params$beta_meta
Generates a simulated panel dataset with known metafrontier parameters for Monte Carlo studies and testing. Implements the Battese-Coelli 1992 DGP with time-varying inefficiency.
simulate_panel_metafrontier( n_groups = 2, n_firms_per_group = 30, n_periods = 5, beta_meta = c(1, 0.5, 0.3), tech_gap = NULL, sigma_u = 0.3, sigma_v = 0.2, eta = 0.05, seed = NULL )simulate_panel_metafrontier( n_groups = 2, n_firms_per_group = 30, n_periods = 5, beta_meta = c(1, 0.5, 0.3), tech_gap = NULL, sigma_u = 0.3, sigma_v = 0.2, eta = 0.05, seed = NULL )
n_groups |
integer. Number of technology groups. |
n_firms_per_group |
integer. Number of firms per group. |
n_periods |
integer. Number of time periods. |
beta_meta |
numeric vector. Metafrontier coefficients. |
tech_gap |
numeric vector of group technology gaps. |
sigma_u |
numeric. Standard deviation of the firm effect. |
sigma_v |
numeric. Standard deviation of noise. |
eta |
numeric. Time-decay parameter for BC92. |
seed |
integer or NULL. Random seed. |
A list with components:
data frame with columns: firm, year,
group, log_y, log_x1, log_x2,
true_te, true_u, true_v
list of true parameter values used in generation
sim <- simulate_panel_metafrontier( n_groups = 2, n_firms_per_group = 20, n_periods = 5, seed = 42 ) head(sim$data) str(sim$params)sim <- simulate_panel_metafrontier( n_groups = 2, n_firms_per_group = 20, n_periods = 5, seed = 42 ) head(sim$data) str(sim$params)
Summary of a Metafrontier Model
## S3 method for class 'metafrontier' summary(object, ...)## S3 method for class 'metafrontier' summary(object, ...)
object |
a |
... |
additional arguments (currently unused). |
An object of class "summary.metafrontier".
sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") s <- summary(fit) print(s)sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") s <- summary(fit) print(s)
Extracts the technology gap ratios (TGR) from a fitted metafrontier model. The TGR measures how close a group's production frontier is to the global metafrontier at each observation's input mix.
technology_gap_ratio(object, by_group = TRUE, ...)technology_gap_ratio(object, by_group = TRUE, ...)
object |
a fitted |
by_group |
logical. If |
... |
additional arguments (currently unused). |
The technology gap ratio is defined as:
for SFA-based metafrontiers, and
for DEA-based metafrontiers.
Under the deterministic metafrontier and DEA, TGR lies in (0, 1] by construction. Under the stochastic metafrontier of Huang, Huang, and Liu (2014), TGR can exceed 1 for some observations because the metafrontier need not envelop the group frontiers at every point.
A TGR of 1 means the group frontier coincides with the metafrontier at that input mix. Values less than 1 indicate a technology gap.
If by_group = TRUE, a named list of numeric vectors.
If by_group = FALSE, a numeric vector of length
nobs(object).
metafrontier, efficiencies.metafrontier
set.seed(42) sim <- simulate_metafrontier(n_groups = 2, n_per_group = 100) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") tgr <- technology_gap_ratio(fit) lapply(tgr, summary)set.seed(42) sim <- simulate_metafrontier(n_groups = 2, n_per_group = 100) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group") tgr <- technology_gap_ratio(fit) lapply(tgr, summary)
Prints a summary table of TGR statistics by group.
tgr_summary(object, ...)tgr_summary(object, ...)
object |
a fitted |
... |
additional arguments (currently unused). |
A data frame with columns: Group, N, Mean, SD, Min, Q1, Median, Q3, Max.
Variance-Covariance Matrix for Metafrontier Coefficients
## S3 method for class 'metafrontier' vcov(object, correction = c("none", "murphy-topel"), ...)## S3 method for class 'metafrontier' vcov(object, correction = c("none", "murphy-topel"), ...)
object |
a |
correction |
character. |
... |
additional arguments (currently unused). |
A variance-covariance matrix, or NULL if unavailable.
Murphy, K.M. and Topel, R.H. (1985). Estimation and inference in two-step econometric models. Journal of Business & Economic Statistics, 3(4), 370–379.
sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") vcov(fit) vcov(fit, correction = "murphy-topel")sim <- simulate_metafrontier(n_groups = 2, n_per_group = 50, seed = 42) fit <- metafrontier(log_y ~ log_x1 + log_x2, data = sim$data, group = "group", meta_type = "stochastic") vcov(fit) vcov(fit, correction = "murphy-topel")