
A Comprehensive Guide to Fractional Response Regressions with fracreg
Sulman Olieko Owili
2026-08-08
fracreg_tutorial.RmdIntroduction
The fracreg package is the most
comprehensive tool available in R for estimating, diagnosing, and
interpreting fractional response models. Originally focused on standard
cross-sectional models, it has been substantially expanded to provide a
complete suite of fractional response methodologies. The package
supports:
-
Cross-Sectional Models (
fracreg): Includes one-part models (1P) for standard fractions, two-part hurdle models (2P) for fractions with boundaries at 0 or 1, and three-part double-inflated models (3P) for inflation at both boundaries. -
Panel Data Models (
fracregpd): Utilises Correlated Random Effects (CRE), Quasi-Maximum Likelihood (QML), and Generalised Method of Moments (GMM) approaches for longitudinal data. -
Endogeneity Correction (
fracreghet): Corrects for endogenous covariates using Control Function and IV-GMM approaches. -
Fractional Multinomial Logit
(
fracregmlogit): Models multivariate fractional outcomes where multiple fractions sum to 1. -
Fractional Ridge Regression
(
fracregridge): Incorporates L2 regularization dynamically controlled by the fraction of the unregularized coefficient vector length.
This vignette walks you through comprehensive empirical examples (using the built-in 401(k) and spending datasets) and simulated examples for each estimator. We provide detailed explanations of why each model is used and how to interpret the associated outputs.
1. Data Description and Preparation
We use the built-in fracreg_k401k dataset to demonstrate
univariate fractional models. This is the canonical firm-level 401(k)
plan participation data used in Papke and Wooldridge
(1996) (“Econometric methods for fractional response
variables with an application to 401(k) plan participation rates”,
Journal of Applied Econometrics). The dataset contains 1,534
observations of 401(k) plans.
The primary variables we use are: - prate: The plan
participation rate (the fraction of eligible employees who are active
participants). It strictly falls in the
interval and serves as our dependent variable
().
- mrate: The firm’s matching rate (the firm’s contribution
per $1 of employee contribution). - age: The age of the
401(k) plan. - totemp: Total number of employees at the
firm. - sole: A binary indicator equal to 1 if the 401(k)
plan is the sole retirement plan offered by the firm.
2. Cross-Sectional Fractional Models (fracreg)
The core fracreg() function is designed for univariate
models where the dependent variable is bounded between 0 and 1 inclusive
().
We explore how to fit 1P, 2P, and 3P models using both the empirical
401(k) data and simulated data with strict boundaries.
2.1 Empirical and Simulated Fractional Regressions
In this section, we start with a standard 1-part (1P) fractional
logit model to estimate participation rates in the 401(k) data. Since we
might also be interested in multiplicative effects, we show how to
extract odds ratios (or=TRUE). Next, we demonstrate how to
tackle boundary inflation. For example, some firms might have 100%
participation (prate = 1), so we fit a 2-part model
(inflation=1).
The simulated section further demonstrates generating artificial
inflation at exactly 0 and 1. We then isolate the components of the
2-part model (using type="2Pbin" and
type="2Pfrac") and fit full 3-part models.
### Empirical 401(k) Examples
data("fracreg_k401k")
y <- fracreg_k401k$prate
X <- cbind(mrate = fracreg_k401k$mrate, age = fracreg_k401k$age,
totemp = fracreg_k401k$totemp, sole = fracreg_k401k$sole)
# 1P Model
mod <- fracreg(y, X, type="1P", linkfrac="logit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: QML
#> Convergence: Successful
#> Number of observations: 1534
#> Log pseudolikelihood: -553.1626
#> Pseudo R-squared: 0.14667
#> Wald chi2(4): 147.3049
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Quasi-Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval]
#> (Intercept) 9.316e-01 8.408e-02 1.108e+01 7.668e-01 1.096
#> mrate 9.531e-01 1.371e-01 6.951e+00 6.843e-01 1.222
#> age 2.791e-02 4.877e-03 5.723e+00 1.835e-02 0.037
#> totemp -8.182e-06 3.061e-06 -2.673e+00 -1.418e-05 0.000
#> sole 3.405e-01 8.066e-02 4.222e+00 1.824e-01 0.499
#> Pr(>|z|)
#> (Intercept) < 2e-16 ***
#> mrate 3.62e-12 ***
#> age 1.05e-08 ***
#> totemp 0.00751 **
#> sole 2.43e-05 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:37
#> --------------------------------------------------------------------------------
# 1P Model reporting odds ratios and 99% confidence intervals
mod <- fracreg(y, X, type="1P", linkfrac="logit", or=TRUE, level=0.99)
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: QML
#> Convergence: Successful
#> Number of observations: 1534
#> Log pseudolikelihood: -553.1626
#> Pseudo R-squared: 0.14667
#> Wald chi2(4): 147.3049
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Quasi-Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Odds Ratio Robust Std.Err. z value [99% Conf. Interval] Pr(>|z|)
#> (Intercept) 2.539e+00 2.134e-01 1.108e+01 2.044e+00 3.153 < 2e-16
#> mrate 2.594e+00 3.556e-01 6.951e+00 1.822e+00 3.692 3.62e-12
#> age 1.028e+00 5.015e-03 5.723e+00 1.015e+00 1.041 1.05e-08
#> totemp 1.000e+00 3.061e-06 -2.673e+00 1.000e+00 1.000 0.00751
#> sole 1.406e+00 1.134e-01 4.222e+00 1.142e+00 1.730 2.43e-05
#>
#> (Intercept) ***
#> mrate ***
#> age ***
#> totemp **
#> sole ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:37
#> --------------------------------------------------------------------------------
# 2P Model (modelling mass at 1)
mod <- fracreg(y, X, type="2P", inflation=1, linkbin="logit", linkfrac="logit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Part 1: Binary logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: ML
#> Convergence: Successful
#> Number of observations: 1534
#> Log-likelihood: -938.1759
#> Pseudo R-squared: 0.1485
#> Wald chi2(4): 173.5169
#> Prob > chi2: 0.0000
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient EIM Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) -1.396e+00 1.270e-01 -1.099e+01 -1.645e+00 -1.147 <2e-16
#> mrate 9.053e-01 9.699e-02 9.334e+00 7.152e-01 1.095 <2e-16
#> age 1.156e-02 6.218e-03 1.858e+00 -6.312e-04 0.024 0.0631
#> totemp -1.418e-05 6.324e-06 -2.242e+00 -2.657e-05 0.000 0.0249
#> sole 8.651e-01 1.131e-01 7.651e+00 6.435e-01 1.087 2e-14
#>
#> (Intercept) ***
#> mrate ***
#> age .
#> totemp *
#> sole ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#>
#>
#> --------------------------------------------------------------------------------
#> Part 2: Fractional logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: QML
#> Convergence: Successful
#> Number of observations: 852
#> Log pseudolikelihood: -450.8391
#> Pseudo R-squared: 0.10004
#> Wald chi2(4): 65.4063
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Quasi-Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval]
#> (Intercept) 7.460e-01 6.850e-02 1.089e+01 6.118e-01 0.880
#> mrate 3.877e-01 9.725e-02 3.987e+00 1.971e-01 0.578
#> age 2.562e-02 4.010e-03 6.390e+00 1.777e-02 0.033
#> totemp -4.061e-06 3.073e-06 -1.322e+00 -1.008e-05 0.000
#> sole -1.510e-02 6.556e-02 -2.303e-01 -1.436e-01 0.113
#> Pr(>|z|)
#> (Intercept) < 2e-16 ***
#> mrate 6.69e-05 ***
#> age 1.66e-10 ***
#> totemp 0.186
#> sole 0.818
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#>
#>
#> --------------------------------------------------------------------------------
#> Two-part fractional regression: binary logit + fractional logit
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Convergence: Successful
#> Pseudo R-squared: 0.11243
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:37
#> --------------------------------------------------------------------------------
# 3P Model (inject artificial 0s for demonstration)
y_3p <- y; y_3p[1:50] <- 0
mod <- fracreg(y_3p, X, type="3P", linkbin=c("logit","logit"), linkfrac="logit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Part 1: Binary logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: ML
#> Convergence: Successful
#> Number of observations: 1534
#> Log-likelihood: -216.6222
#> Pseudo R-squared: 0.00324
#> Wald chi2(4): 3.7679
#> Prob > chi2: 0.4383
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient EIM Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) 2.867e+00 3.157e-01 9.080e+00 2.248e+00 3.486 <2e-16
#> mrate 1.147e-01 2.131e-01 5.381e-01 -3.030e-01 0.532 0.590
#> age 8.375e-03 1.765e-02 4.745e-01 -2.622e-02 0.043 0.635
#> totemp 1.036e-04 6.959e-05 1.489e+00 -3.275e-05 0.000 0.136
#> sole 3.371e-01 2.983e-01 1.130e+00 -2.476e-01 0.922 0.259
#>
#> (Intercept) ***
#> mrate
#> age
#> totemp
#> sole
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#>
#>
#> --------------------------------------------------------------------------------
#> Part 2: Binary logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: ML
#> Convergence: Successful
#> Number of observations: 1484
#> Log-likelihood: -903.5457
#> Pseudo R-squared: 0.15199
#> Wald chi2(4): 172.201
#> Prob > chi2: 0.0000
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient EIM Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) -1.435e+00 1.306e-01 -1.099e+01 -1.691e+00 -1.179 < 2e-16
#> mrate 9.244e-01 9.877e-02 9.360e+00 7.309e-01 1.118 < 2e-16
#> age 1.198e-02 6.339e-03 1.890e+00 -4.453e-04 0.024 0.0588
#> totemp -1.371e-05 6.317e-06 -2.170e+00 -2.609e-05 0.000 0.0300
#> sole 8.852e-01 1.154e-01 7.674e+00 6.591e-01 1.111 1.67e-14
#>
#> (Intercept) ***
#> mrate ***
#> age .
#> totemp *
#> sole ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#>
#>
#> --------------------------------------------------------------------------------
#> Part 3: Fractional logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: QML
#> Convergence: Successful
#> Number of observations: 826
#> Log pseudolikelihood: -437.3715
#> Pseudo R-squared: 0.09937
#> Wald chi2(4): 62.3685
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Quasi-Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval]
#> (Intercept) 7.388e-01 7.039e-02 1.050e+01 6.008e-01 0.877
#> mrate 3.960e-01 1.019e-01 3.885e+00 1.962e-01 0.596
#> age 2.531e-02 4.068e-03 6.223e+00 1.734e-02 0.033
#> totemp -3.817e-06 3.088e-06 -1.236e+00 -9.869e-06 0.000
#> sole -4.483e-03 6.672e-02 -6.719e-02 -1.353e-01 0.126
#> Pr(>|z|)
#> (Intercept) < 2e-16 ***
#> mrate 0.000102 ***
#> age 4.88e-10 ***
#> totemp 0.216472
#> sole 0.946434
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#>
#>
#> --------------------------------------------------------------------------------
#> Three-part fractional regression: binary logit , binary logit + fractional logit
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Convergence: Successful
#> Pseudo R-squared: 0.07934
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
### Simulated Examples
set.seed(123)
N <- 1000
x1 <- rnorm(N)
x2 <- runif(N)
# Generating a fractional dependent variable with inflation at 0 and 1
XB <- -0.5 + 0.8 * x1 + 1.2 * x2 + rnorm(N)
y_latent <- exp(XB) / (1 + exp(XB))
y <- y_latent
# Inflate at boundaries
y[y_latent < 0.2] <- 0
y[y_latent > 0.8] <- 1
X <- cbind(x1 = x1, x2 = x2)
# fracreg estimation of a logit fractional response model
mod <- fracreg(y, X, type="1P", linkfrac="logit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: QML
#> Convergence: Successful
#> Number of observations: 1000
#> Log pseudolikelihood: -614.973
#> Pseudo R-squared: 0.3903
#> Wald chi2(2): 472.2453
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Quasi-Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) -0.56969 0.06750 -8.43960 -0.70199 -0.437 <2e-16
#> x1 0.78822 0.04015 19.63424 0.70954 0.867 <2e-16
#> x2 1.35611 0.11899 11.39668 1.12289 1.589 <2e-16
#>
#> (Intercept) ***
#> x1 ***
#> x2 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
2.1.2 Binary Logit Component of a Two-Part Model
Here, we estimate the binary (hurdle) component of a two-part
fractional regression model. We specify type="2Pbin", which
instructs the function to model the probability of observing a
non-boundary value versus the boundary value (in this case, 0). The
inflation=0 argument explicitly sets 0 as the relevant
boundary.
# Estimate the binary logit component
mod <- fracreg(y, X, type="2Pbin", inflation=0, linkbin="logit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Part 1: Binary logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: ML
#> Convergence: Successful
#> Number of observations: 1000
#> Log-likelihood: -295.2068
#> Pseudo R-squared: 0.14527
#> Wald chi2(2): 102.5171
#> Prob > chi2: 0.0000
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient EIM Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) 1.4638 0.1933 7.5732 1.0849 1.843 3.64e-14 ***
#> x1 1.1857 0.1287 9.2126 0.9335 1.438 < 2e-16 ***
#> x2 2.2279 0.3932 5.6662 1.4572 2.999 1.46e-08 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
2.1.3 Fractional Component of a Two-Part Model
After modelling the hurdle, we estimate the continuous fractional
component using type="2Pfrac". This component only uses
observations that are strictly bounded away from the inflated boundary
().
In this example, we apply a probit link function to
model the fractional values.
# Estimate the fractional component using a probit link
mod <- fracreg(y, X, type="2Pfrac", inflation=0, linkfrac="probit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Part 2: Fractional probit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: QML
#> Convergence: Successful
#> Number of observations: 881
#> Log pseudolikelihood: -555.3304
#> Pseudo R-squared: 0.32474
#> Wald chi2(2): 391.6944
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Quasi-Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) -0.10334 0.03566 -2.89793 -0.17323 -0.033 0.00376
#> x1 0.37512 0.02129 17.62293 0.33340 0.417 < 2e-16
#> x2 0.61326 0.06529 9.39237 0.48529 0.741 < 2e-16
#>
#> (Intercept) **
#> x1 ***
#> x2 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
2.1.4 Full Two-Part Model (Joint Estimation)
Alternatively, we can estimate both the binary and fractional
components simultaneously by specifying type="2P". Here we
use different link functions for each part: a cloglog
link for the binary hurdle (which is useful for asymmetric data) and a
logit link for the fractional continuous part.
# Estimate both components jointly
mod <- fracreg(y, X, type="2P", inflation=0, linkbin="cloglog", linkfrac="logit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Part 1: Binary cloglog regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: ML
#> Convergence: Successful
#> Number of observations: 1000
#> Log-likelihood: -291.7986
#> Pseudo R-squared: 0.14837
#> Wald chi2(2): 100.5683
#> Prob > chi2: 0.0000
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient EIM Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) 0.43428 0.08825 4.92113 0.26132 0.607 8.60e-07 ***
#> x1 0.55192 0.06009 9.18429 0.43414 0.670 < 2e-16 ***
#> x2 1.05359 0.17403 6.05409 0.71250 1.395 1.41e-09 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#>
#>
#> --------------------------------------------------------------------------------
#> Part 2: Fractional logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: QML
#> Convergence: Successful
#> Number of observations: 881
#> Log pseudolikelihood: -555.4465
#> Pseudo R-squared: 0.32412
#> Wald chi2(2): 368.0384
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Quasi-Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) -0.17323 0.05786 -2.99384 -0.28664 -0.060 0.00275
#> x1 0.61205 0.03554 17.22078 0.54239 0.682 < 2e-16
#> x2 1.00509 0.10703 9.39074 0.79531 1.215 < 2e-16
#>
#> (Intercept) **
#> x1 ***
#> x2 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#>
#>
#> --------------------------------------------------------------------------------
#> Two-part fractional regression: binary cloglog + fractional logit
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Convergence: Successful
#> Pseudo R-squared: 0.38829
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
2.1.5 Three-Part Double-Inflated Model
When the data exhibits inflation at both 0 and 1, a
three-part model (type="3P") is required. This models the
probability of observing 0, the probability of observing 1, and the
continuous fractional outcomes in between. We pass a vector of link
functions c("logit", "probit") for the binary components,
alongside the logit fractional link.
# Three-part double-inflated model
mod <- fracreg(y, X, type="3P", linkbin=c("logit","probit"), linkfrac="logit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Part 1: Binary logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: ML
#> Convergence: Successful
#> Number of observations: 1000
#> Log-likelihood: -295.2068
#> Pseudo R-squared: 0.14527
#> Wald chi2(2): 102.5171
#> Prob > chi2: 0.0000
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient EIM Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) 1.4638 0.1933 7.5732 1.0849 1.843 3.64e-14 ***
#> x1 1.1857 0.1287 9.2126 0.9335 1.438 < 2e-16 ***
#> x2 2.2279 0.3932 5.6662 1.4572 2.999 1.46e-08 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#>
#>
#> --------------------------------------------------------------------------------
#> Part 2: Binary probit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: ML
#> Convergence: Successful
#> Number of observations: 881
#> Log-likelihood: -348.8644
#> Pseudo R-squared: 0.18634
#> Wald chi2(2): 123.5731
#> Prob > chi2: 0.0000
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient EIM Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) -1.71537 0.12933 -13.26354 -1.96885 -1.462 < 2e-16
#> x1 0.64810 0.06323 10.25024 0.52418 0.772 < 2e-16
#> x2 1.07752 0.19174 5.61978 0.70172 1.453 1.91e-08
#>
#> (Intercept) ***
#> x1 ***
#> x2 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#>
#>
#> --------------------------------------------------------------------------------
#> Part 3: Fractional logit regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: QML
#> Convergence: Successful
#> Number of observations: 715
#> Log pseudolikelihood: -484.9654
#> Pseudo R-squared: 0.24292
#> Wald chi2(2): 261.436
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> Small sample correction: FALSE
#> --------------------------------------------------------------------------------
#> Final Quasi-Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) -0.26763 0.04539 -5.89578 -0.35660 -0.179 3.73e-09
#> x1 0.36198 0.02454 14.75144 0.31389 0.410 < 2e-16
#> x2 0.58505 0.07969 7.34179 0.42886 0.741 2.11e-13
#>
#> (Intercept) ***
#> x1 ***
#> x2 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#>
#>
#> --------------------------------------------------------------------------------
#> Three-part fractional regression: binary logit , binary probit + fractional logit
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Convergence: Successful
#> Pseudo R-squared: 0.38917
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
2.2 Partial Effects (fracreg.pe)
Because fractional models are inherently non-linear, raw coefficients
cannot be interpreted directly as constant marginal effects. The
fracreg.pe() function computes the actual marginal effects.
We can compute Average Partial Effects (APE) across all observations or
Conditional Partial Effects (CPE) evaluated at specific covariate values
(e.g., holding covariates at their median). The examples below
demonstrate how to extract these effects across standard, 2-part, and
3-part models.
### Empirical 401(k) Examples
data("fracreg_k401k")
y <- fracreg_k401k$prate
X <- cbind(mrate = fracreg_k401k$mrate, age = fracreg_k401k$age,
totemp = fracreg_k401k$totemp, sole = fracreg_k401k$sole)
m <- fracreg(y, X, type="1P", linkfrac="logit")
pe_res <- fracreg.pe(m)
summary(pe_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Average partial effects
#> --------------------------------------------------------------------------------
#> Fractional logit regression
#> --------------------------------------------------------------------------------
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> mrate 1.018e-01 1.456e-02 6.989 2.77e-12 ***
#> age 2.980e-03 5.293e-04 5.630 1.80e-08 ***
#> totemp -8.736e-07 3.279e-07 -2.665 0.00771 **
#> sole 3.635e-02 8.515e-03 4.270 1.96e-05 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
### Simulated Examples
N <- 250
u <- rnorm(N)
X <- cbind(rnorm(N),rnorm(N))
dimnames(X)[[2]] <- c("X1","X2")
ym <- exp(X[,1]+X[,2]+u)/(1+exp(X[,1]+X[,2]+u))
y <- rbeta(N,ym*20,20*(1-ym))
y[y > 0.9] <- 1
#Computing average partial effects for a logit fractional response model
mod <- fracreg(y,X,linkfrac="logit",table=FALSE)
pe_res <- fracreg.pe(mod)
summary(pe_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Average partial effects
#> --------------------------------------------------------------------------------
#> Fractional logit regression
#> --------------------------------------------------------------------------------
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> X1 0.161653 0.009584 16.87 <2e-16 ***
#> X2 0.165141 0.012853 12.85 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
2.2.2 APEs for a Two-Part Model
When the data has boundary inflation (e.g., at 1), partial effects
must account for both the hurdle process and the fractional continuous
process. The fracreg.pe() function automatically handles
this composite calculation for type="2P".
# Compute average partial effects for a binary logit + fractional probit two-part model
mod <- fracreg(y,X,linkbin="logit",linkfrac="probit",type="2P",inf=1,table=FALSE)
pe_res <- fracreg.pe(mod)
summary(pe_res)Toggle to see the output
#>
#>
#> --------------------------------------------------------------------------------
#> Average partial effects
#> --------------------------------------------------------------------------------
#>
#> Binary logit regression (Pr(y = 1)):
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> X1 0.10163 0.01549 6.560 5.37e-11 ***
#> X2 0.10992 0.01649 6.665 2.64e-11 ***
#>
#> Fractional probit regression (Fractional Component):
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> X1 0.14809 0.01068 13.86 <2e-16 ***
#> X2 0.14840 0.01407 10.55 <2e-16 ***
#>
#> --------------------------------------------------------------------------------
#> Binary logit + Fractional probit two-part regression
#> --------------------------------------------------------------------------------
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> X1 0.08479 0.01192 7.115 1.12e-12 ***
#> X2 0.09068 0.01249 7.259 3.89e-13 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
2.2.3 Conditional Partial Effects (CPE)
Instead of averaging the effects over all observations (APE), you may
want the effect for a “typical” observation. By setting
APE=FALSE and CPE=TRUE, and providing
at="median", we compute the Conditional Partial Effect
evaluated at the median values of all covariates. We isolate the effect
of X2 using which.x="X2".
# Compute conditional partial effects for X2 at median values
mod <- fracreg(y,X,linkfrac="logit",type="2Pfrac",inf=1,table=FALSE)
pe_res <- fracreg.pe(mod,APE=FALSE,CPE=TRUE,at="median",which.x="X2")
summary(pe_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Conditional partial effects
#> --------------------------------------------------------------------------------
#> Fractional logit component of a two-part regression
#> --------------------------------------------------------------------------------
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> X2 0.17106 0.01895 9.026 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
#>
#> Note: covariates evaluated at median (or mode, for dummies) values
2.2.4 APEs for a Three-Part Model
For double-inflated models (type="3P"), the partial
effect calculation incorporates both boundary probabilities and the
interior fractional distribution.
# Compute average partial effects for a three-part double-inflated model
y3p <- y
y3p[1:20] <- 0
y3p[21:40] <- 1
res3p <- fracreg(y3p,X,linkbin=c("logit","probit"),linkfrac="logit",type="3P",table=FALSE)
pe_res <- fracreg.pe(res3p)
summary(pe_res)Toggle to see the output
#>
#>
#> --------------------------------------------------------------------------------
#> Average partial effects
#> --------------------------------------------------------------------------------
#>
#> Binary logit regression (Pr(y > 0)):
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> X1 0.006772 0.016605 0.408 0.683
#> X2 -0.020995 0.017401 -1.207 0.228
#>
#> Binary probit regression (Pr(y = 1 | y > 0)):
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> X1 0.11296 0.02152 5.249 1.53e-07 ***
#> X2 0.06011 0.02444 2.460 0.0139 *
#>
#> Fractional logit regression (Fractional Component):
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> X1 0.14591 0.01227 11.893 <2e-16 ***
#> X2 0.14019 0.01645 8.521 <2e-16 ***
#>
#> --------------------------------------------------------------------------------
#> Three-part regression - binary logit , binary probit + fractional logit
#> --------------------------------------------------------------------------------
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> X1 0.15535 0.01440 10.790 < 2e-16 ***
#> X2 0.11405 0.01854 6.153 7.62e-10 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
3. Hypothesis Testing and Specification Diagnostics
fracreg includes state-of-the-art specification tests to
validate your model’s functional form and link function assumptions.
3.1 Generalised Goodness-Of-Functional-Form
(fracreg.ggoff)
The GGOFF test checks if the chosen link function (e.g.,
logit, probit) is appropriate for the data. A
significant test statistic suggests that the link function may be
misspecified and an alternative should be explored. Here, we run the LM,
Wald, and LR variations of the test on our fitted fractional models.
### Empirical 401(k) Examples
data("fracreg_k401k")
y <- fracreg_k401k$prate
X <- cbind(mrate = fracreg_k401k$mrate, age = fracreg_k401k$age,
totemp = fracreg_k401k$totemp, sole = fracreg_k401k$sole)
m <- fracreg(y, X, type="1P", linkfrac="logit")
ggoff_res <- fracreg.ggoff(m)
summary(ggoff_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> GGOFF test
#> --------------------------------------------------------------------------------
#> H0: Fractional logit regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> GOFF1 - LM 8.838 0.00295 **
#> GOFF2 - LM 9.828 0.00172 **
#> GGOFF - LM 10.351 0.00565 **
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
### Simulated Examples
N <- 250
u <- rnorm(N)
X <- cbind(rnorm(N),rnorm(N))
dimnames(X)[[2]] <- c("X1","X2")
ym <- exp(X[,1]+X[,2]+u)/(1+exp(X[,1]+X[,2]+u))
y <- rbeta(N,ym*20,20*(1-ym))
y[y > 0.9] <- 1
#Testing the logit specification of a standard fractional response model
#using LM and Wald versions of the GGOFF test, based on 1 or 2 fitted powers of
#the linear predictor
mod <- fracreg(y,X,linkfrac="logit",table=FALSE)
ggoff_res <- fracreg.ggoff(mod,c("Wald","LM"))
summary(ggoff_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> GGOFF test
#> --------------------------------------------------------------------------------
#> H0: Fractional logit regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> GOFF1 - LM 1.256 0.262
#> GOFF1 - Wald 1.274 0.259
#> GOFF2 - LM 1.513 0.219
#> GOFF2 - Wald 1.401 0.237
#> GGOFF - LM 1.612 0.447
#> GGOFF - Wald 1.336 0.513
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
3.1.2 GGOFF Test for the Binary Component
The GGOFF test can also be applied to individual components of hurdle
models. Here, we test the probit specification of the
binary component (2Pbin) using a Likelihood Ratio (LR) test
approach.
# Test the probit specification of the binary component
mod <- fracreg(y,X,linkbin="probit",type="2Pbin",inf=1,table=FALSE)
ggoff_res <- fracreg.ggoff(mod,"LR")
summary(ggoff_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> GGOFF test
#> --------------------------------------------------------------------------------
#> H0: Binary probit component of a two-part regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> GOFF1 - LR 0.012 0.914
#> GOFF2 - LR 0.017 0.895
#> GGOFF - LR 0.024 0.988
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:38
#> --------------------------------------------------------------------------------
3.2 RESET Test (fracreg.reset)
The RESET test detects general functional form misspecification by testing whether powers of the fitted values have explanatory power. Testing provides a robust diagnostic check against omitted non-linearities.
### Empirical 401(k) Examples
data("fracreg_k401k")
y <- fracreg_k401k$prate
X <- cbind(mrate = fracreg_k401k$mrate, age = fracreg_k401k$age,
totemp = fracreg_k401k$totemp, sole = fracreg_k401k$sole)
m <- fracreg(y, X, type="1P", linkfrac="logit")
reset_res <- fracreg.reset(m)
summary(reset_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> RESET test
#> --------------------------------------------------------------------------------
#> H0: Fractional logit regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> LM(3) 10.29 0.00583 **
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:39
#> --------------------------------------------------------------------------------
### Simulated Examples
N <- 250
u <- rnorm(N)
X <- cbind(rnorm(N),rnorm(N))
dimnames(X)[[2]] <- c("X1","X2")
ym <- exp(X[,1]+X[,2]+u)/(1+exp(X[,1]+X[,2]+u))
y <- rbeta(N,ym*20,20*(1-ym))
y[y > 0.9] <- 1
#Testing the logit specification of a standard fractional response model
#using LM and Wald versions of the RESET test, based on 1 or 2 fitted powers of
#the linear predictor
mod <- fracreg(y,X,linkfrac="logit",table=FALSE)
reset_res <- fracreg.reset(mod,2:3,c("Wald","LM"))
summary(reset_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> RESET test
#> --------------------------------------------------------------------------------
#> H0: Fractional logit regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> LM(2) 4.832 0.0279 *
#> Wald(2) 5.816 0.0159 *
#> LM(3) 4.866 0.0878 .
#> Wald(3) 6.870 0.0322 *
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:39
#> --------------------------------------------------------------------------------
3.2.2 RESET Test for the Binary Component
Similar to GGOFF, the RESET test can validate individual hurdle components. Here, we use the Likelihood Ratio (LR) version of the RESET test on the binary probit component, checking up to cubic fitted powers of the linear predictor.
# Test the probit specification of the binary component using LR RESET
mod <- fracreg(y,X,linkbin="probit",type="2Pbin",inf=1,table=FALSE)
reset_res <- fracreg.reset(mod,3,"LR")
#> Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred
summary(reset_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> RESET test
#> --------------------------------------------------------------------------------
#> H0: Binary probit component of a two-part regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> LR(3) 0.976 0.614
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:39
#> --------------------------------------------------------------------------------
3.3 P-Test for Non-Nested Models (fracreg.ptest)
When you need to choose between two non-nested model specifications
(for example, a logit link vs. a probit or
loglog link, or a 1P vs. a 2P model), the P-test compares
them directly to see if one statistically dominates the other.
### Empirical 401(k) Examples
data("fracreg_k401k")
y <- fracreg_k401k$prate
X <- cbind(mrate = fracreg_k401k$mrate, age = fracreg_k401k$age,
totemp = fracreg_k401k$totemp, sole = fracreg_k401k$sole)
m1 <- fracreg(y, X, type="1P", linkfrac="logit")
m2 <- fracreg(y, X, type="1P", linkfrac="probit")
ptest_res <- fracreg.ptest(m1, m2)
summary(ptest_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> P test
#> --------------------------------------------------------------------------------
#> H0: Fractional logit regression
#> H1: Fractional probit regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> Wald -1.483 0.138
#> --------------------------------------------------------------------------------
#> H0: Fractional probit regression
#> H1: Fractional logit regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> Wald 2.754 0.00595 **
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:39
#> --------------------------------------------------------------------------------
### Simulated Examples
N <- 250
u <- rnorm(N)
X <- cbind(rnorm(N),rnorm(N))
dimnames(X)[[2]] <- c("X1","X2")
ym <- exp(X[,1]+X[,2]+u)/(1+exp(X[,1]+X[,2]+u))
y <- rbeta(N,ym*20,20*(1-ym))
y[y > 0.9] <- 1
#Testing logit versus loglog specifications for standard fractional
#regression models using a LM version of the P test
res1 <- fracreg(y,X,linkfrac="logit",table=FALSE)
res2 <- fracreg(y,X,linkfrac="loglog",table=FALSE)
ptest_res <- fracreg.ptest(res1,res2,"LM")
summary(ptest_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> P test
#> --------------------------------------------------------------------------------
#> H0: Fractional logit regression
#> H1: Fractional loglog regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> LM 0.239 0.625
#> --------------------------------------------------------------------------------
#> H0: Fractional loglog regression
#> H1: Fractional logit regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> LM 8.502 0.00355 **
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:39
#> --------------------------------------------------------------------------------
3.3.2 P-Test: 1P vs. 2P Model
The P-test is exceptionally useful for deciding whether a simple
1-part model suffices, or if the extra complexity of a 2-part model is
statistically justified. We test the 1P logit model against
a 2P (binary logit + fractional probit) model using the
Wald test statistic.
# Test 1P logit versus 2P logit-probit using Wald P-test
res1 <- fracreg(y,X,linkfrac="logit",table=FALSE)
res2 <- fracreg(y,X,linkbin="logit",linkfrac="probit",type="2P",inf=1,table=FALSE)
ptest_res <- fracreg.ptest(res1,res2,"Wald")
summary(ptest_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> P test
#> --------------------------------------------------------------------------------
#> H0: Fractional logit regression
#> H1: Binary logit + Fractional probit two-part regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> Wald 0.207 0.836
#> --------------------------------------------------------------------------------
#> H0: Binary logit + Fractional probit two-part regression
#> H1: Fractional logit regression
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> Wald 13.95 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:39
#> --------------------------------------------------------------------------------
4. Endogeneity & Heteroscedasticity
(fracreghet)
When a covariate is endogenous (correlated with the error term) or
heteroscedasticity is present, standard maximum likelihood estimation
becomes inconsistent. fracreghet() provides Instrumental
Variable (IV) corrections using Control Function (CF) and Generalised
Method of Moments (GMM) approaches.
In the empirical example below, we suspect mrate
(matching rate) might be endogenous. We use age and
ltotemp (log of total employees) as instruments. We
estimate the model using a Quasi-Maximum Likelihood control function
approach (QMLxv). We also show how to extract odds ratios.
In the simulated examples, we explore GMMx,
GMMz, and GMMxv estimators which relax the
need for a linear first-stage relationship in different ways.
### Empirical 401(k) Examples
data("fracreg_k401k")
y <- fracreg_k401k$prate
X_het <- cbind(mrate = fracreg_k401k$mrate, ltotemp = fracreg_k401k$ltotemp)
# fracreghet estimators do not allow exact 1s or 0s
y_adj <- y
y_adj[y_adj == 1] <- 0.999
# Instrument mrate using age
Z_emp <- cbind(age = fracreg_k401k$age, ltotemp = fracreg_k401k$ltotemp)
mod <- fracreghet(y_adj, X_het, Z_emp, var.endog = X_het[, "mrate"], type="QMLxv", link="logit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression with heteroscedasticity/endogeneity
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: QMLxv
#> Convergence: Successful
#> Number of observations: 1534
#> Wald chi2(6): 1991.8748
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> --------------------------------------------------------------------------------
#> Final Quasi-Maximum Likelihood xv estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) -0.10561 0.75224 -0.14040 -1.57997 1.369 0.888
#> mrate 3.72138 0.68952 5.39703 2.36994 5.073 6.78e-08
#> ltotemp -0.07009 0.05348 -1.31060 -0.17491 0.035 0.190
#> vhat -2.79515 0.70026 -3.99157 -4.16764 -1.423 6.56e-05
#>
#> (Intercept)
#> mrate ***
#> ltotemp
#> vhat ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Reduced form:
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval]
#> Z_(Intercept) 0.95046 0.09550 9.95211 0.76327 1.138
#> Z_age 0.01146 0.00231 4.95997 0.00693 0.016
#> Z_ltotemp -0.05534 0.01421 -3.89528 -0.08318 -0.027
#> Pr(>|z|)
#> Z_(Intercept) < 2e-16 ***
#> Z_age 7.05e-07 ***
#> Z_ltotemp 9.81e-05 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:39
#> --------------------------------------------------------------------------------
# Compute the same QMLxv estimator reporting Odds Ratios with 90% confidence intervals
mod <- fracreghet(y_adj, X_het, Z_emp, var.endog = X_het[, "mrate"], type="QMLxv", link="logit", or=TRUE, level=0.90)
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression with heteroscedasticity/endogeneity
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: QMLxv
#> Convergence: Successful
#> Number of observations: 1534
#> Wald chi2(6): 2243425.9766
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> --------------------------------------------------------------------------------
#> Final Quasi-Maximum Likelihood xv estimates
#> --------------------------------------------------------------------------------
#> Odds Ratio Robust Std.Err. z value [90% Conf. Interval] Pr(>|z|)
#> (Intercept) 0.89977 0.67684 -0.14040 0.26108 3.101 0.888
#> mrate 41.32157 28.49225 5.39703 13.29273 128.452 6.78e-08
#> ltotemp 0.93231 0.04986 -1.31060 0.85380 1.018 0.190
#> vhat 0.06111 0.04279 -3.99157 0.01931 0.193 6.56e-05
#>
#> (Intercept)
#> mrate ***
#> ltotemp
#> vhat ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Reduced form:
#> --------------------------------------------------------------------------------
#> Odds Ratio Robust Std.Err. z value [90% Conf. Interval]
#> Z_(Intercept) 2.586889 0.247056 9.952107 2.210829 3.027
#> Z_age 1.011524 0.002337 4.959966 1.007688 1.015
#> Z_ltotemp 0.946168 0.013441 -3.895285 0.924315 0.969
#> Pr(>|z|)
#> Z_(Intercept) < 2e-16 ***
#> Z_age 7.05e-07 ***
#> Z_ltotemp 9.81e-05 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:39
#> --------------------------------------------------------------------------------
### Simulated Examples
set.seed(123)
N <- 1000
x1 <- rnorm(N)
# Simulating an endogenous variable (var.endog) and an instrument (z1)
z1 <- rnorm(N)
u <- 0.5 * z1 + rnorm(N)
var.endog <- 0.8 * z1 + u
y_endog <- exp(0.5 * x1 + 1.2 * var.endog + u) / (1 + exp(0.5 * x1 + 1.2 * var.endog + u))
# Avoid exact 0 or 1 boundaries for some estimators
y_endog[y_endog <= 0] <- 0.01
y_endog[y_endog >= 1] <- 0.99
X <- cbind(x1 = x1, var.endog = var.endog)
Z <- cbind(x1 = x1, z1 = z1)
# Exogeneity (assuming var.endog is exogenous for comparison), GMMx estimator
mod <- fracreghet(y = y_endog, x = X, type = "GMMx", link = "logit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression with heteroscedasticity/endogeneity
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: GMMx
#> Convergence: Successful
#> Number of observations: 1000
#> Wald chi2(2): 42761.0276
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> --------------------------------------------------------------------------------
#> Final GMMx estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) 9.132e-02 1.536e-02 5.947e+00 6.123e-02 0.121 2.73e-09
#> x1 4.608e-01 1.538e-02 2.995e+01 4.306e-01 0.491 < 2e-16
#> var.endog 1.808e+00 9.021e-03 2.004e+02 1.790e+00 1.826 < 2e-16
#>
#> (Intercept) ***
#> x1 ***
#> var.endog ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:39
#> --------------------------------------------------------------------------------
4.1.2 GMMz Estimator
The GMMz estimator handles endogeneity directly through moment conditions using the instruments , without requiring an explicit linear reduced form equation for the endogenous variable. This approach is more robust to first-stage misspecification.
# Endogeneity, GMMz estimator
mod <- fracreghet(y = y_endog, x = X, z = Z, type = "GMMz", link = "logit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression with heteroscedasticity/endogeneity
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: GMMz
#> Convergence: Successful
#> Number of observations: 1000
#> Wald chi2(2): 14903.8562
#> Prob > chi2: 0.0000
#> Standard errors: HC0
#> --------------------------------------------------------------------------------
#> Final GMMz estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) 0.15277 0.02018 7.56931 0.11321 0.192 3.75e-14
#> x1 0.47947 0.02051 23.37680 0.43927 0.520 < 2e-16
#> var.endog 1.61252 0.01445 111.61802 1.58421 1.641 < 2e-16
#>
#> (Intercept) ***
#> x1 ***
#> var.endog ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:39
#> --------------------------------------------------------------------------------
4.1.3 GMMxv Estimator
The GMMxv estimator is a variation that does assume a linear reduced form for the endogenous variable, utilizing the first-stage residuals within the generalized method of moments framework to correct for endogeneity.
# Endogeneity, GMMxv estimator
mod <- fracreghet(y = y_endog, x = X, z = Z, var.endog = var.endog, type = "GMMxv", link = "logit")
#> Warning in dgamma(y, 1/disp, scale = mu * disp, log = TRUE): NaNs produced
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression with heteroscedasticity/endogeneity
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: GMMxv
#> Convergence: Successful
#> Number of observations: 1000
#> Standard errors: HC0
#> --------------------------------------------------------------------------------
#> Final GMMxv estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) -0.01262 0.01859 -0.67857 -0.04905 0.024 0.497
#> x1 0.48705 0.01884 25.85287 0.45012 0.524 <2e-16
#> var.endog 1.59737 0.01339 119.33166 1.57113 1.624 <2e-16
#> vhat 0.60263 0.01339 45.01988 0.57640 0.629 <2e-16
#>
#> (Intercept)
#> x1 ***
#> var.endog ***
#> vhat ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Reduced form:
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval]
#> Z_(Intercept) -0.02093 0.03082 -0.67933 -0.08133 0.039
#> Z_x1 -0.02149 0.03132 -0.68612 -0.08288 0.040
#> Z_z1 1.32751 0.02949 45.01988 1.26971 1.385
#> Pr(>|z|)
#> Z_(Intercept) 0.497
#> Z_x1 0.493
#> Z_z1 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:39
#> --------------------------------------------------------------------------------
4.1.4 QMLxv Control Function Estimator
The QMLxv approach utilizes a Control Function (CF). It explicitly estimates the first-stage linear reduced form, extracts the residuals, and includes them as control variables in the second-stage Quasi-Maximum Likelihood estimation to absorb the endogeneity.
# Endogeneity, QMLxv control function approach
mod <- fracreghet(y = y_endog, x = X, z = Z, var.endog = var.endog, type = "QMLxv", link = "logit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression with heteroscedasticity/endogeneity
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Estimator: QMLxv
#> Convergence: Successful
#> Number of observations: 1000
#> Standard errors: HC0
#> --------------------------------------------------------------------------------
#> Final Quasi-Maximum Likelihood xv estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> (Intercept) -0.01262 0.01859 -0.67857 -0.04905 0.024 0.497
#> x1 0.48705 0.01884 25.85287 0.45012 0.524 <2e-16
#> var.endog 1.59737 0.01339 119.33166 1.57113 1.624 <2e-16
#> vhat 0.60263 0.01339 45.01988 0.57640 0.629 <2e-16
#>
#> (Intercept)
#> x1 ***
#> var.endog ***
#> vhat ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Reduced form:
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval]
#> Z_(Intercept) -0.02093 0.03082 -0.67933 -0.08133 0.039
#> Z_x1 -0.02149 0.03132 -0.68612 -0.08288 0.040
#> Z_z1 1.32751 0.02949 45.01988 1.26971 1.385
#> Pr(>|z|)
#> Z_(Intercept) 0.497
#> Z_x1 0.493
#> Z_z1 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:40
#> --------------------------------------------------------------------------------
4.1 Partial Effects for Endogenous Models
(fracreghet.pe)
Partial effects can also be calculated for endogenous models. When
using a control function approach (QMLxv),
fracreghet.pe accurately integrates over the estimated
first-stage residuals, offering a corrected smearing estimation.
### Empirical 401(k) Examples
data("fracreg_k401k")
y <- fracreg_k401k$prate
X_het <- cbind(mrate = fracreg_k401k$mrate, ltotemp = fracreg_k401k$ltotemp)
# fracreghet estimators do not allow exact 1s or 0s
y_adj <- y
y_adj[y_adj == 1] <- 0.999
# Instrument mrate using age
Z_emp <- cbind(age = fracreg_k401k$age, ltotemp = fracreg_k401k$ltotemp)
res_emp <- fracreghet(y_adj, X_het, Z_emp, var.endog = X_het[, "mrate"], type="QMLxv", link="logit", table=FALSE)
pe_res <- fracreghet.pe(res_emp, which.x="mrate")
summary(pe_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Average partial effects
#> --------------------------------------------------------------------------------
#> (conditional only on observables, based on the smearing estimator)
#> Fractional logit regression
#> Estimator: QMLxv
#> --------------------------------------------------------------------------------
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> mrate 0.39498 0.09827 4.019 5.84e-05 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:40
#> --------------------------------------------------------------------------------
#>
#> Note: Partial effects for the reduced form are omitted because it is a linear model where they strictly equal the estimated coefficients.
### Simulated Examples
N <- 250
u <- rnorm(N)
X <- cbind(rnorm(N),rnorm(N))
dimnames(X)[[2]] <- c("X1","X2")
Z <- cbind(rnorm(N),rnorm(N),rnorm(N))
dimnames(Z)[[2]] <- c("Z1","Z2","Z3")
y <- exp(X[,1]+X[,2]+u)/(1+exp(X[,1]+X[,2]+u))
mod <- fracreghet(y,X,type="GMMx",table=FALSE)
#Smearing estimator of average partial effects for variable X1
pe_res <- fracreghet.pe(mod,which.x="X1")
summary(pe_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Average partial effects
#> --------------------------------------------------------------------------------
#> (conditional only on observables, based on the smearing estimator)
#> Fractional logit regression
#> Estimator: GMMx
#> --------------------------------------------------------------------------------
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> X1 0.166732 0.009667 17.25 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:40
#> --------------------------------------------------------------------------------
#>
#> Note: Partial effects for the reduced form are omitted because it is a linear model where they strictly equal the estimated coefficients.
4.1.2 Naive Estimator for CPEs
For a targeted interpretation, we can calculate Conditional Partial
Effects (CPE) evaluated at specific fixed values (e.g.,
and
).
By setting smearing=FALSE, we use a naive estimator that
does not integrate over the estimated unobserved heterogeneity.
# Naive estimator of CPE evaluated at fixed values
pe_res <- fracreghet.pe(mod,smearing=FALSE,APE=FALSE,CPE=TRUE,at=c(1,-1))
summary(pe_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Conditional partial effects
#> --------------------------------------------------------------------------------
#> (conditional on both observables and unobservables, with error term = 0)
#> Fractional logit regression
#> Estimator: GMMx
#> --------------------------------------------------------------------------------
#>
#> Note: Standard errors computed using the Delta method
#> dy/dx Std. Error z value Pr(>|z|)
#> X1 0.22869 0.01337 17.11 <2e-16 ***
#> X2 0.20596 0.01454 14.17 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:40
#> --------------------------------------------------------------------------------
#>
#> Note: covariates evaluated at the following values:
#>
#> X1 X2
#> 1 -1
#>
#> Note: Partial effects for the reduced form are omitted because it is a linear model where they strictly equal the estimated coefficients.
4.2 RESET Test for Endogenous Models
(fracreghet.reset)
Just as with fracreg, we can run RESET specification
tests on our heteroscedasticity and endogeneity-robust models to assure
proper functional form.
### Empirical 401(k) Examples
data("fracreg_k401k")
y <- fracreg_k401k$prate
X_het <- cbind(mrate = fracreg_k401k$mrate, ltotemp = fracreg_k401k$ltotemp)
# fracreghet estimators do not allow exact 1s or 0s
y_adj <- y
y_adj[y_adj == 1] <- 0.999
# Instrument mrate using age
Z_emp <- cbind(age = fracreg_k401k$age, ltotemp = fracreg_k401k$ltotemp)
res_emp <- fracreghet(y_adj, X_het, type="GMMx", link="logit", table=FALSE)
reset_res <- fracreghet.reset(res_emp)
summary(reset_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> RESET test
#> --------------------------------------------------------------------------------
#> Fractional logit regression
#> --------------------------------------------------------------------------------
#> H0: Estimator: GMMx
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> Wald(3) 47.56 4.7e-11 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:40
#> --------------------------------------------------------------------------------
### Simulated Examples
N <- 250
u <- rnorm(N)
X <- cbind(rnorm(N),rnorm(N))
dimnames(X)[[2]] <- c("X1","X2")
Z <- cbind(rnorm(N),rnorm(N),rnorm(N))
dimnames(Z)[[2]] <- c("Z1","Z2","Z3")
y <- exp(X[,1]+X[,2]+u)/(1+exp(X[,1]+X[,2]+u))
mod <- fracreghet(y,X,type="GMMx",table=FALSE)
#LM and Wald versions of the RESET test, based on 1 or 2 fitted powers of xb
reset_res <- fracreghet.reset(mod,2:3,c("Wald","LM"))
summary(reset_res)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> RESET test
#> --------------------------------------------------------------------------------
#> Fractional logit regression
#> --------------------------------------------------------------------------------
#> H0: Estimator: GMMx
#> --------------------------------------------------------------------------------
#> Statistic p-value
#> LM(2) 0.216 0.6424
#> Wald(2) 0.180 0.6711
#> LM(3) 3.481 0.1754
#> Wald(3) 6.273 0.0434 *
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:40
#> --------------------------------------------------------------------------------
5. Panel Data Fractional Models (fracregpd)
When you observe the same entities over multiple time periods,
unobserved individual heterogeneity must be accounted for.
fracregpd() provides fixed-T panel estimators. We explore
Correlated Random Effects (CRE) which includes time-averages of the
covariates to proxy the unobserved effect, as well as various panel GMM
estimators (like GMMbgw, GMMww, and
GMMpfe) which can handle lagged dependent variables,
endogenous covariates, and time dummies.
### Empirical 401(k) Examples
data("fracreg_k401k")
y <- fracreg_k401k$prate
X <- cbind(mrate = fracreg_k401k$mrate, age = fracreg_k401k$age,
totemp = fracreg_k401k$totemp, sole = fracreg_k401k$sole)
# Artificial panel data structure for demonstration
N_emp <- nrow(X)
id_emp <- rep(1:(N_emp/2), each=2)
time_emp <- rep(1:2, times=N_emp/2)
mod <- fracregpd(id_emp, time_emp, y, X, type="QMLcre", link="probit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional probit (correlated random effects) regression
#> --------------------------------------------------------------------------------
#> Data type: Panel
#> Estimator: QMLcre
#> Convergence: Successful
#> Number of observations: 1534
#> Number of groups: 767
#> Obs per group: 2
#> Log pseudolikelihood: -554.0205
#> Wald chi2(9): 3191.0501
#> Prob > chi2: 0.0000
#> Exogeneity: TRUE
#> Use first lag of instruments: FALSE
#> Standard errors: CRVE
#> --------------------------------------------------------------------------------
#> Final (Correlated Random Effects) Quasi-Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient Cluster Std.Err. z value [95% Conf. Interval]
#> mrate 3.915e-01 7.007e-02 5.588e+00 2.542e-01 0.529
#> age 1.386e-02 3.543e-03 3.911e+00 6.912e-03 0.021
#> totemp -5.250e-06 2.649e-06 -1.982e+00 -1.044e-05 0.000
#> sole 2.378e-01 6.038e-02 3.938e+00 1.194e-01 0.356
#> (Intercept)_mean 6.235e-01 5.885e-02 1.060e+01 5.082e-01 0.739
#> mrate_mean 5.726e-02 6.343e-02 9.027e-01 -6.706e-02 0.182
#> age_mean 1.544e-03 4.233e-03 3.649e-01 -6.751e-03 0.010
#> totemp_mean 1.223e-06 2.946e-06 4.152e-01 -4.551e-06 0.000
#> sole_mean -7.157e-02 8.424e-02 -8.495e-01 -2.367e-01 0.094
#> Pr(>|z|)
#> mrate 2.30e-08 ***
#> age 9.20e-05 ***
#> totemp 0.0475 *
#> sole 8.22e-05 ***
#> (Intercept)_mean < 2e-16 ***
#> mrate_mean 0.3667
#> age_mean 0.7152
#> totemp_mean 0.6780
#> sole_mean 0.3956
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:40
#> --------------------------------------------------------------------------------
### Simulated Examples
set.seed(123)
# Simulating Panel Data
N <- 100
T_periods <- 5
id <- rep(1:N, each = T_periods)
time <- rep(1:T_periods, times = N)
x_panel <- rnorm(N * T_periods)
# Unobserved individual effect (CRE)
c_i <- rep(rnorm(N), each = T_periods)
y_panel <- exp(x_panel + c_i) / (1 + exp(x_panel + c_i))
X <- cbind(x_panel = x_panel)
# Endogenous variable and instrument simulation
z_panel <- rnorm(N * T_periods)
u_panel <- 0.5 * z_panel + rnorm(N * T_periods)
var_endog <- 0.8 * z_panel + u_panel
y_endog <- exp(x_panel + 1.2 * var_endog + c_i + u_panel) /
(1 + exp(x_panel + 1.2 * var_endog + c_i + u_panel))
X_endog <- cbind(x_panel = x_panel, var_endog = var_endog)
Z_inst <- cbind(x_panel = x_panel, z_panel = z_panel)
# Estimate a Correlated Random Effects (CRE) Model
mod <- fracregpd(id=id, time=time, y=y_panel, x=X, type="QMLcre", link="probit")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional probit (correlated random effects) regression
#> --------------------------------------------------------------------------------
#> Data type: Panel
#> Estimator: QMLcre
#> Convergence: Successful
#> Number of observations: 500
#> Number of groups: 100
#> Obs per group: 5
#> Log pseudolikelihood: -313.6436
#> Wald chi2(3): 2156.6004
#> Prob > chi2: 0.0000
#> Exogeneity: TRUE
#> Use first lag of instruments: FALSE
#> Standard errors: CRVE
#> --------------------------------------------------------------------------------
#> Final (Correlated Random Effects) Quasi-Maximum Likelihood estimates
#> --------------------------------------------------------------------------------
#> Coefficient Cluster Std.Err. z value [95% Conf. Interval]
#> x_panel 0.52902 0.01143 46.29965 0.50662 0.551
#> (Intercept)_mean -0.01246 0.04901 -0.25433 -0.10851 0.084
#> x_panel_mean -0.17409 0.13491 -1.29040 -0.43850 0.090
#> Pr(>|z|)
#> x_panel <2e-16 ***
#> (Intercept)_mean 0.799
#> x_panel_mean 0.197
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:40
#> --------------------------------------------------------------------------------
5.1.2 Standard Panel GMM (GMMbgw)
The GMMbgw estimator is a standard GMM panel approach that doesn’t explicitly model unobserved effects via time-averages, but relies on moment conditions. Here we apply it with clustered standard errors.
# Exogeneity, GMMbgw estimator
mod <- fracregpd(id=id, time=time, y=y_panel, x=X, type="GMMbgw")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression
#> --------------------------------------------------------------------------------
#> Data type: Panel
#> Estimator: GMMbgw
#> Convergence: Successful
#> Number of observations: 500
#> Number of groups: 100
#> Obs per group: 5
#> Wald chi2(1): 4.87462988128311e+31
#> Prob > chi2: 0.0000
#> Exogeneity: TRUE
#> Use first lag of instruments: FALSE
#> Standard errors: CRVE
#> --------------------------------------------------------------------------------
#> Final GMM bgw estimates
#> --------------------------------------------------------------------------------
#> Coefficient Cluster Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> x_panel 1.000e+00 1.432e-16 6.982e+15 1.000e+00 1 <2e-16
#>
#> x_panel ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:41
#> --------------------------------------------------------------------------------
5.1.3 Generalized Method of Moments (GMMww)
The GMMww estimator extends panel GMM capabilities.
Below, we estimate the model and demonstrate how to extract odds ratios
(or=TRUE) with a 99% confidence level.
# Estimate GMMww estimator with odds ratios
mod <- fracregpd(id=id, time=time, y=y_panel, x=X, type="GMMww", or=TRUE, level=0.99)
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression
#> --------------------------------------------------------------------------------
#> Data type: Panel
#> Estimator: GMMww
#> Convergence: Successful
#> Number of obs (initial): 500
#> Number of observations: 400
#> Number of groups (initial): 100
#> Number of groups: 100
#> Obs per group: 4
#> Wald chi2(1): 8.09654990520078e+32
#> Prob > chi2: 0.0000
#> Exogeneity: TRUE
#> Use first lag of instruments: TRUE
#> Standard errors: CRVE
#> --------------------------------------------------------------------------------
#> Final GMM ww estimates
#> --------------------------------------------------------------------------------
#> Odds Ratio Cluster Std.Err. z value [99% Conf. Interval] Pr(>|z|)
#> x_panel 2.718e+00 2.597e-16 1.047e+16 2.718e+00 2.718 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:41
#> --------------------------------------------------------------------------------
5.1.4 GMMww with Lagged Covariates
Dynamic panel data often require the inclusion of lagged covariates
as instruments. By setting lags=TRUE, the model
automatically configures the moment conditions using lagged values,
employing robust standard errors to handle potential heteroscedasticity
across time periods.
# Lagged covariates and instruments
mod <- fracregpd(id=id, time=time, y=y_panel, x=X, lags=TRUE, type="GMMww", var.type="robust")
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit regression
#> --------------------------------------------------------------------------------
#> Data type: Panel
#> Estimator: GMMww
#> Convergence: Successful
#> Number of obs (initial): 500
#> Number of observations: 400
#> Number of groups (initial): 100
#> Number of groups: 100
#> Obs per group: 4
#> Wald chi2(1): 1.27815198429371e+32
#> Prob > chi2: 0.0000
#> Exogeneity: TRUE
#> Use first lag of instruments: TRUE
#> Standard errors: HC0
#> --------------------------------------------------------------------------------
#> Final GMM ww estimates
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> x_panel 1.000e+00 8.845e-17 1.131e+16 1.000e+00 1 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:41
#> --------------------------------------------------------------------------------
5.1.5 Endogenous Panel GMM (GMMpfe)
When covariates are endogenous in a panel setting, we combine
instruments
()
with panel structure. The GMMpfe estimator allows for
endogenous variables (x.exogenous=FALSE) and includes time
dummies (tdummies=TRUE) to control for macroeconomic or
aggregate time shocks.
# Endogeneity, time dummies, GMMpfe estimator
mod <- fracregpd(id=id, time=time, y=y_endog, x=X_endog, z=Z_inst,
x.exogenous=FALSE, type="GMMpfe", tdummies=TRUE)
summary(mod)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional logit (pooled fixed effects) regression
#> --------------------------------------------------------------------------------
#> Data type: Panel
#> Estimator: GMMpfe
#> Convergence: Successful
#> Number of observations: 500
#> Number of groups: 100
#> Obs per group: 5
#> Wald chi2(6): 7156.2911
#> Prob > chi2: 0.0000
#> Exogeneity: FALSE
#> Use first lag of instruments: FALSE
#> Standard errors: CRVE
#> --------------------------------------------------------------------------------
#> Final (Pooled Fixed Effects) Generalized Method of Moments estimates
#> --------------------------------------------------------------------------------
#> Coefficient Cluster Std.Err. z value [95% Conf. Interval] Pr(>|z|)
#> x_panel 0.99602 0.03117 31.95739 0.93493 1.057 <2e-16
#> var_endog 1.57689 0.02524 62.47420 1.52742 1.626 <2e-16
#> time.2 -0.15363 0.09752 -1.57541 -0.34476 0.038 0.1152
#> time.3 -0.04402 0.09147 -0.48128 -0.22331 0.135 0.6303
#> time.4 -0.10609 0.09379 -1.13110 -0.28992 0.078 0.2580
#> time.5 -0.19163 0.08917 -2.14916 -0.36640 -0.017 0.0316
#>
#> x_panel ***
#> var_endog ***
#> time.2
#> time.3
#> time.4
#> time.5 *
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:41
#> --------------------------------------------------------------------------------
6. Fractional Ridge Regression
The fracreg package also includes an implementation of
Fractional Ridge Regression (fracregridge). Standard
maximum likelihood approaches can suffer from multicollinearity or
overfitting when the number of covariates is large relative to the
sample size. fracregridge implements Fractional Ridge
Regression, which applies L2 regularization to shrink coefficients.
Unlike standard ridge regression where the penalty term
is chosen directly, fracregridge allows you to specify the
desired fraction of the unregularized OLS coefficient vector
length (e.g. 0.2 implies shrinking to 20% of the full OLS
length). The algorithm then automatically determines the corresponding
penalties.
6.1 Empirical 401(k) Example
We can apply this to the 401(k) participation rate data to observe how the coefficients dynamically shrink across different target vector length fractions (from 20% to 100%). We also demonstrate how to compute partial effects on the regularized coefficients.
data("fracreg_k401k")
y_401k <- fracreg_k401k$prate
X_401k <- cbind(mrate = fracreg_k401k$mrate, age = fracreg_k401k$age,
totemp = fracreg_k401k$totemp, sole = fracreg_k401k$sole)
# Fit fractional ridge regression
mod_401k <- fracregridge(y = y_401k, x = X_401k, fracs = seq(0.2, 1.0, by = 0.2))
# View full detailed summary showing the chosen alphas
summary(mod_401k)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional ridge regression
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Convergence: Successful
#> Standard errors: homoskedastic
#> --------------------------------------------------------------------------------
#> Target Fraction: 0.2
#> --------------------------------------------------------------------------------
#> Number of observations: 1534
#> Pseudo R-squared: 0.04571
#> Degrees of freedom: 1531.43
#> Wald chi2(5): 7427.4748
#> Prob > chi2: 0.0000
#> --------------------------------------------------------------------------------
#> Coefficient Std. Error z value Pr(>|z|)
#> (Intercept) 1.218e-01 2.623e-03 46.434 <2e-16 ***
#> mrate 6.721e-02 3.418e-03 19.662 <2e-16 ***
#> age 3.471e-02 7.071e-04 49.080 <2e-16 ***
#> totemp 1.033e-06 9.158e-07 1.127 0.26
#> sole 6.265e-02 2.701e-03 23.196 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Target Fraction: 0.4
#> --------------------------------------------------------------------------------
#> Number of observations: 1534
#> Pseudo R-squared: 0.06873
#> Degrees of freedom: 1530.76
#> Wald chi2(5): 12909.0207
#> Prob > chi2: 0.0000
#> --------------------------------------------------------------------------------
#> Coefficient Std. Error z value Pr(>|z|)
#> (Intercept) 2.741e-01 4.766e-03 57.513 <2e-16 ***
#> mrate 1.007e-01 5.152e-03 19.549 <2e-16 ***
#> age 2.461e-02 6.189e-04 39.769 <2e-16 ***
#> totemp 8.942e-07 6.957e-07 1.285 0.199
#> sole 1.115e-01 4.878e-03 22.855 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Target Fraction: 0.6
#> --------------------------------------------------------------------------------
#> Number of observations: 1534
#> Pseudo R-squared: 0.08697
#> Degrees of freedom: 1530.11
#> Wald chi2(5): 22975.8691
#> Prob > chi2: 0.0000
#> --------------------------------------------------------------------------------
#> Coefficient Std. Error z value Pr(>|z|)
#> (Intercept) 4.439e-01 6.218e-03 71.390 <2e-16 ***
#> mrate 9.801e-02 5.457e-03 17.960 <2e-16 ***
#> age 1.586e-02 5.288e-04 29.996 <2e-16 ***
#> totemp 5.080e-07 5.229e-07 0.971 0.331
#> sole 1.246e-01 6.223e-03 20.027 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Target Fraction: 0.8
#> --------------------------------------------------------------------------------
#> Number of observations: 1534
#> Pseudo R-squared: 0.10095
#> Degrees of freedom: 1529.52
#> Wald chi2(5): 38093.0055
#> Prob > chi2: 0.0000
#> --------------------------------------------------------------------------------
#> Coefficient Std. Error z value Pr(>|z|)
#> (Intercept) 6.162e-01 7.193e-03 85.673 <2e-16 ***
#> mrate 7.665e-02 5.176e-03 14.808 <2e-16 ***
#> age 8.729e-03 4.567e-04 19.114 <2e-16 ***
#> totemp -1.493e-07 4.081e-07 -0.366 0.714
#> sole 9.781e-02 7.001e-03 13.970 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Target Fraction: 1
#> --------------------------------------------------------------------------------
#> Number of observations: 1534
#> Pseudo R-squared: 0.11402
#> Degrees of freedom: 1529
#> Wald chi2(5): 47362.8169
#> Prob > chi2: 0.0000
#> --------------------------------------------------------------------------------
#> Coefficient Std. Error z value Pr(>|z|)
#> (Intercept) 7.827e-01 8.711e-03 89.853 < 2e-16 ***
#> mrate 5.062e-02 5.259e-03 9.625 < 2e-16 ***
#> age 2.822e-03 4.487e-04 6.289 3.20e-10 ***
#> totemp -9.814e-07 3.689e-07 -2.660 0.00782 **
#> sole 4.137e-02 8.275e-03 4.999 5.77e-07 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:42
#> --------------------------------------------------------------------------------
# Compute Average Partial Effects for Ridge
pe_401k <- fracregridge.pe(mod_401k)
summary(pe_401k)Toggle to see the output
#>
#>
#> --------------------------------------------------------------------------------
#> Average partial effects
#> --------------------------------------------------------------------------------
#> Fractional ridge regression
#> --------------------------------------------------------------------------------
#>
#> Note: Fractional ridge regression is a linear model without a link function.
#> Therefore, the partial effects are mathematically identical to the coefficients themselves.
#>
#> Target Fraction: 0.2
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> (Intercept) 1.218e-01 2.623e-03 46.434 <2e-16 ***
#> mrate 6.721e-02 3.418e-03 19.662 <2e-16 ***
#> age 3.471e-02 7.071e-04 49.080 <2e-16 ***
#> totemp 1.033e-06 9.158e-07 1.127 0.26
#> sole 6.265e-02 2.701e-03 23.196 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Target Fraction: 0.4
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> (Intercept) 2.741e-01 4.766e-03 57.513 <2e-16 ***
#> mrate 1.007e-01 5.152e-03 19.549 <2e-16 ***
#> age 2.461e-02 6.189e-04 39.769 <2e-16 ***
#> totemp 8.942e-07 6.957e-07 1.285 0.199
#> sole 1.115e-01 4.878e-03 22.855 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Target Fraction: 0.6
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> (Intercept) 4.439e-01 6.218e-03 71.390 <2e-16 ***
#> mrate 9.801e-02 5.457e-03 17.960 <2e-16 ***
#> age 1.586e-02 5.288e-04 29.996 <2e-16 ***
#> totemp 5.080e-07 5.229e-07 0.971 0.331
#> sole 1.246e-01 6.223e-03 20.027 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Target Fraction: 0.8
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> (Intercept) 6.162e-01 7.193e-03 85.673 <2e-16 ***
#> mrate 7.665e-02 5.176e-03 14.808 <2e-16 ***
#> age 8.729e-03 4.567e-04 19.114 <2e-16 ***
#> totemp -1.493e-07 4.081e-07 -0.366 0.714
#> sole 9.781e-02 7.001e-03 13.970 <2e-16 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Target Fraction: 1
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> (Intercept) 7.827e-01 8.711e-03 89.853 < 2e-16 ***
#> mrate 5.062e-02 5.259e-03 9.625 < 2e-16 ***
#> age 2.822e-03 4.487e-04 6.289 3.20e-10 ***
#> totemp -9.814e-07 3.689e-07 -2.660 0.00782 **
#> sole 4.137e-02 8.275e-03 4.999 5.77e-07 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:42
#> --------------------------------------------------------------------------------
6.2 Simulated Data Example
Using a random matrix of 10 predictors on 100 observations, we can see how the fraction parameters precisely constrain the output coefficients to 30%, 50%, and 80% lengths.
# Generate random data
set.seed(123)
n <- 100
p <- 10
y_sim <- rnorm(n)
X_sim <- matrix(rnorm(n * p), n, p)
colnames(X_sim) <- paste0("X", 1:p)
# Fit Fractional Ridge Regression for 30%, 50%, and 80% fractions
mod_sim <- fracregridge(y = y_sim, x = X_sim, fracs = c(0.3, 0.5, 0.8))
# View brief summary
print(mod_sim)Toggle to see the output
#>
#> Fractional Ridge Regression
#>
#> Call: fracregridge(y = y_sim, x = X_sim, fracs = c(0.3, 0.5, 0.8))
#>
#> Coefficients:
#> frac_0.3 frac_0.5 frac_0.8
#> (Intercept) 0.025969041 0.043431002 0.06995586
#> X1 -0.015190037 -0.025277903 -0.04006089
#> X2 -0.029634697 -0.050625055 -0.08391206
#> X3 -0.017972923 -0.035289788 -0.06765584
#> X4 -0.048194568 -0.081684776 -0.13262875
#> X5 -0.013807840 -0.021406027 -0.02901469
#> X6 -0.013152916 -0.022143313 -0.03593916
#> X7 0.048353290 0.078031858 0.11711702
#> X8 -0.006353284 -0.014086532 -0.03160760
#> X9 0.001567879 0.002529806 0.00567404
#> X10 0.020836124 0.031879315 0.04441221
#>
#> Degrees of Freedom: 100 Total; 89 Residual
# Compute Partial Effects
pe_sim <- fracregridge.pe(mod_sim)
summary(pe_sim)Toggle to see the output
#>
#>
#> --------------------------------------------------------------------------------
#> Average partial effects
#> --------------------------------------------------------------------------------
#> Fractional ridge regression
#> --------------------------------------------------------------------------------
#>
#> Note: Fractional ridge regression is a linear model without a link function.
#> Therefore, the partial effects are mathematically identical to the coefficients themselves.
#>
#> Target Fraction: 0.3
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> (Intercept) 0.025969 0.026424 0.983 0.3257
#> X1 -0.015190 0.026179 -0.580 0.5618
#> X2 -0.029635 0.026080 -1.136 0.2558
#> X3 -0.017973 0.026498 -0.678 0.4976
#> X4 -0.048195 0.026318 -1.831 0.0671 .
#> X5 -0.013808 0.025679 -0.538 0.5908
#> X6 -0.013153 0.026949 -0.488 0.6255
#> X7 0.048353 0.026532 1.822 0.0684 .
#> X8 -0.006353 0.027076 -0.235 0.8145
#> X9 0.001568 0.026610 0.059 0.9530
#> X10 0.020836 0.026763 0.779 0.4362
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Target Fraction: 0.5
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> (Intercept) 0.04343 0.04478 0.970 0.3322
#> X1 -0.02528 0.04490 -0.563 0.5735
#> X2 -0.05063 0.04501 -1.125 0.2607
#> X3 -0.03529 0.04449 -0.793 0.4277
#> X4 -0.08168 0.04471 -1.827 0.0677 .
#> X5 -0.02141 0.04462 -0.480 0.6314
#> X6 -0.02214 0.04502 -0.492 0.6228
#> X7 0.07803 0.04477 1.743 0.0814 .
#> X8 -0.01409 0.04497 -0.313 0.7541
#> X9 0.00253 0.04489 0.056 0.9551
#> X10 0.03188 0.04471 0.713 0.4758
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Target Fraction: 0.8
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> (Intercept) 0.069956 0.074554 0.938 0.3481
#> X1 -0.040061 0.075645 -0.530 0.5964
#> X2 -0.083912 0.076139 -1.102 0.2704
#> X3 -0.067656 0.073864 -0.916 0.3597
#> X4 -0.132629 0.074935 -1.770 0.0767 .
#> X5 -0.029015 0.077330 -0.375 0.7075
#> X6 -0.035939 0.072614 -0.495 0.6206
#> X7 0.117117 0.074087 1.581 0.1139
#> X8 -0.031608 0.072003 -0.439 0.6607
#> X9 0.005674 0.073844 0.077 0.9388
#> X10 0.044412 0.072992 0.608 0.5429
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:42
#> --------------------------------------------------------------------------------
7. Fractional Multinomial Logit
The fracreg package incorporates the fractional
multinomial logit (fracregmlogit) to estimate fractional
response data where the response variable consists of fractions that sum
up to one across multiple categories (e.g., budget allocations across
departments). A univariate model is insufficient because the bounded
choices are perfectly collinear in sum.
7.1 Estimating Budget Shares
We use the built-in fracreg_spending dataset, which
records the budget share allocations of local governments across 6
distinct sectors. The sum of these 6 sectoral fractions for any given
government is exactly 1. We compute both the model summary and the
discrete partial effects for specific explanatory variables.
# Load the empirical spending data
data("fracreg_spending")
# Define covariates and fractional responses
X <- fracreg_spending[, c("houseval", "popdens", "noleft", "minorityleft", "tot")]
y <- fracreg_spending[, c("governing", "safety", "education", "recreation", "social", "urbanplanning")]
# Fit the Fractional Multinomial Logit model
mn_fit <- fracregmlogit(y, X)
# View estimates
summary(mn_fit)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Fractional multinomial logit model
#> --------------------------------------------------------------------------------
#> Data type: Cross-sectional
#> Convergence: Successful
#> Number of observations: 392
#> Log pseudolikelihood: -672.9218
#> Pseudo R-squared: 0.00612
#> Baseline choice: governing
#> Standard errors: HC0
#>
#> --------------------------------------------------------------------------------
#> Choice: safety
#> --------------------------------------------------------------------------------
#> Wald chi2(5): 42.6552
#> Prob > chi2: 0.0000
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value Pr(>|z|)
#> (Intercept) 0.730439 0.064200 11.378 < 2e-16 ***
#> houseval -0.131353 0.036779 -3.571 0.000355 ***
#> popdens -0.004797 0.020959 -0.229 0.818951
#> noleft 0.087689 0.045501 1.927 0.053957 .
#> minorityleft 0.192293 0.044135 4.357 1.32e-05 ***
#> tot 0.002264 0.001230 1.841 0.065677 .
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> --------------------------------------------------------------------------------
#> Choice: education
#> --------------------------------------------------------------------------------
#> Wald chi2(5): 287.4992
#> Prob > chi2: 0.0000
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value Pr(>|z|)
#> (Intercept) 1.1827277 0.1661416 7.119 1.09e-12 ***
#> houseval -0.6211445 0.1082112 -5.740 9.46e-09 ***
#> popdens 0.0649859 0.0332356 1.955 0.0505 .
#> noleft -0.3564567 0.0915540 -3.893 9.88e-05 ***
#> minorityleft 0.0444696 0.0934246 0.476 0.6341
#> tot 0.0035276 0.0004931 7.154 8.40e-13 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> --------------------------------------------------------------------------------
#> Choice: recreation
#> --------------------------------------------------------------------------------
#> Wald chi2(5): 211.0898
#> Prob > chi2: 0.0000
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value Pr(>|z|)
#> (Intercept) 0.3960070 0.0665687 5.949 2.70e-09 ***
#> houseval -0.2189703 0.0400569 -5.466 4.59e-08 ***
#> popdens 0.0498010 0.0173550 2.870 0.00411 **
#> noleft 0.0204260 0.0428769 0.476 0.63380
#> minorityleft 0.2264631 0.0416128 5.442 5.26e-08 ***
#> tot 0.0029646 0.0004319 6.865 6.66e-12 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> --------------------------------------------------------------------------------
#> Choice: social
#> --------------------------------------------------------------------------------
#> Wald chi2(5): 444.6676
#> Prob > chi2: 0.0000
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value Pr(>|z|)
#> (Intercept) 1.6604352 0.1105265 15.023 < 2e-16 ***
#> houseval -0.5957574 0.0653650 -9.114 < 2e-16 ***
#> popdens 0.1571051 0.0226909 6.924 4.4e-12 ***
#> noleft -0.1364859 0.0598455 -2.281 0.0226 *
#> minorityleft 0.1467254 0.0592470 2.477 0.0133 *
#> tot 0.0044515 0.0005819 7.650 2.0e-14 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> --------------------------------------------------------------------------------
#> Choice: urbanplanning
#> --------------------------------------------------------------------------------
#> Wald chi2(5): 216.0163
#> Prob > chi2: 0.0000
#> --------------------------------------------------------------------------------
#> Coefficient Robust Std.Err. z value Pr(>|z|)
#> (Intercept) 0.9281283 0.1247764 7.438 1.02e-13 ***
#> houseval -0.1500466 0.0746389 -2.010 0.04440 *
#> popdens 0.1110771 0.0384526 2.889 0.00387 **
#> noleft 0.0433797 0.0830757 0.522 0.60155
#> minorityleft 0.2500309 0.0766200 3.263 0.00110 **
#> tot 0.0050419 0.0006371 7.914 2.44e-15 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:50
#> --------------------------------------------------------------------------------
# Compute Average Partial Effects (discrete)
mn_pe <- fracregmlogit.pe(mn_fit, effect = "discrete", varlist = c("noleft", "minorityleft"))
summary(mn_pe)Toggle to see the output
#>
#>
#> --------------------------------------------------------------------------------
#> Conditional partial effects
#> --------------------------------------------------------------------------------
#> Fractional multinomial logit regression
#> --------------------------------------------------------------------------------
#>
#> Note: discrete effect at the mean, Krinsky-Robb standard error calculated
#>
#> --------------------------------------------------------------------------------
#> Choice: governing
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> noleft 0.0003228 0.0027516 0.117 0.90661
#> minorityleft -0.0073188 0.0026085 -2.806 0.00502 **
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> --------------------------------------------------------------------------------
#> Choice: safety
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> noleft 0.018650 0.008907 2.094 0.0363 *
#> minorityleft 0.004872 0.008286 0.588 0.5565
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> --------------------------------------------------------------------------------
#> Choice: education
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> noleft -0.017494 0.009573 -1.827 0.0676 .
#> minorityleft -0.017209 0.010103 -1.703 0.0885 .
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> --------------------------------------------------------------------------------
#> Choice: recreation
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> noleft 0.005778 0.005670 1.019 0.308
#> minorityleft 0.005583 0.005503 1.014 0.310
#>
#> --------------------------------------------------------------------------------
#> Choice: social
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> noleft -0.032389 0.012085 -2.680 0.00736 **
#> minorityleft -0.004287 0.012058 -0.356 0.72221
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> --------------------------------------------------------------------------------
#> Choice: urbanplanning
#> --------------------------------------------------------------------------------
#> dy/dx Std. Error z value Pr(>|z|)
#> noleft 0.02513 0.01653 1.520 0.128
#> minorityleft 0.01836 0.01474 1.245 0.213
#>
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:50
#> --------------------------------------------------------------------------------
7.2 Willingness to Pay (WTP)
In policy or consumer choice applications, you might want to
calculate the aggregate effect of a variable scaled by arbitrary outcome
weights (such as cost, budget, or willingness to pay associated with
each choice). The wtp() function multiplies the average
partial effects by these arbitrary values and tests if the aggregate
effect differs from zero. We define a vector of length 6 (to match the 6
categories) and plot the effect.
# Calculate Willingness to Pay for the 'noleft' variable using a hypothetical WTP vector
# Assuming WTP = 1, 2, 3, 4, 5, 6 for each of the 6 choices
wtp_est <- wtp(mn_pe, wtp.vec = 1:6, varlist = "noleft")
summary(wtp_est)Toggle to see the output
#>
#> --------------------------------------------------------------------------------
#> Willingness to Pay
#> --------------------------------------------------------------------------------
#> Fractional multinomial logit regression
#> --------------------------------------------------------------------------------
#>
#> Note: Krinsky-Robb standard error calculated
#> Coefficient Std. Error z value Pr(>|z|)
#> noleft -0.0029003 0.1231102 -0.0236 0.9812
#>
#> --------------------------------------------------------------------------------
#> Run Date: 2026-08-08 15:50:50
#> --------------------------------------------------------------------------------
# Plot the Willingness to Pay effect across observations
plot(mn_fit, wtp.vec = 1:6, varlist = "noleft")
Toggle to see the output
#> [[1]]
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#> [19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
#> [37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
#> [55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#> [73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
#> [91] 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
#> [109] 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
#> [127] 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
#> [145] 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
#> [163] 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
#> [181] 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
#> [199] 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
#> [217] 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
#> [235] 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
#> [253] 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
#> [271] 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
#> [289] 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
#> [307] 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
#> [325] 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
#> [343] 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
#> [361] 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
#> [379] 379 380 381 382 383 384 385 386 387 388 389 390 391 392
#>
#> [[2]]
#> noleft
#> [1,] -5.598854e-03
#> [2,] 1.947691e-02
#> [3,] -7.610176e-03
#> [4,] -9.407539e-03
#> [5,] -8.263849e-03
#> [6,] -1.354069e-02
#> [7,] -2.897260e-03
#> [8,] 2.405588e-03
#> [9,] -5.684884e-03
#> [10,] -8.971919e-03
#> [11,] 7.715002e-03
#> [12,] 6.915716e-04
#> [13,] -1.255854e-03
#> [14,] -2.234417e-03
#> [15,] -1.280000e-02
#> [16,] -8.633698e-03
#> [17,] -6.764194e-03
#> [18,] -1.065028e-02
#> [19,] -1.119340e-04
#> [20,] -4.248981e-03
#> [21,] 1.104562e-02
#> [22,] -6.224539e-03
#> [23,] -7.119823e-03
#> [24,] -6.586711e-03
#> [25,] 9.038284e-04
#> [26,] -8.324465e-03
#> [27,] 4.782521e-04
#> [28,] -5.375073e-04
#> [29,] -1.073197e-02
#> [30,] -2.530772e-03
#> [31,] -1.031508e-02
#> [32,] -3.040353e-03
#> [33,] -6.047038e-03
#> [34,] -1.076244e-02
#> [35,] -5.909659e-03
#> [36,] -3.586903e-03
#> [37,] -4.701642e-03
#> [38,] -1.117985e-02
#> [39,] -1.207208e-02
#> [40,] -9.110558e-03
#> [41,] -7.396853e-03
#> [42,] -5.605949e-03
#> [43,] -9.539017e-03
#> [44,] -8.209897e-03
#> [45,] -7.920193e-03
#> [46,] -7.818359e-03
#> [47,] 2.999515e-03
#> [48,] -7.292930e-03
#> [49,] -9.987825e-03
#> [50,] -1.235784e-02
#> [51,] -8.166522e-03
#> [52,] -1.286443e-02
#> [53,] -4.607253e-03
#> [54,] -8.309164e-03
#> [55,] -1.012658e-02
#> [56,] 1.821426e-03
#> [57,] -5.847346e-03
#> [58,] -4.634895e-03
#> [59,] -5.031743e-03
#> [60,] -5.963923e-03
#> [61,] -8.492884e-03
#> [62,] -7.245164e-03
#> [63,] -2.257415e-03
#> [64,] -1.114970e-02
#> [65,] -6.521955e-03
#> [66,] -9.271598e-03
#> [67,] 2.033763e-03
#> [68,] -9.783927e-03
#> [69,] -8.482927e-03
#> [70,] -1.002320e-02
#> [71,] 1.230245e-03
#> [72,] 1.308569e-02
#> [73,] -5.343928e-03
#> [74,] -9.636662e-03
#> [75,] -8.131686e-03
#> [76,] -6.745575e-03
#> [77,] -4.714038e-03
#> [78,] -4.022970e-03
#> [79,] -1.482641e-03
#> [80,] -9.479402e-03
#> [81,] -9.077293e-03
#> [82,] -4.495311e-04
#> [83,] 3.683801e-03
#> [84,] -8.967541e-03
#> [85,] -9.079677e-04
#> [86,] -6.163238e-03
#> [87,] -3.834142e-03
#> [88,] -4.064429e-03
#> [89,] -5.317392e-03
#> [90,] -2.811435e-03
#> [91,] -1.183620e-02
#> [92,] 2.310135e-03
#> [93,] -6.933637e-03
#> [94,] -9.392247e-03
#> [95,] -8.042752e-03
#> [96,] -7.181138e-03
#> [97,] -6.090108e-03
#> [98,] -1.852381e-03
#> [99,] -8.444797e-03
#> [100,] -1.153635e-02
#> [101,] -1.823285e-03
#> [102,] -1.186612e-02
#> [103,] -8.495658e-03
#> [104,] 2.926322e-03
#> [105,] -8.495694e-03
#> [106,] -2.800565e-03
#> [107,] 9.195199e-04
#> [108,] 1.117515e-03
#> [109,] -9.679737e-03
#> [110,] -9.992904e-03
#> [111,] -4.730572e-03
#> [112,] -2.704436e-03
#> [113,] -2.525097e-03
#> [114,] -6.451570e-03
#> [115,] -4.131519e-03
#> [116,] -1.038064e-02
#> [117,] -3.555941e-03
#> [118,] -8.771981e-03
#> [119,] -9.890811e-03
#> [120,] -7.720109e-03
#> [121,] -9.793562e-03
#> [122,] -4.307873e-03
#> [123,] -7.379533e-03
#> [124,] 1.567603e-03
#> [125,] 1.056375e-02
#> [126,] -1.129856e-02
#> [127,] -1.028816e-02
#> [128,] -6.531394e-03
#> [129,] -8.253127e-03
#> [130,] -5.778853e-03
#> [131,] -9.384508e-03
#> [132,] -6.967463e-03
#> [133,] -1.262078e-02
#> [134,] 1.385889e-02
#> [135,] -1.083462e-02
#> [136,] -7.090411e-03
#> [137,] -7.958103e-03
#> [138,] -8.628959e-03
#> [139,] -3.133813e-03
#> [140,] -3.370332e-03
#> [141,] -7.815314e-03
#> [142,] -9.206213e-03
#> [143,] -4.336083e-04
#> [144,] -8.077976e-03
#> [145,] -2.549950e-03
#> [146,] -4.414385e-03
#> [147,] -9.398115e-03
#> [148,] -5.102839e-03
#> [149,] 4.706209e-03
#> [150,] -1.245213e-02
#> [151,] -7.070327e-03
#> [152,] -8.829713e-03
#> [153,] -6.843928e-03
#> [154,] -2.127594e-03
#> [155,] 1.158059e-03
#> [156,] 4.783059e-04
#> [157,] -8.988268e-03
#> [158,] -8.687988e-03
#> [159,] -8.950051e-03
#> [160,] -3.273317e-03
#> [161,] -1.045214e-02
#> [162,] -2.838142e-03
#> [163,] -3.245044e-03
#> [164,] 3.148915e-05
#> [165,] 8.704610e-03
#> [166,] -8.400509e-03
#> [167,] -1.854410e-03
#> [168,] -9.801467e-03
#> [169,] -1.172643e-02
#> [170,] -5.338011e-03
#> [171,] 2.015288e-03
#> [172,] 4.979274e-03
#> [173,] -9.569083e-03
#> [174,] -3.568949e-03
#> [175,] -7.412216e-03
#> [176,] 7.025432e-03
#> [177,] -9.600163e-03
#> [178,] -1.111764e-02
#> [179,] 8.042417e-04
#> [180,] -9.133616e-03
#> [181,] -5.870149e-03
#> [182,] -1.214722e-02
#> [183,] -4.670361e-03
#> [184,] -4.463847e-03
#> [185,] -1.191072e-02
#> [186,] 3.744473e-03
#> [187,] -3.891586e-03
#> [188,] 1.528163e-02
#> [189,] -1.221664e-03
#> [190,] -4.915570e-03
#> [191,] -8.721642e-03
#> [192,] -1.009661e-02
#> [193,] -7.628408e-03
#> [194,] -9.192919e-03
#> [195,] -3.858843e-03
#> [196,] -1.195107e-02
#> [197,] -5.028167e-03
#> [198,] -1.339013e-02
#> [199,] -7.686808e-03
#> [200,] -2.176133e-03
#> [201,] -7.631159e-03
#> [202,] -1.298518e-02
#> [203,] -4.121600e-03
#> [204,] -5.522212e-03
#> [205,] -9.009378e-03
#> [206,] -9.511223e-03
#> [207,] 1.040695e-02
#> [208,] 1.940570e-03
#> [209,] -1.062995e-02
#> [210,] -7.643976e-03
#> [211,] -8.563306e-03
#> [212,] -7.959956e-03
#> [213,] -9.433846e-03
#> [214,] -3.209404e-03
#> [215,] -3.150984e-03
#> [216,] -2.387284e-03
#> [217,] -7.153031e-04
#> [218,] -5.670886e-03
#> [219,] -6.323098e-03
#> [220,] -1.111397e-02
#> [221,] -5.925548e-03
#> [222,] -7.399698e-03
#> [223,] -9.956110e-03
#> [224,] -7.299961e-03
#> [225,] -1.132823e-02
#> [226,] -7.113894e-03
#> [227,] -9.448984e-03
#> [228,] -1.019893e-02
#> [229,] -8.152148e-03
#> [230,] -3.653059e-03
#> [231,] 2.727981e-03
#> [232,] -4.551678e-03
#> [233,] -1.172625e-02
#> [234,] -4.562168e-03
#> [235,] -8.218960e-03
#> [236,] -5.250022e-03
#> [237,] -6.993540e-03
#> [238,] -7.474405e-03
#> [239,] -3.874375e-03
#> [240,] -1.083441e-02
#> [241,] -8.430320e-03
#> [242,] -1.028667e-02
#> [243,] -1.086752e-02
#> [244,] -7.085297e-03
#> [245,] -7.576289e-03
#> [246,] -1.892620e-03
#> [247,] -1.162052e-02
#> [248,] -8.591166e-03
#> [249,] -9.919356e-04
#> [250,] -8.738679e-03
#> [251,] -7.579555e-03
#> [252,] -5.653748e-03
#> [253,] -6.007387e-03
#> [254,] -6.723396e-03
#> [255,] -2.589610e-03
#> [256,] -9.611075e-03
#> [257,] -8.339605e-03
#> [258,] -1.034724e-02
#> [259,] 6.449653e-03
#> [260,] -5.453678e-04
#> [261,] 7.807255e-03
#> [262,] -1.190980e-02
#> [263,] -1.225839e-02
#> [264,] -7.026296e-04
#> [265,] -3.534063e-03
#> [266,] -9.039158e-03
#> [267,] -1.041918e-02
#> [268,] -1.124720e-02
#> [269,] -6.150881e-03
#> [270,] -8.219340e-03
#> [271,] 2.273634e-03
#> [272,] -1.731304e-03
#> [273,] -5.824994e-03
#> [274,] -9.284898e-03
#> [275,] 8.094266e-03
#> [276,] -8.595659e-03
#> [277,] -1.528955e-03
#> [278,] -9.066420e-03
#> [279,] -3.612434e-03
#> [280,] 1.061575e-02
#> [281,] 8.192020e-03
#> [282,] -1.455340e-02
#> [283,] -8.812395e-03
#> [284,] -1.469500e-03
#> [285,] -3.639738e-03
#> [286,] -2.807088e-03
#> [287,] -1.057517e-02
#> [288,] -8.283281e-03
#> [289,] 1.545140e-02
#> [290,] -9.695313e-03
#> [291,] -8.974447e-03
#> [292,] -6.694284e-03
#> [293,] -1.173783e-04
#> [294,] -9.899151e-03
#> [295,] -5.181071e-03
#> [296,] -1.103900e-02
#> [297,] -1.056806e-02
#> [298,] -5.546009e-03
#> [299,] 2.493672e-03
#> [300,] -2.497729e-03
#> [301,] 1.162192e-03
#> [302,] -8.480914e-03
#> [303,] -1.052029e-02
#> [304,] -9.326039e-03
#> [305,] 8.126301e-03
#> [306,] -1.696894e-03
#> [307,] -9.493063e-03
#> [308,] 1.863949e-04
#> [309,] -7.722495e-03
#> [310,] -2.712192e-03
#> [311,] -7.345542e-03
#> [312,] -6.245210e-03
#> [313,] -3.628836e-03
#> [314,] -1.004603e-02
#> [315,] -1.228634e-02
#> [316,] -3.471334e-03
#> [317,] -8.496891e-03
#> [318,] -1.634942e-03
#> [319,] 8.509398e-04
#> [320,] -9.725645e-03
#> [321,] -7.165937e-03
#> [322,] -4.550288e-03
#> [323,] -8.196571e-03
#> [324,] -7.555617e-03
#> [325,] -6.571531e-03
#> [326,] -4.990407e-03
#> [327,] 1.357978e-03
#> [328,] -6.225577e-03
#> [329,] -7.268842e-03
#> [330,] -8.533163e-03
#> [331,] -1.207973e-03
#> [332,] 4.608005e-03
#> [333,] -6.600236e-03
#> [334,] -8.155322e-03
#> [335,] -9.723216e-03
#> [336,] -6.908020e-03
#> [337,] -7.237832e-03
#> [338,] -3.098171e-03
#> [339,] -8.913110e-03
#> [340,] 2.397142e-03
#> [341,] -1.171867e-02
#> [342,] -7.446317e-03
#> [343,] -7.712823e-03
#> [344,] -3.783772e-03
#> [345,] -1.021129e-02
#> [346,] -8.919352e-03
#> [347,] -1.007298e-02
#> [348,] -5.308508e-03
#> [349,] -4.117933e-03
#> [350,] -1.233761e-02
#> [351,] -1.361011e-02
#> [352,] -9.970790e-03
#> [353,] -6.904952e-03
#> [354,] -4.347283e-03
#> [355,] -7.313139e-03
#> [356,] -5.978944e-03
#> [357,] -9.183730e-03
#> [358,] -8.776306e-03
#> [359,] -9.290147e-03
#> [360,] 2.381648e-03
#> [361,] -5.364837e-03
#> [362,] -1.219718e-02
#> [363,] -8.367265e-03
#> [364,] -5.194363e-03
#> [365,] -5.673361e-03
#> [366,] -6.472872e-03
#> [367,] -9.275085e-03
#> [368,] 1.657650e-03
#> [369,] -3.023228e-03
#> [370,] -6.505736e-03
#> [371,] -7.801924e-03
#> [372,] -8.525035e-03
#> [373,] -7.158055e-03
#> [374,] -1.035213e-02
#> [375,] -7.747649e-03
#> [376,] -5.979195e-03
#> [377,] -4.369613e-03
#> [378,] 2.092486e-03
#> [379,] -7.930378e-03
#> [380,] -9.832511e-03
#> [381,] -9.789738e-03
#> [382,] -1.135378e-02
#> [383,] -9.973452e-03
#> [384,] -7.304104e-03
#> [385,] -4.796923e-03
#> [386,] -9.855183e-03
#> [387,] -7.577378e-03
#> [388,] -1.034961e-02
#> [389,] -4.421783e-03
#> [390,] -9.486059e-03
#> [391,] -2.199229e-03
#> [392,] -2.324035e-03
Conclusion
With fracreg, fracreghet,
fracregpd, fracregmlogit, and
fracregridge, you have a complete toolkit for modelling
fractional responses bounded between
,
regardless of inflation, endogeneity, unobserved panel effects,
multinomial structure, or multicollinearity.
Acknowledgements
This package builds upon, consolidates, and modernises the fractional
regression frameworks originally implemented in the frm,
frmhet, and frmpd R packages developed by
Joaquim J.S. Ramalho. As those original packages have been deprecated
and removed from the active CRAN repository, fracreg serves
as an actively maintained successor, ensuring these econometric tools
remain available to the R community.
Furthermore, we acknowledge James Ji (@f1kidd) and A. John Woodill (@johnwoodill), the authors of the
fmlogit R package on GitHub, whose foundational work on
fractional multinomial logit models inspired the implementation of
fracregmlogit. We also extend our gratitude to Ariel Rokem
and Kendrick Kay, the authors of the fracridge package,
whose methodological contributions to fractional ridge regression are
incorporated into the fracregridge functionalities of this
package.
References
Ji, J., and Woodill, A. J. fmlogit: Fractional Multinomial Logit. R package repository. https://github.com/f1kidd/fmlogit
Rokem, A., and Kay, K. fracridge: Fractional Ridge Regression. Package repository. https://github.com/nrdg/fracridge
Ramalho, J. J. S. (2022). frm: Fractional Regression Models. R package. Formerly available on CRAN, currently archived.
Ramalho, J. J. S. (2023). frmhet: Fractional Regression Models under Heterogeneity. R package. Formerly available on CRAN, currently archived.
Ramalho, J. J. S. (2023). frmpd: Fractional Regression Models for Panel Data. R package. Formerly available on CRAN, currently archived.
Buis, M. L. (2008). “fmlogit: Stata module fitting a fractional multinomial logit model by quasi maximum likelihood”, Statistical Software Components, Boston College Department of Economics.
Davidson, R. and MacKinnon, J.G. (1981). “Several tests for model specification in the presence of alternative hypotheses”, Econometrica, 49(3), 781-793.
Fang, K., & Ma, S. (2013). “Three-part model for fractional response variables with application to Chinese household health insurance coverage”, Journal of Applied Statistics, 40(5), 925-940.
Mullahy, J. (2015). “Multivariate fractional regression estimation of econometric share models”, Journal of Econometric Methods, 4(1), 71-100.
Murteira, J. M. R., and Ramalho, J. J. S. (2016). “Regression analysis of multivariate fractional data”, Econometric Reviews, 35(4), 515-552.
Papke, L. E. and Wooldridge, J. M. (1996). “Econometric methods for fractional response variables with an application to 401(k) plan participation rates”, Journal of Applied Econometrics, 11(6), 619-632.
Papke, L. and Wooldridge, J.M. (2008). “Panel data methods for fractional response variables with an application to test pass rates”, Journal of Econometrics, 145(1-2), 121-233.
Pregibon, D. (1980). “Goodness of Link Tests for Generalized Linear Models”, Journal of the Royal Statistical Society: Series C (Applied Statistics), 29(1), 15-24.
Ramalho, E. A., & Ramalho, J. J. S. (2017). “Moment-based estimation of nonlinear regression models with boundary outcomes and endogeneity, with applications to nonnegative and fractional responses”, Econometric Reviews, 36(4), 397-420.
Ramalho, E.A., Ramalho, J.J.S. and Murteira, J.M.R. (2011). “Alternative estimating and testing empirical strategies for fractional response models”, Journal of Economic Surveys, 25(1), 19-68.
Ramalho, E.A., Ramalho, J.J.S. and Murteira, J.M.R. (2014). “A generalized goodness-of-functional form test for binary and fractional response models”, Manchester School, 82(4), 488-507.
Ramsey, J.B. (1969). “Tests for Specification Errors in Classical Linear Least-Squares Regression Analysis”, Journal of the Royal Statistical Society: Series B (Methodological), 31(2), 350-371.
Rokem, A., and Kay, K. (2020). “Fractional ridge regression: a fast, interpretable reparameterization of ridge regression”, GigaScience, 9(12), giaa133.
For more information, please visit the package website or file an issue on GitHub.
To cite this package in your research:
citation("fracreg")