Skip to contents

copreg() only rewrites the call and hands it to the estimator's own function, so both routes behave identically down to the warnings. This matters because each wrapper carries rules of its own: BMW warns when the CDF departs from the one its asymptotics are derived for, the two-stage estimators redirect to Park and Gupta when the formula has no exogenous part, and each tells summary() which assumptions it makes. CopRegPANEL() and CopRegBAYES() are deliberately not reachable through copreg(): the former needs a panel index and a different likelihood, the latter replaces bootstrap inference by a posterior.

Usage

copreg(
  formula,
  data,
  method = c("pg", "2scope", "ima", "bmw", "jams", "np"),
  cdf = NULL,
  ...
)

Arguments

formula

A two-part formula y ~ endogenous_1 + endogenous_2 + ... | exogenous_1 + exogenous_2 + ..., see CopRegPG() for the full syntax.

data

A data.frame containing the variables referenced in formula.

method

Estimator to use: one of "pg" (CopRegPG()), "2scope" (CopReg2sCOPE()), "ima", "bmw", "jams" or "np".

cdf

CDF estimator for the copula transformation; see CopRegPG() for the seven available options. NULL (default) is dropped from the call so that the selected estimator's own default applies.

...

Further arguments passed on to the selected estimator's function, e.g. ties, nboots, subset, contrasts, parallel, ncores, verbose.

Value

An object of class "copreg", identical to what the estimator named by method would return had it been called directly; see CopRegPG() and CopReg2sCOPE().

References

Qian, Y., A. Koschmann, and H. Xie (2025). A practical guide to endogeneity correction using copulas. Journal of Marketing.

Examples

set.seed(42)
n <- 300
w <- rnorm(n)
u <- rnorm(n)
p <- rchisq(n, df = 3) + 0.3 * u   # non-normal endogenous regressor
y <- 1 + 2 * p + 0.5 * w + u
dat <- data.frame(y = y, p = p, w = w)

fit <- copreg(y ~ p | w, data = dat, method = "pg", nboots = 25)
summary(fit)
#> 
#> Copula endogeneity correction: PG (Park & Gupta 2012) 
#> 
#> Call:
#> copreg(formula = y ~ p | w, data = dat, method = "pg", nboots = 25)
#> 
#> Residuals of the augmented regression (u = xi - C gamma):
#>     Min      1Q  Median      3Q     Max 
#> -2.6892 -0.6745 -0.0929  0.6247  3.0787 
#> 
#> Residuals of the structural model (xi = y - mu - P alpha - W beta):
#>      Min       1Q   Median       3Q      Max 
#> -2.53982 -0.62128 -0.06731  0.61248  3.31175 
#> 
#> Coefficients:
#>             Estimate Std. Error z value Pr(>|z|)    
#> (Intercept)  1.35084    0.43959   3.073  0.00212 ** 
#> p            1.86613    0.16466  11.333  < 2e-16 ***
#> w            0.53260    0.05763   9.242  < 2e-16 ***
#> p_cop        0.49819    0.33814   1.473  0.14066    
#> ---
#> Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#> 
#> Endogeneity: rho(P*, xi*) is the correlation between the normal score 
#>   of an endogenous regressor and that of the structural error, xi* = xi / sigma.
#>              Estimate Std. Error z value Pr(>|z|)  
#> rho(p*, xi*)   0.4512     0.1810   2.493   0.0127 *
#> ---
#> Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#> 
#> Fit, on 296 residual degrees of freedom:
#>                         augmented structural
#> Residual standard error 0.9668    1.0834    
#> R-squared               0.9645    0.9555    
#> Adjusted R-squared      0.9642    0.9550    
#>   sigma above is the standard error of the structural model, the one 
#>   entering xi* = xi / sigma.
#> Standard errors from 25 bootstrap replicates; cdf = "kde.silverman", ties = "max".
#> Pr(>|z|) in both tables: Wald test using the normal approximation,
#>   z = Estimate / Std. Error, with the bootstrap standard error.
#>   See confint(object, type = "percentile") for bootstrap percentile intervals.
#> 
#> --- Identification diagnostics ------------------------------------
#> 
#> Non-normality of the endogenous regressors (small p = non-normal, good):
#>      AD      AD p     KS p
#> p 8.608 5.845e-21 0.001517
#> 
#> Correlation of the copula terms with the exogenous regressors
#> (Park & Gupta assume this is zero; 'joint' tests all of them at once,
#>  the Holm p value refers to the single largest correlation):
#>   max |corr| with p (Holm)  joint R2 joint p
#> p    0.02702    w   0.6414 0.0007299  0.6412
#>  full matrix in summary(object)$diagnostics$exog.correlation.matrix
#> 
#> Collinearity of the copula terms (omega near 0 = weakly identified):
#>       corr(P, C) omega
#> p_cop     0.9214  0.15
#>