diff --git a/DESCRIPTION b/DESCRIPTION index 6a9f772..02f6536 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: csdm -Title: Cross Section Dependence Models +Title: Cross-Sectional Dependence Models Version: 1.0.0 -Depends: R (>= 3.5.0) +Depends: R (>= 4.0.0) Imports: MASS Suggests: testthat (>= 3.0.0), @@ -9,12 +9,16 @@ Suggests: rmarkdown, kableExtra, xtsum -Author: Joao Claudio Macosso -Maintainer: Joao Claudio Macosso -Description: Estimators and utilities for panel-data models with cross-sectional dependence. +Authors@R: + person(given = c("Joao", "Claudio"), + family = "Macosso", + email = "joaoclaudiomacosso@gmail.com", + role = c("aut", "cre")) +Description: Provides estimators and utilities for large panel-data models with cross-sectional dependence, including mean group (MG), common correlated effects (CCE) and dynamic CCE (DCCE) estimators, and cross-sectionally augmented ARDL (CS-ARDL) specifications, plus related inference and diagnostics. License: GPL-3 Encoding: UTF-8 LazyData: true +Roxygen: list(markdown = TRUE) RoxygenNote: 7.3.2 Config/testthat/edition: 3 VignetteBuilder: knitr diff --git a/R/csdm.R b/R/csdm.R index b9827e1..38cd9bd 100644 --- a/R/csdm.R +++ b/R/csdm.R @@ -1,49 +1,130 @@ # csdm.R -#' Unified front door for csdm estimators +#' Panel Model Estimation with Cross Section Dependence #' -#' @param formula A model formula like `y ~ x1 + x2`. -#' @param data A `data.frame` (or `plm::pdata.frame`) containing the variables in `formula`. -#' @param id,time Column names (strings) for the unit and time indexes. -#' If `data` is a `pdata.frame`, these are taken from its index and the provided values are ignored. -#' @param model Which estimator to fit. Currently implemented: `"mg"`, `"cce"`, `"dcce"`. +#' Estimate panel data models that allow for cross-sectional dependence and +#' heterogeneous slopes. The interface supports Mean Group (MG), Common +#' Correlated Effects (CCE), Dynamic CCE (DCCE), and Cross-Sectionally +#' Augmented ARDL (CS-ARDL) estimators with consistent handling of +#' cross-sectional averages, dynamic structure, and robust inference. +#' +#' @param formula Model formula of the form \code{y ~ x1 + x2}. +#' @param data A \code{data.frame} (or \code{plm::pdata.frame}) containing the +#' variables in \code{formula}. +#' @param id,time Column names (strings) for the unit and time indexes. If +#' \code{data} is a \code{pdata.frame}, these are taken from its index and the +#' provided values are ignored. +#' @param model Estimator to fit. One of \code{"mg"}, \code{"cce"}, +#' \code{"dcce"}, or \code{"cs_ardl"}. #' @param csa Cross-sectional-average specification, created by [csdm_csa()]. -#' @param lr Long-run specification (currently a stub), created by [csdm_lr()]. -#' @param pooled Pooled specification (currently a stub), created by [csdm_pooled()]. -#' @param trend One of `"none"` or `"unit"` (a linear trend per unit is added as a regressor). -#' `"pooled"` is reserved and not implemented. +#' @param lr Long-run or dynamic specification, created by [csdm_lr()]. +#' @param pooled Pooled specification (reserved for future use), created by +#' [csdm_pooled()]. +#' @param trend One of \code{"none"} or \code{"unit"} (adds a linear unit trend). +#' \code{"pooled"} is reserved and not implemented. #' @param fullsample Logical; reserved for future extensions. #' @param mgmissing Logical; reserved for future extensions. #' @param vcov Variance-covariance specification, created by [csdm_vcov()]. #' @param ... Reserved for future extensions. #' -#' @return An object of class `csdm_fit`. -#' @export +#' @return An object of class \code{csdm_fit} containing estimated coefficients, +#' residuals, variance-covariance estimates, model metadata, and diagnostics. +#' Use \code{summary()}, \code{coef()}, \code{residuals()}, \code{vcov()}, and +#' \code{cd_test()} to access standard outputs. +#' +#' @details +#' ## Model equations +#' +#' \describe{ +#' \item{MG (Pesaran and Smith, 1995)}{ +#' \deqn{y_{it} = x_{it}^\top \beta_i + u_{it}} +#' } +#' \item{CCE (Pesaran, 2006)}{ +#' \deqn{y_{it} = x_{it}^\top \beta_i + \lambda_i^\top F_t + u_{it}} +#' } +#' \item{DCCE (Chudik and Pesaran, 2015)}{ +#' \deqn{\Delta y_{it} = \Delta x_{it}^\top \beta_i + \lambda_i^\top \Delta F_t + u_{it}} +#' } +#' \item{CS-ARDL (Chudik and Pesaran, 2015)}{ +#' \deqn{y_{it} = \phi_i y_{it-1} + x_{it}^\top \theta_i + \lambda_i^\top F_t + u_{it}} +#' } +#' } +#' +#' ## Estimation, identification, and assumptions +#' +#' \describe{ +#' \item{MG}{Unit-by-unit estimation with heterogeneous slopes. The reported +#' coefficients are cross-sectional averages of unit estimates. Requires +#' sufficient time series per unit and weak serial dependence in errors.} +#' \item{CCE}{Augments regressions with cross-sectional averages (CSA) to proxy +#' unobserved common factors. Identification relies on large N and T, weak +#' dependence in idiosyncratic errors after CSA, and weak exogeneity of +#' regressors.} +#' \item{DCCE}{Extends CCE to dynamic settings with lagged dependent variables +#' and CSA lags. Identification relies on weak exogeneity, adequate time length +#' for dynamic lags, and a stable factor structure.} +#' \item{CS-ARDL}{Specifies dynamic distributed lags with CSA terms. Estimation +#' follows ARDL-style dynamics in each unit and aggregates to panel averages. +#' Assumes weak exogeneity and sufficient time length for lag structure.} +#' } +#' +#' @references +#' Pesaran, M.H. and Smith, R. (1995). "Estimating long-run relationships from +#' dynamic heterogeneous panels." Journal of Econometrics, 68(1), 79-113. +#' +#' Pesaran, M.H. (2006). "Estimation and inference in large heterogeneous panels +#' with multifactor error structure." Econometrica, 74(4), 967-1012. +#' +#' Chudik, A. and Pesaran, M.H. (2015). "Common correlated effects estimation of +#' heterogeneous dynamic panel data models with weakly exogenous regressors." +#' Journal of Econometrics, 188(2), 393-420. +#' +#' Chudik, A. and Pesaran, M.H. (2015). "Large panel data models with +#' cross-sectional dependence: A survey." Annals of Economics and Finance, 16(1), +#' 53-78. +#' #' @examples +#' library(csdm) #' data(PWT_60_07, package = "csdm") #' df <- PWT_60_07 #' -#' # Keep examples fast: use a small subset +#' # Keep examples fast but fully runnable #' keep_ids <- unique(df$id)[1:10] -#' # Use enough time periods so DCCE + CSA lags is estimable #' df_small <- df[df$id %in% keep_ids & df$year >= 1970, ] #' -#' # xtdcce2-style DCCE specification -#' fit <- csdm( +#' # Mean Group (MG) +#' mg <- csdm( +#' log_rgdpo ~ log_hc + log_ck + log_ngd, +#' data = df_small, id = "id", time = "year", model = "mg" +#' ) +#' summary(mg) +#' +#' # Common Correlated Effects (CCE) +#' cce <- csdm( +#' log_rgdpo ~ log_hc + log_ck + log_ngd, +#' data = df_small, id = "id", time = "year", model = "cce", +#' csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +#' ) +#' summary(cce) +#' +#' # Dynamic CCE (DCCE) +#' dcce <- csdm( #' log_rgdpo ~ log_hc + log_ck + log_ngd, -#' data = df_small, -#' id = "id", -#' time = "year", -#' model = "dcce", -#' csa = csdm_csa( -#' vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), -#' lags = 3 -#' ), -#' lr = csdm_lr(type = "ardl", ylags = 1) +#' data = df_small, id = "id", time = "year", model = "dcce", +#' csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), lags = 3), +#' lr = csdm_lr(type = "ardl", ylags = 1, xdlags = 0) #' ) +#' summary(dcce) #' -#' summary(fit) -#' cd_test(fit) +#' # CS-ARDL +#' cs_ardl <- csdm( +#' log_rgdpo ~ log_hc + log_ck + log_ngd, +#' data = df_small, id = "id", time = "year", model = "cs_ardl", +#' csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), lags = 3), +#' lr = csdm_lr(type = "ardl", ylags = 1, xdlags = 0) +#' ) +#' summary(cs_ardl) +#' @export csdm <- function( formula, data, id, time, model = c("mg", "cce", "dcce", "cs_ardl", "cs_ecm", "cs_dl"), diff --git a/R/csdm_methods.R b/R/csdm_methods.R index 0ac61aa..16a4682 100644 --- a/R/csdm_methods.R +++ b/R/csdm_methods.R @@ -1,5 +1,17 @@ # csdm_methods.R +#' Compact print method for fitted csdm models +#' +#' Prints a concise overview of a fitted \code{csdm_fit} object, including the +#' model type, formula, panel dimensions, and a coefficient table with standard +#' errors when available. +#' +#' @param x A fitted object of class \code{csdm_fit}. +#' @param digits Number of printed digits. +#' @param ... Currently unused. +#' +#' @return Invisibly returns \code{x}. +#' @seealso [summary.csdm_fit()], [coef.csdm_fit()], [residuals.csdm_fit()] #' @export print.csdm_fit <- function(x, digits = 4, ...) { cat("csdm fit (", x$model, ")\n", sep = "") @@ -22,17 +34,49 @@ print.csdm_fit <- function(x, digits = 4, ...) { invisible(x) } -#' Summarize csdm_fit model results +#' Summarize csdm model estimation results #' -#' @param object A csdm_fit model object. +#' Computes post-estimation summaries for \code{csdm_fit} objects, including +#' mean-group coefficient inference, model-level diagnostics, and model-specific +#' summary tables (for example, short-run and long-run blocks for CS-ARDL). +#' +#' @param object A fitted model object of class \code{csdm_fit}. #' @param digits Number of digits to print. #' @param ... Further arguments passed to methods. #' #' @details -#' The summary displays classic Pesaran CD test statistics. For additional CD diagnostics -#' (CDw, CDw+, CD*), use `cd_test()` on the fitted model object. +#' ## Reported inference +#' +#' For each coefficient \eqn{\hat\beta_k}, the summary reports standard errors, +#' \eqn{z}-statistics, and two-sided normal-approximation p-values: +#' \deqn{z_k = \frac{\hat\beta_k}{\operatorname{se}(\hat\beta_k)}, \qquad +#' p_k = 2\{1-\Phi(|z_k|)\}.} +#' +#' ## Diagnostics #' -#' @return An object of class 'summary.csdm_fit'. +#' The printed summary shows the classic Pesaran CD diagnostic by default. Extended +#' diagnostics (CDw, CDw+, CD*) are available through [cd_test()]. +#' +#' @return An object of class \code{summary.csdm_fit} with core metadata +#' (call/formula/model/N/T), coefficient tables, fit statistics, and +#' model-specific components for printing and downstream inspection. +#' @seealso [print.summary.csdm_fit()], [cd_test()], [coef.csdm_fit()], [vcov.csdm_fit()] +#' +#' @examples +#' data(PWT_60_07, package = "csdm") +#' df <- PWT_60_07 +#' ids <- unique(df$id)[1:10] +#' df_small <- df[df$id %in% ids & df$year >= 1970, ] +#' fit <- csdm( +#' log_rgdpo ~ log_hc + log_ck + log_ngd, +#' data = df_small, +#' id = "id", +#' time = "year", +#' model = "cce", +#' csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +#' ) +#' s <- summary(fit) +#' s #' @export summary.csdm_fit <- function(object, digits = 4, ...) { est <- object$coef_mg @@ -189,15 +233,23 @@ summary.csdm_fit <- function(object, digits = 4, ...) { } -#' Print summary of csdm_fit model +#' Print method for csdm summary objects +#' +#' Formats and prints a \code{summary.csdm_fit} object. Output adapts to model +#' type and includes coefficient tables, selected goodness-of-fit diagnostics, +#' and compact model metadata. #' -#' @param x A summary.csdm_fit object. +#' @param x A \code{summary.csdm_fit} object. #' @param digits Number of digits to print. #' @param ... Further arguments passed to methods. #' #' @details -#' Displays classic Pesaran CD test statistics in the summary output. For extended CD diagnostics -#' (CDw, CDw+, CD*), call `cd_test()` on the fitted model object. +#' The printout includes classic Pesaran CD diagnostics from the summary object. +#' For a full CD diagnostic panel (CD, CDw, CDw+, CD*), use [cd_test()] on the +#' fitted model. +#' +#' @return Invisibly returns \code{x}. +#' @seealso [summary.csdm_fit()], [cd_test()] #' #' @export print.summary.csdm_fit <- function(x, digits = 4, ...) { @@ -290,6 +342,18 @@ print.summary.csdm_fit <- function(x, digits = 4, ...) { invisible(x) } +#' Extract model coefficients from a fitted csdm model +#' +#' Returns estimated mean-group coefficients from a \code{csdm_fit} object. For +#' \code{model = "cs_ardl"}, the returned vector includes short-run mean-group +#' coefficients, the adjustment coefficient (named \code{lr_}), and long-run +#' coefficients when available. +#' +#' @param object A fitted object of class \code{csdm_fit}. +#' @param ... Currently unused. +#' +#' @return A named numeric vector of estimated coefficients. +#' @seealso [summary.csdm_fit()], [vcov.csdm_fit()] #' @export coef.csdm_fit <- function(object, ...) { if (identical(object$model, "cs_ardl") && !is.null(object$cs_ardl) && !is.null(object$cs_ardl$mg)) { @@ -310,12 +374,32 @@ coef.csdm_fit <- function(object, ...) { } +#' Extract coefficient covariance matrix from a fitted csdm model +#' +#' @param object A fitted object of class \code{csdm_fit}. +#' @param ... Currently unused. +#' +#' @return A numeric variance-covariance matrix aligned with \code{coef(object)} +#' for models where this is available. +#' @seealso [coef.csdm_fit()], [summary.csdm_fit()] #' @export vcov.csdm_fit <- function(object, ...) { object$vcov_mg } +#' Extract residual matrix from a fitted csdm model +#' +#' Returns residuals as an \eqn{N x T} matrix (rows are units, columns are time). +#' This method is designed for panel diagnostics and downstream tools such as +#' [cd_test()]. +#' +#' @param object A fitted object of class \code{csdm_fit}. +#' @param type Residual type. Currently only \code{"e"} is implemented. +#' @param ... Currently unused. +#' +#' @return A numeric matrix of residuals with dimensions \eqn{N x T}. +#' @seealso [get_residuals()], [cd_test()], [predict.csdm_fit()] #' @export residuals.csdm_fit <- function(object, type = c("e", "u"), ...) { type <- match.arg(type) @@ -324,6 +408,19 @@ residuals.csdm_fit <- function(object, type = c("e", "u"), ...) { } +#' Predict method for csdm models +#' +#' Produces fitted values (index \code{"xb"}) when available, or returns model +#' residuals. Prediction on new data is not yet implemented. +#' +#' @param object A fitted object of class \code{csdm_fit}. +#' @param newdata Optional new data (not yet supported). +#' @param type One of \code{"xb"} for fitted values or \code{"residuals"}. +#' @param ... Currently unused. +#' +#' @return A numeric matrix of fitted values or residuals, depending on +#' \code{type}. +#' @seealso [residuals.csdm_fit()], [summary.csdm_fit()] #' @export predict.csdm_fit <- function(object, newdata = NULL, type = c("xb", "residuals"), ...) { type <- match.arg(type) diff --git a/R/utils_cd.R b/R/utils_cd.R index 3cb21de..fb7c8b1 100644 --- a/R/utils_cd.R +++ b/R/utils_cd.R @@ -1,51 +1,67 @@ # utils_cd.R - Cross-sectional dependence tests for panel models -#' Cross-sectional dependence (CD) tests for panel data +#' Cross-sectional dependence (CD) tests for panel residuals #' -#' Computes cross-sectional dependence tests for panel residuals: CD (Pesaran 2015), -#' CDw (Juodis & Reese 2021), CDw+ (Fan et al. 2015), and CD* (Pesaran & Xie 2021) -#' with PCA-based factor adjustment. +#' Computes Pesaran CD, CDw, CDw+, and CD* tests for cross-sectional dependence +#' in panel residuals. The implementation supports residual matrices or fitted +#' \code{csdm_fit} objects and provides consistent handling of unbalanced panels. #' #' @param object A \code{csdm_fit} model object or a numeric matrix of residuals (N x T). #' @param ... Additional arguments passed to methods. #' -#' @return An object of class \code{cd_test} with a \code{tests} list. -#' Each test returns a sublist with: -#' \item{statistic}{Test statistic value} -#' \item{p.value}{Two-sided p-value under standard normal null} +#' @return An object of class \code{cd_test} with fields \code{tests}, \code{type}, +#' \code{N}, \code{T}, \code{na.action}, and \code{call}. The \code{tests} list +#' contains one or more test results, each with \code{statistic} and \code{p.value}. #' #' @details -#' \strong{Handling of missing data:} -#' \itemize{ -#' \item \strong{CD, CDw, CDw+:} Always use pairwise-complete observations. Each pair (i,j) -#' correlation is computed over time periods where both units have finite residuals. -#' \item \strong{CD*:} By default (\code{na.action = "drop.incomplete.times"}), automatically -#' removes time periods with any missing observations to create a balanced panel and -#' applies CD*. With \code{na.action = "pairwise"}, requires a balanced panel and -#' returns \code{NA} with a warning if NAs are present. +#' ## Notation +#' +#' Let \eqn{E} be the residual matrix with \eqn{N} cross-sectional units and \eqn{T} +#' time periods. For each unit pair \eqn{(i,j)}, let \eqn{T_{ij}} be the number of +#' overlapping time periods and \eqn{\rho_{ij}} the pairwise correlation. +#' +#' ## Test statistics +#' +#' \describe{ +#' \item{CD (Pesaran, 2015)}{ +#' \deqn{CD = \sqrt{\frac{2}{N(N-1)}} \sum_{i= 1970, ] +#' fit <- csdm( +#' log_rgdpo ~ log_hc + log_ck + log_ngd, +#' data = df_small, +#' id = "id", +#' time = "year", +#' model = "cce", +#' csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +#' ) +#' cd_test(fit, type = "all") +#' #' @export cd_test <- function(object, ...) { UseMethod("cd_test") diff --git a/R/utils_residuals.R b/R/utils_residuals.R index bd9ba97..b07c117 100644 --- a/R/utils_residuals.R +++ b/R/utils_residuals.R @@ -1,14 +1,14 @@ # utils_residuals.R -#' Extract residual matrices from model objects +#' Extract residual matrices for panel diagnostics #' #' @description -#' Unified accessor that returns an \eqn{N \times T} residual matrix suitable for -#' cross-sectional dependence testing. +#' Unified accessor that returns an \eqn{N x T} residual matrix suitable for +#' cross-sectional dependence diagnostics and post-estimation analysis. #' #' @param object A fitted model object supported by this package (e.g., class #' \code{csdm_fit}), or directly a numeric matrix of residuals shaped as -#' \eqn{N \times T}. +#' \eqn{N x T}. #' @param type Character string selecting which residuals to return when available: #' one of \code{"auto"}, \code{"cce"}, \code{"pca"}, or \code{"pca_std"}. #' \itemize{ @@ -22,10 +22,45 @@ #' @param strict Logical; if \code{TRUE}, error on unsupported objects. If \code{FALSE}, #' return \code{NULL} when residuals cannot be found. #' -#' @returns A numeric matrix of residuals with rows = units and columns = time, +#' @return A numeric matrix of residuals with rows = units and columns = time, #' preserving \code{rownames} and \code{colnames} when available; or \code{NULL} #' if nothing suitable is found and \code{strict = FALSE}. #' +#' @details +#' ## Residual types +#' +#' \describe{ +#' \item{cce}{Residuals from the cross-sectionally augmented unit regressions.} +#' \item{pca}{Residuals after principal-component factor removal.} +#' \item{pca_std}{PCA residuals standardized by unit-specific scale.} +#' \item{auto}{Priority rule: \code{pca_std} -> \code{pca} -> \code{cce} -> +#' generic residual slots.} +#' } +#' +#' ## Assumptions and usage +#' +#' The returned matrix is intended for diagnostics that operate on unit-time panels, +#' including [cd_test()]. Missing values are preserved unless downstream routines +#' explicitly filter or balance the panel. +#' +#' @examples +#' data(PWT_60_07, package = "csdm") +#' df <- PWT_60_07 +#' ids <- unique(df$id)[1:10] +#' df_small <- df[df$id %in% ids & df$year >= 1970, ] +#' +#' fit <- csdm( +#' log_rgdpo ~ log_hc + log_ck + log_ngd, +#' data = df_small, +#' id = "id", +#' time = "year", +#' model = "cce", +#' csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +#' ) +#' +#' E <- get_residuals(fit, type = "auto") +#' dim(E) +#' #' @keywords internal #' @export get_residuals <- function(object, @@ -87,10 +122,10 @@ get_residuals <- function(object, } -#' Prepare residuals for CD / CD* tests +#' Prepare residual matrices for CD and CD* diagnostics #' #' @description -#' Cleans and transforms an \eqn{N \times T} residual matrix for cross-sectional +#' Cleans and transforms an \eqn{N x T} residual matrix for cross-sectional #' dependence testing. Operations include: #' \enumerate{ #' \item Dropping time periods with fewer than \code{min_per_time} finite observations. @@ -98,7 +133,7 @@ get_residuals <- function(object, #' \item Optional demeaning across units at each time (recommended for CD). #' } #' -#' @param E A numeric matrix of residuals (\eqn{N \times T}); rows are units, +#' @param E A numeric matrix of residuals (\eqn{N x T}); rows are units, #' columns are time; may be unbalanced (contain \code{NA}). #' @param standardize One of \code{"row"}, \code{"none"}. #' If \code{"row"}, scale each row by its observed standard deviation. @@ -107,13 +142,45 @@ get_residuals <- function(object, #' @param min_per_time Integer; drop time columns with fewer than this many finite #' observations. #' -#' @returns A list with: -#' \item{Z}{Processed residual matrix (\eqn{N \times T^*}) after filtering/standardizing/demeaning.} +#' @return A list with: +#' \item{Z}{Processed residual matrix (\eqn{N x T^*}) after filtering/standardizing/demeaning.} #' \item{kept_t}{Integer indices of kept time columns (relative to the original \code{E}).} #' \item{m_t}{Integer vector of cross-sectional counts per kept time (number of finite rows).} #' \item{row_sds}{Numeric vector of row standard deviations used (invisibly \code{NA} if \code{standardize="none"}).} #' \item{col_means}{Numeric vector of time means subtracted when \code{demean_time=TRUE}.} #' +#' @details +#' ## Transformation steps +#' +#' \enumerate{ +#' \item Time periods with fewer than \code{min_per_time} finite observations are removed. +#' \item If \code{standardize = "row"}, each unit is scaled by its observed standard deviation. +#' \item If \code{demean_time = TRUE}, each time slice is demeaned across available units. +#' } +#' +#' ## Why this preprocessing matters +#' +#' CD-type tests are sensitive to scale heterogeneity and sparse columns in +#' unbalanced panels. This helper creates a better-conditioned input matrix while +#' preserving as much usable information as possible. +#' +#' @examples +#' data(PWT_60_07, package = "csdm") +#' df <- PWT_60_07 +#' ids <- unique(df$id)[1:10] +#' df_small <- df[df$id %in% ids & df$year >= 1970, ] +#' fit <- csdm( +#' log_rgdpo ~ log_hc + log_ck + log_ngd, +#' data = df_small, +#' id = "id", +#' time = "year", +#' model = "cce", +#' csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +#' ) +#' E <- get_residuals(fit) +#' prep <- prepare_cd_input(E, standardize = "row", demean_time = TRUE, min_per_time = 3) +#' dim(prep$Z) +#' #' @keywords internal #' @export prepare_cd_input <- function(E, diff --git a/README.md b/README.md index 4129020..06fd09a 100644 --- a/README.md +++ b/README.md @@ -1,65 +1,253 @@ -# csdm + +[![R-CMD-check](https://github.com/Macosso/csdm/workflows/R-CMD-check/badge.svg)](https://github.com/Macosso/csdm/actions) + -`csdm` provides Mean Group (MG), Common Correlated Effects (CCE), and Dynamic CCE (DCCE) estimators via `csdm()`. +## Overview -This package does **not** execute Stata code and does **not** claim numerical equivalence to `xtdcce2`. The goal of the mapping below is to provide a conceptual translation and runnable R usage. +The `csdm` package implements econometric methods for panel data with cross-sectional dependence (CSD). In many applications, observations across units (e.g., countries, firms, regions) are not independent—macroeconomic shocks, trade relationships, or spillovers create correlation across cross-sectional units. The `csdm` package provides robust estimators that account for this dependence structure, plus diagnostic tests to detect and characterize it. -## Replicating xtdcce2 syntax (Stata) in csdm (R) +This vignette demonstrates four core estimation methods and related inference tools on real panel data from the Penn World Table (PWT). -### Quick mapping +## Methodology: Four Estimators -| Stata concept / xtdcce2 option (descriptive) | `csdm` syntax | -|---|---| -| Dynamic dependent-variable lag (e.g., `L.y`) | `lr = csdm_lr(type="ardl", ylags=1)` | -| Cross-sectional averages controls | `csa = csdm_csa(vars=c(...), lags=...)` | -| CSA lags (e.g., 3) | `csa = csdm_csa(..., lags=3)` | -| Scalar distributed lags for all RHS regressors | `lr = csdm_lr(type="ardl", xdlags=K)` | -| Pesaran CD test | `cd_test(fit)` | -### Worked end-to-end example (DCCE + CSA + y-lag) +### Model Specification -```r -library(csdm) -data(PWT_60_07, package="csdm") -df <- PWT_60_07 +Consider a panel model with $T$ time periods and $N$ cross-sectional units (e.g., countries): + +$$y_{it} = \alpha_i + \beta_i x_{it} + u_{it}, \quad i = 1, \ldots, N; \quad t = 1, \ldots, T$$ + +where: +- $y_{it}$ is the outcome variable for unit $i$ at time $t$ +- $\alpha_i$ is a unit-specific intercept +- $\beta_i$ is a unit-specific slope (heterogeneous across units) +- $x_{it}$ is explanatory variable(s) +- $u_{it}$ is the idiosyncratic error term + +The key feature is **heterogeneity in slopes** ($\beta_i$ varies by unit), which allows each unit to have its own relationship between $x$ and $y$. Four estimators are available to fit this model under different assumptions about cross-sectional dependence. + +### 1. Mean Group (MG) Estimator + +The Mean Group (MG) estimator fits unit-specific regressions separately and averages the results: + +$$\hat{\beta}_{MG} = \frac{1}{N} \sum_{i=1}^{N} \hat{\beta}_i$$ + +**Interpretation**: The MG coefficient is the simple average of individual unit slopes. It is consistent under mild regularity conditions and allows arbitrary cross-sectional dependence in errors $u_{it}$. + +**Use case**: When dependence is present but you only care about average effects. MG is robust to forms of CSD that would break other methods. + +### 2. Common Correlated Effects (CCE) Estimator + +The Common Correlated Effects (CCE) estimator augments the model with cross-sectional averages of regressors $\bar{x}_t = \frac{1}{N} \sum_{i=1}^{N} x_{it}$: + +$$y_{it} = \alpha_i + \beta_i x_{it} + \gamma_i \bar{x}_t + \gamma_i \bar{y}_t + v_{it}$$ + +By including these cross-sectional mean terms, the estimator **controls for common factors** (unobserved shocks that affect all units similarly). The CCE approach is more efficient than MG when common factor structure is strong, while retaining robustness to CSD. + +**Interpretation**: After accounting for common shocks, the $\beta_i$ coefficients represent unit-specific sensitivities net of factor loadings $\gamma_i$. + +**Use case**: When cross-sectional dependence arises primarily from common shocks or latent factors. + +### 3. Dynamic CCE (DCCE) Estimator + +The Dynamic Common Correlated Effects (DCCE) estimator extends CCE to include lagged dependent variable: + +$$y_{it} = \alpha_i + \lambda_i y_{it-1} + \beta_i x_{it} + \gamma_i \bar{x}_t + \gamma_i \bar{y}_t + v_{it}$$ + +where $\lambda_i$ is the unit-specific autoregressive coefficient. DCCE is ideal for dynamic panel models (e.g., when studying persistence of outcomes over time). + +**Interpretation**: $\lambda_i$ captures dynamic adjustment within units, $\beta_i$ measures the long-run effect after accounting for dynamics, and $\gamma_i$ adjusts for common factors. + +**Use case**: When the outcome has substantial persistence (lagged effects) and cross-sectional dependence is suspected. + +### 4. Cross-Sectionally Augmented ARDL (CS-ARDL) + +The CS-ARDL model extends the ARDL framework with cross-sectional augmentation: + +$$\Delta y_{it} = \alpha_i + \lambda_i (y_{it-1} - \theta_i x_{it-1}) + \beta_i \Delta x_{it} + \hat{\gamma}_i \Delta \bar{x}_t + v_{it}$$ + +This model combines **autoregressive and distributed lag** dynamics. It separates short-run effects ($\beta_i$) from long-run cointegrating relationships ($\theta_i$), all while controlling for common factors. + +**Interpretation**: +- $\theta_i$ is the long-run equilibrium relationship (cointegrating coefficient) +- $\beta_i$ is the short-run adjustment to shocks +- $\lambda_i$ governs speed of reversion to equilibrium + +**Use case**: When studying long-run relationships in non-stationary panels with complex short-run dynamics. + +## Package installation +To install the `csdm` package from CRAN, run: +``` +install.packages("csdm") +``` + +To install the latest development version from GitHub, run: +``` +install.packages("remotes") +remotes::install_github("Macosso/csdm") +``` + + + + +## Model Estimation: Four Examples + + +All models are fitted with `csdm()`, which automatically detects the input structure and applies the appropriate methodology. The key arguments are `id` and `time` to specify the cross-sectional and time-period identifiers, and `model` to choose the estimator. For CCE and DCCE, additional arguments (`csa` and `lr`) specify treatment of cross-sectional averages and dynamics. + +### Example 1: Mean Group (MG) Estimation + +``` +# MG: Separate regression per country, then average coefficients +fit_mg <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df, + id = "id", + time = "year", + model = "mg" +) + +print(fit_mg) +summary(fit_mg) +``` + +### Example 2: Common Correlated Effects (CCE) -fit <- csdm( +``` +# CCE: Add cross-sectional means to control for common shocks +fit_cce <- csdm( log_rgdpo ~ log_hc + log_ck + log_ngd, data = df, - id = "id", + id = "id", + time = "year", + model = "cce", + csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +) + +print(fit_cce) +summary(fit_cce) +``` + +### Example 3: Dynamic CCE (DCCE) + +``` +# DCCE: Include dynamics and cross-sectional means +# Use lagged dependent variable to capture dynamic adjustment +fit_dcce <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df, + id = "id", time = "year", model = "dcce", csa = csdm_csa( - vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), + vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), lags = 3 ), - lr = csdm_lr(type = "ardl", ylags = 1) + lr = csdm_lr(type = "ardl", ylags = 1, xdlags = 0) ) -summary(fit) -cd_test(fit) +print(fit_dcce) +summary(fit_dcce) ``` -### Distributed lags for RHS regressors (`xdlags`) +### Example 4: Cross-Sectionally Augmented ARDL (CS-ARDL) -```r -fit_dx <- csdm( +``` +# CS-ARDL: Separate short-run and long-run dynamics +# Includes lagged dependent and lagged regressors +fit_csardl <- csdm( log_rgdpo ~ log_hc + log_ck + log_ngd, data = df, - id = "id", + id = "id", time = "year", - model = "dcce", + model = "cs_ardl", csa = csdm_csa( - vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), + vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), lags = 3 ), lr = csdm_lr(type = "ardl", ylags = 1, xdlags = 1) ) -names(coef(fit_dx)) +print(fit_csardl) +summary(fit_csardl) ``` -### Notes +## Cross-Sectional Dependence Testing + +After fitting a model, we can test whether residuals exhibit cross-sectional dependence using the Pesaran CD test and related variants. CSD tests detect whether residuals $u_{it}$ are correlated across units—a key assumption violation that can bias standard errors. + +### Four CD Test Types + +All CD tests have null hypothesis: **residuals are cross-sectionally independent**. + +#### 1. Pesaran CD Test + +The Pesaran CD statistic is: + +$$CD = \sqrt{\frac{2}{N(N-1)}} \sum_{i=1}^{N-1} \sum_{j=i+1}^{N} \hat{\rho}_{ij} \sqrt{T}$$ + +where $\hat{\rho}_{ij}$ is the cross-sectional correlation between residuals of units $i$ and $j$. The test statistic is approximately standard normal under the null. + +**Interpretation**: Large $|CD|$ rejects independence; both positive and negative correlations are flagged. This is the most general CD test and works even when $N$ is fixed and $T \to \infty$. + +#### 2. Pesaran CD Weighted (CDw) + +The CDw statistic uses unit-level random sign flips to form a wild-type version of the CD test: + +$$CD_w = \sqrt{\frac{2}{N(N-1)}} \sum_{i=1}^{N-1} \sum_{j=i+1}^{N} w_i w_j \, \hat{\rho}_{ij} \sqrt{T},$$ + +where $(w_1,\ldots,w_N)$ are independent random weights with $w_i \in \{-1,1\}$ applied at the unit level. This statistic can be used in randomization-based or simulation-based inference procedures. + +#### 3. Pesaran CD Weighted Plus (CDw+) + +CDw+ applies an alternative unit-level random sign-flip scheme: + +$$CD_w^+ = \sqrt{\frac{2}{N(N-1)}} \sum_{i=1}^{N-1} \sum_{j=i+1}^{N} w_i^{(+)} w_j^{(+)} \, \hat{\rho}_{ij} \sqrt{T},$$ + +where $(w_1^{(+)},\ldots,w_N^{(+)})$ are again independent random weights with $w_i^{(+)} \in \{-1,1\}$ (typically a separate draw from that used for $CD_w$). + +#### 4. Pesaran CD*, Fan-Liao-Yao (FLY) + +The CD* statistic is a semiparametric refinement for large $N$ and $T$: + +$$CD^* = \frac{1}{\sqrt{N(N-1)}} \sum_{i=1}^{N-1} \sum_{j=i+1}^{N} (\hat{\rho}_{ij}^2 - \tau_T)$$ + +where $\tau_T$ is a variance adjustment. FLY-type tests are designed for large panel dimensions and provide robustness against certain forms of weak cross-sectional dependence. + +### Running CD Tests with Seed Selection + +The `cd_test()` function accepts the fitted model and computes all test variants. Tests use a **random seed** to initialize pseudo-random computations (for `cdw` and `cdw+`); setting a `seed` ensures reproducibility of numerical results across runs. + +```r +# Test MG residuals for CSD +cd_mg <- cd_test(fit_mg, type = "CD") +print(cd_mg) + +# Test CCE residuals for CSD +set.seed(1234) +cd_cce <- cd_test(fit_cce, type = "all") +print(cd_cce) +``` + +**Interpreting Results**: + +- **CD statistic p-value < 0.05**: Reject null of CSD independence; residuals are correlated across units. +- **CDw, CDw+, CD* variants**: Provide robustness checks; if all reject the null, CSD is strongly evidenced. +- **Magnitude**: Large $|CD|$ statistics (e.g., $|CD| > 3$) indicate substantial and economically meaningful dependence. + +In practice, models that do not account for cross-sectional dependence (like MG without augmentation) typically show significant CD test rejections, justifying the use of CSD-robust methods like CCE and DCCE. + +## References + +Chudik, A., & Pesaran, M. H. (2013). Common correlated effects estimation of heterogeneous dynamic panel data models with weakly exogenous regressors. *Journal of Business and Economic Statistics*, 33(2), 232–247. + +Ditzen, J. (2021). Estimating dynamic common-correlated effects in Stata. *The Stata Journal*, 21(1), 39–59. + +Fan, J., Liao, Y., & Yao, J. (2015). Power-enhanced simultaneous test for high-dimensional covariance matrix. *Journal of the American Statistical Association*, 110(510), 325–337. + +Juodis, A., & Reese, S. (2022). The role of the *N/T* ratio in large N, large T panel time-series models. *Econometric Reviews*, 41(2), 221–261. + +Pesaran, M. H. (2007). A simple unit root test in the presence of cross-section dependence. *Journal of Applied Econometrics*, 22(2), 265–312. + +Pesaran, M. H., & Xie, Y. (2021). A bias-adjusted LM test of error cross-section independence. *Econometric Reviews*, 40(1), 7–24. -- `xdlags` currently supports only **simple RHS variable names** (no transformations or interactions like `log(x)` or `x1:x2`). -- Generated lag columns follow the naming convention `lag1_`, `lag2_`, ... diff --git a/man/PWT_60_07.Rd b/man/PWT_60_07.Rd index e2ad31e..2ada3cc 100644 --- a/man/PWT_60_07.Rd +++ b/man/PWT_60_07.Rd @@ -7,24 +7,24 @@ \format{ A data frame with 4464 rows and 6 variables: \describe{ - \item{id}{Unit identifier (country id).} - \item{year}{Time identifier (year, 1960–2007).} - \item{log_rgdpo}{Log real GDP (output).} - \item{log_hc}{Log human capital index.} - \item{log_ck}{Log capital stock.} - \item{log_ngd}{Log (net) government debt (or similar), used as a covariate/control.} +\item{id}{Unit identifier (country id).} +\item{year}{Time identifier (year, 1960–2007).} +\item{log_rgdpo}{Log real GDP (output).} +\item{log_hc}{Log human capital index.} +\item{log_ck}{Log capital stock.} +\item{log_ngd}{Log (net) government debt (or similar), used as a covariate/control.} } } \source{ Penn World Table (PWT). This dataset is included as a small, convenient - panel for examples and tests. +panel for examples and tests. } \usage{ PWT_60_07 } \description{ A panel of 93 countries (unit id) observed annually over 1960–2007 (time/year), -with the log-transformed variables used in +with the log-transformed variables used in xtdcce2-style examples. } \keyword{datasets} diff --git a/man/cd_test.Rd b/man/cd_test.Rd index f1ce7ae..9e1f508 100644 --- a/man/cd_test.Rd +++ b/man/cd_test.Rd @@ -5,7 +5,7 @@ \alias{cd_test.default} \alias{cd_test.csdm_fit} \alias{print.cd_test} -\title{Cross-sectional dependence (CD) tests for panel data} +\title{Cross-sectional dependence (CD) tests for panel residuals} \usage{ cd_test(object, ...) @@ -55,40 +55,55 @@ removes time periods with any missing observations to create a balanced panel fo \item{digits}{Number of digits to print (default 3).} } \value{ -An object of class \code{cd_test} with a \code{tests} list. - Each test returns a sublist with: - \item{statistic}{Test statistic value} - \item{p.value}{Two-sided p-value under standard normal null} +An object of class \code{cd_test} with fields \code{tests}, \code{type}, +\code{N}, \code{T}, \code{na.action}, and \code{call}. The \code{tests} list +contains one or more test results, each with \code{statistic} and \code{p.value}. } \description{ -Computes cross-sectional dependence tests for panel residuals: CD (Pesaran 2015), -CDw (Juodis & Reese 2021), CDw+ (Fan et al. 2015), and CD* (Pesaran & Xie 2021) -with PCA-based factor adjustment. +Computes Pesaran CD, CDw, CDw+, and CD* tests for cross-sectional dependence +in panel residuals. The implementation supports residual matrices or fitted +\code{csdm_fit} objects and provides consistent handling of unbalanced panels. } \details{ -\strong{Handling of missing data:} -\itemize{ - \item \strong{CD, CDw, CDw+:} Always use pairwise-complete observations. Each pair (i,j) - correlation is computed over time periods where both units have finite residuals. - \item \strong{CD*:} By default (\code{na.action = "drop.incomplete.times"}), automatically - removes time periods with any missing observations to create a balanced panel and - applies CD*. With \code{na.action = "pairwise"}, requires a balanced panel and - returns \code{NA} with a warning if NAs are present. -} - -When \code{na.action = "drop.incomplete.times"}, the function reports how many time periods -were dropped and the dimensions of the resulting balanced panel. - -\strong{Test descriptions:} -\itemize{ - \item \strong{CD (Pesaran 2015, 2021):} Classic test using pairwise correlations. - Statistic: \eqn{CD = \sqrt{2/(N(N-1))} \sum_{i= 1970, ] +fit <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df_small, + id = "id", + time = "year", + model = "cce", + csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +) +cd_test(fit, type = "all") + } \references{ Pesaran, M.H. (2015). "Testing weak cross-sectional dependence in large panels." - \emph{Econometric Reviews}, 34(6-10), 1089-1117. +\emph{Econometric Reviews}, 34(6-10), 1089-1117. + +Pesaran, M.H. (2021). "General diagnostic tests for cross-sectional dependence +in panels." \emph{Empirical Economics}, 60, 13-50. Juodis, A., & Reese, S. (2021). "The incidental parameters problem in testing for - remaining cross-sectional correlation." \emph{Journal of Business & Economic Statistics}. +remaining cross-sectional correlation." \emph{Journal of Business and Economic Statistics}, +40(3), 1193-1203. Fan, J., Liao, Y., & Yao, J. (2015). "Power Enhancement in High-Dimensional - Cross-Sectional Tests." \emph{Econometric Reviews}, 34(6-10), 742-779. +Cross-Sectional Tests." \emph{Econometric Reviews}, 34(6-10), 742-779. Pesaran, M.H., & Xie, Y. (2021). "A bias-corrected CD test for error cross-sectional - dependence in panel models." \emph{Econometric Reviews}, 41(6), 649-677. +dependence in panel models." \emph{Econometric Reviews}, 41(6), 649-677. } diff --git a/man/cluster_vcov.Rd b/man/cluster_vcov.Rd index 36b936d..6343b57 100644 --- a/man/cluster_vcov.Rd +++ b/man/cluster_vcov.Rd @@ -13,8 +13,8 @@ cluster_vcov(X, u, cluster, df_correction = TRUE, type = c("oneway", "twoway")) \item{cluster}{One of: \itemize{ - \item a vector (length n) of cluster ids for one-way clustering; or - \item a data.frame/list with two vectors (each length n) for two-way clustering. +\item a vector (length n) of cluster ids for one-way clustering; or +\item a data.frame/list with two vectors (each length n) for two-way clustering. }} \item{df_correction}{Logical; apply small-sample corrections. Default \code{TRUE}.} diff --git a/man/coef.csdm_fit.Rd b/man/coef.csdm_fit.Rd new file mode 100644 index 0000000..bee196d --- /dev/null +++ b/man/coef.csdm_fit.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/csdm_methods.R +\name{coef.csdm_fit} +\alias{coef.csdm_fit} +\title{Extract model coefficients from a fitted csdm model} +\usage{ +\method{coef}{csdm_fit}(object, ...) +} +\arguments{ +\item{object}{A fitted object of class \code{csdm_fit}.} + +\item{...}{Currently unused.} +} +\value{ +A named numeric vector of estimated coefficients. +} +\description{ +Returns estimated mean-group coefficients from a \code{csdm_fit} object. For +\code{model = "cs_ardl"}, the returned vector includes short-run mean-group +coefficients, the adjustment coefficient (named \code{lr_}), and long-run +coefficients when available. +} +\seealso{ +\code{\link[=summary.csdm_fit]{summary.csdm_fit()}}, \code{\link[=vcov.csdm_fit]{vcov.csdm_fit()}} +} diff --git a/man/cross_sectional_avg.Rd b/man/cross_sectional_avg.Rd index 8b16d0c..860b2e3 100644 --- a/man/cross_sectional_avg.Rd +++ b/man/cross_sectional_avg.Rd @@ -32,8 +32,8 @@ If \code{FALSE}, computes standard time means: \item{weights}{Optional. Either: \itemize{ - \item a numeric vector of length \code{nrow(data)}, or - \item the name of a column in \code{data} with nonnegative weights. +\item a numeric vector of length \code{nrow(data)}, or +\item the name of a column in \code{data} with nonnegative weights. } If \code{NULL}, uses equal weights (1 for observed values).} @@ -41,8 +41,8 @@ If \code{NULL}, uses equal weights (1 for observed values).} \item{return_mode}{One of \code{"attach"} or \code{"time"}. \itemize{ - \item \code{"attach"} returns the original \code{data} with CSA columns added. - \item \code{"time"} returns a unique-time table \code{[time, csa_*]}. +\item \code{"attach"} returns the original \code{data} with CSA columns added. +\item \code{"time"} returns a unique-time table \code{[time, csa_*]}. }} \item{na.rm}{Logical; if \code{TRUE}, excludes \code{NA}s from sums and @@ -51,11 +51,11 @@ for that time's CSA for that variable.} } \value{ A \code{data.frame}: - \itemize{ - \item If \code{return_mode="attach"}: original data + CSA columns - named \code{paste0(suffix, "_", vars)}. - \item If \code{return_mode="time"}: unique time rows with CSA columns. - } +\itemize{ +\item If \code{return_mode="attach"}: original data + CSA columns +named \code{paste0(suffix, "_", vars)}. +\item If \code{return_mode="time"}: unique time rows with CSA columns. +} } \description{ Computes cross-sectional averages (CSAs) of specified variables for each time diff --git a/man/csdm.Rd b/man/csdm.Rd index 8baed41..8e838bc 100644 --- a/man/csdm.Rd +++ b/man/csdm.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/csdm.R \name{csdm} \alias{csdm} -\title{Unified front door for csdm estimators} +\title{Panel Model Estimation with Cross Section Dependence} \usage{ csdm( formula, @@ -21,61 +21,141 @@ csdm( ) } \arguments{ -\item{formula}{A model formula like `y ~ x1 + x2`.} +\item{formula}{Model formula of the form \code{y ~ x1 + x2}.} -\item{data}{A `data.frame` (or `plm::pdata.frame`) containing the variables in `formula`.} +\item{data}{A \code{data.frame} (or \code{plm::pdata.frame}) containing the +variables in \code{formula}.} -\item{id, time}{Column names (strings) for the unit and time indexes. -If `data` is a `pdata.frame`, these are taken from its index and the provided values are ignored.} +\item{id, time}{Column names (strings) for the unit and time indexes. If +\code{data} is a \code{pdata.frame}, these are taken from its index and the +provided values are ignored.} -\item{model}{Which estimator to fit. Currently implemented: `"mg"`, `"cce"`, `"dcce"`.} +\item{model}{Estimator to fit. One of \code{"mg"}, \code{"cce"}, +\code{"dcce"}, or \code{"cs_ardl"}.} -\item{csa}{Cross-sectional-average specification, created by [csdm_csa()].} +\item{csa}{Cross-sectional-average specification, created by \code{\link[=csdm_csa]{csdm_csa()}}.} -\item{lr}{Long-run specification (currently a stub), created by [csdm_lr()].} +\item{lr}{Long-run or dynamic specification, created by \code{\link[=csdm_lr]{csdm_lr()}}.} -\item{pooled}{Pooled specification (currently a stub), created by [csdm_pooled()].} +\item{pooled}{Pooled specification (reserved for future use), created by +\code{\link[=csdm_pooled]{csdm_pooled()}}.} -\item{trend}{One of `"none"` or `"unit"` (a linear trend per unit is added as a regressor). -`"pooled"` is reserved and not implemented.} +\item{trend}{One of \code{"none"} or \code{"unit"} (adds a linear unit trend). +\code{"pooled"} is reserved and not implemented.} \item{fullsample}{Logical; reserved for future extensions.} \item{mgmissing}{Logical; reserved for future extensions.} -\item{vcov}{Variance-covariance specification, created by [csdm_vcov()].} +\item{vcov}{Variance-covariance specification, created by \code{\link[=csdm_vcov]{csdm_vcov()}}.} \item{...}{Reserved for future extensions.} } \value{ -An object of class `csdm_fit`. +An object of class \code{csdm_fit} containing estimated coefficients, +residuals, variance-covariance estimates, model metadata, and diagnostics. +Use \code{summary()}, \code{coef()}, \code{residuals()}, \code{vcov()}, and +\code{cd_test()} to access standard outputs. } \description{ -Unified front door for csdm estimators +Estimate panel data models that allow for cross-sectional dependence and +heterogeneous slopes. The interface supports Mean Group (MG), Common +Correlated Effects (CCE), Dynamic CCE (DCCE), and Cross-Sectionally +Augmented ARDL (CS-ARDL) estimators with consistent handling of +cross-sectional averages, dynamic structure, and robust inference. +} +\details{ +\subsection{Model equations}{ + +\describe{ +\item{MG (Pesaran and Smith, 1995)}{ +\deqn{y_{it} = x_{it}^\top \beta_i + u_{it}} +} +\item{CCE (Pesaran, 2006)}{ +\deqn{y_{it} = x_{it}^\top \beta_i + \lambda_i^\top F_t + u_{it}} +} +\item{DCCE (Chudik and Pesaran, 2015)}{ +\deqn{\Delta y_{it} = \Delta x_{it}^\top \beta_i + \lambda_i^\top \Delta F_t + u_{it}} +} +\item{CS-ARDL (Chudik and Pesaran, 2015)}{ +\deqn{y_{it} = \phi_i y_{it-1} + x_{it}^\top \theta_i + \lambda_i^\top F_t + u_{it}} +} +} +} + +\subsection{Estimation, identification, and assumptions}{ + +\describe{ +\item{MG}{Unit-by-unit estimation with heterogeneous slopes. The reported +coefficients are cross-sectional averages of unit estimates. Requires +sufficient time series per unit and weak serial dependence in errors.} +\item{CCE}{Augments regressions with cross-sectional averages (CSA) to proxy +unobserved common factors. Identification relies on large N and T, weak +dependence in idiosyncratic errors after CSA, and weak exogeneity of +regressors.} +\item{DCCE}{Extends CCE to dynamic settings with lagged dependent variables +and CSA lags. Identification relies on weak exogeneity, adequate time length +for dynamic lags, and a stable factor structure.} +\item{CS-ARDL}{Specifies dynamic distributed lags with CSA terms. Estimation +follows ARDL-style dynamics in each unit and aggregates to panel averages. +Assumes weak exogeneity and sufficient time length for lag structure.} +} +} } \examples{ +library(csdm) data(PWT_60_07, package = "csdm") df <- PWT_60_07 -# Keep examples fast: use a small subset +# Keep examples fast but fully runnable keep_ids <- unique(df$id)[1:10] -# Use enough time periods so DCCE + CSA lags is estimable df_small <- df[df$id \%in\% keep_ids & df$year >= 1970, ] -# xtdcce2-style DCCE specification -fit <- csdm( +# Mean Group (MG) +mg <- csdm( log_rgdpo ~ log_hc + log_ck + log_ngd, - data = df_small, - id = "id", - time = "year", - model = "dcce", - csa = csdm_csa( - vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), - lags = 3 - ), - lr = csdm_lr(type = "ardl", ylags = 1) + data = df_small, id = "id", time = "year", model = "mg" ) +summary(mg) + +# Common Correlated Effects (CCE) +cce <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df_small, id = "id", time = "year", model = "cce", + csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +) +summary(cce) + +# Dynamic CCE (DCCE) +dcce <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df_small, id = "id", time = "year", model = "dcce", + csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), lags = 3), + lr = csdm_lr(type = "ardl", ylags = 1, xdlags = 0) +) +summary(dcce) + +# CS-ARDL +cs_ardl <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df_small, id = "id", time = "year", model = "cs_ardl", + csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), lags = 3), + lr = csdm_lr(type = "ardl", ylags = 1, xdlags = 0) +) +summary(cs_ardl) +} +\references{ +Pesaran, M.H. and Smith, R. (1995). "Estimating long-run relationships from +dynamic heterogeneous panels." Journal of Econometrics, 68(1), 79-113. + +Pesaran, M.H. (2006). "Estimation and inference in large heterogeneous panels +with multifactor error structure." Econometrica, 74(4), 967-1012. + +Chudik, A. and Pesaran, M.H. (2015). "Common correlated effects estimation of +heterogeneous dynamic panel data models with weakly exogenous regressors." +Journal of Econometrics, 188(2), 393-420. -summary(fit) -cd_test(fit) +Chudik, A. and Pesaran, M.H. (2015). "Large panel data models with +cross-sectional dependence: A survey." Annals of Economics and Finance, 16(1), +53-78. } diff --git a/man/get_residuals.Rd b/man/get_residuals.Rd index e25c9f4..dca3455 100644 --- a/man/get_residuals.Rd +++ b/man/get_residuals.Rd @@ -2,24 +2,24 @@ % Please edit documentation in R/utils_residuals.R \name{get_residuals} \alias{get_residuals} -\title{Extract residual matrices from model objects} +\title{Extract residual matrices for panel diagnostics} \usage{ get_residuals(object, type = c("auto", "cce", "pca", "pca_std"), strict = TRUE) } \arguments{ \item{object}{A fitted model object supported by this package (e.g., class \code{csdm_fit}), or directly a numeric matrix of residuals shaped as -\eqn{N \times T}.} +\eqn{N x T}.} \item{type}{Character string selecting which residuals to return when available: one of \code{"auto"}, \code{"cce"}, \code{"pca"}, or \code{"pca_std"}. \itemize{ - \item \code{"auto"}: prefer standardized PCA residuals if present, otherwise - PCA residuals, otherwise CCE residuals, otherwise \code{object} if it is a matrix. - \item \code{"cce"}: residuals from the CCE-augmented per-unit regressions. - \item \code{"pca"}: residuals after removing estimated factors from \eqn{\hat v_{it}}. - \item \code{"pca_std"}: \code{"pca"} residuals standardized by unit-specific - scale (recommended for CD). +\item \code{"auto"}: prefer standardized PCA residuals if present, otherwise +PCA residuals, otherwise CCE residuals, otherwise \code{object} if it is a matrix. +\item \code{"cce"}: residuals from the CCE-augmented per-unit regressions. +\item \code{"pca"}: residuals after removing estimated factors from \eqn{\hat v_{it}}. +\item \code{"pca_std"}: \code{"pca"} residuals standardized by unit-specific +scale (recommended for CD). }} \item{strict}{Logical; if \code{TRUE}, error on unsupported objects. If \code{FALSE}, @@ -27,11 +27,49 @@ return \code{NULL} when residuals cannot be found.} } \value{ A numeric matrix of residuals with rows = units and columns = time, - preserving \code{rownames} and \code{colnames} when available; or \code{NULL} - if nothing suitable is found and \code{strict = FALSE}. +preserving \code{rownames} and \code{colnames} when available; or \code{NULL} +if nothing suitable is found and \code{strict = FALSE}. } \description{ -Unified accessor that returns an \eqn{N \times T} residual matrix suitable for -cross-sectional dependence testing. +Unified accessor that returns an \eqn{N x T} residual matrix suitable for +cross-sectional dependence diagnostics and post-estimation analysis. +} +\details{ +\subsection{Residual types}{ + +\describe{ +\item{cce}{Residuals from the cross-sectionally augmented unit regressions.} +\item{pca}{Residuals after principal-component factor removal.} +\item{pca_std}{PCA residuals standardized by unit-specific scale.} +\item{auto}{Priority rule: \code{pca_std} -> \code{pca} -> \code{cce} -> +generic residual slots.} +} +} + +\subsection{Assumptions and usage}{ + +The returned matrix is intended for diagnostics that operate on unit-time panels, +including \code{\link[=cd_test]{cd_test()}}. Missing values are preserved unless downstream routines +explicitly filter or balance the panel. +} +} +\examples{ +data(PWT_60_07, package = "csdm") +df <- PWT_60_07 +ids <- unique(df$id)[1:10] +df_small <- df[df$id \%in\% ids & df$year >= 1970, ] + +fit <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df_small, + id = "id", + time = "year", + model = "cce", + csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +) + +E <- get_residuals(fit, type = "auto") +dim(E) + } \keyword{internal} diff --git a/man/pooled_vcov.Rd b/man/pooled_vcov.Rd index 621d739..6fd86cf 100644 --- a/man/pooled_vcov.Rd +++ b/man/pooled_vcov.Rd @@ -17,7 +17,7 @@ summing to 1. If \code{NULL}, uses equal weights.} } \value{ A \code{K x K} covariance matrix for the MG mean, with - \code{dimnames} inherited from \code{colnames(beta_i)}. +\code{dimnames} inherited from \code{colnames(beta_i)}. } \description{ Computes the covariance matrix of the MG estimator \eqn{\bar{\beta} = N^{-1} \sum_i \hat\beta_i}, diff --git a/man/predict.csdm_fit.Rd b/man/predict.csdm_fit.Rd new file mode 100644 index 0000000..b604430 --- /dev/null +++ b/man/predict.csdm_fit.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/csdm_methods.R +\name{predict.csdm_fit} +\alias{predict.csdm_fit} +\title{Predict method for csdm models} +\usage{ +\method{predict}{csdm_fit}(object, newdata = NULL, type = c("xb", "residuals"), ...) +} +\arguments{ +\item{object}{A fitted object of class \code{csdm_fit}.} + +\item{newdata}{Optional new data (not yet supported).} + +\item{type}{One of \code{"xb"} for fitted values or \code{"residuals"}.} + +\item{...}{Currently unused.} +} +\value{ +A numeric matrix of fitted values or residuals, depending on +\code{type}. +} +\description{ +Produces fitted values (index \code{"xb"}) when available, or returns model +residuals. Prediction on new data is not yet implemented. +} +\seealso{ +\code{\link[=residuals.csdm_fit]{residuals.csdm_fit()}}, \code{\link[=summary.csdm_fit]{summary.csdm_fit()}} +} diff --git a/man/prepare_cd_input.Rd b/man/prepare_cd_input.Rd index cd14901..1f42944 100644 --- a/man/prepare_cd_input.Rd +++ b/man/prepare_cd_input.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/utils_residuals.R \name{prepare_cd_input} \alias{prepare_cd_input} -\title{Prepare residuals for CD / CD* tests} +\title{Prepare residual matrices for CD and CD* diagnostics} \usage{ prepare_cd_input( E, @@ -12,7 +12,7 @@ prepare_cd_input( ) } \arguments{ -\item{E}{A numeric matrix of residuals (\eqn{N \times T}); rows are units, +\item{E}{A numeric matrix of residuals (\eqn{N x T}); rows are units, columns are time; may be unbalanced (contain \code{NA}).} \item{standardize}{One of \code{"row"}, \code{"none"}. @@ -26,19 +26,54 @@ observations.} } \value{ A list with: -\item{Z}{Processed residual matrix (\eqn{N \times T^*}) after filtering/standardizing/demeaning.} +\item{Z}{Processed residual matrix (\eqn{N x T^*}) after filtering/standardizing/demeaning.} \item{kept_t}{Integer indices of kept time columns (relative to the original \code{E}).} \item{m_t}{Integer vector of cross-sectional counts per kept time (number of finite rows).} \item{row_sds}{Numeric vector of row standard deviations used (invisibly \code{NA} if \code{standardize="none"}).} \item{col_means}{Numeric vector of time means subtracted when \code{demean_time=TRUE}.} } \description{ -Cleans and transforms an \eqn{N \times T} residual matrix for cross-sectional +Cleans and transforms an \eqn{N x T} residual matrix for cross-sectional dependence testing. Operations include: \enumerate{ - \item Dropping time periods with fewer than \code{min_per_time} finite observations. - \item Optional row-wise standardization to unit variance over available times. - \item Optional demeaning across units at each time (recommended for CD). +\item Dropping time periods with fewer than \code{min_per_time} finite observations. +\item Optional row-wise standardization to unit variance over available times. +\item Optional demeaning across units at each time (recommended for CD). } +} +\details{ +\subsection{Transformation steps}{ + +\enumerate{ +\item Time periods with fewer than \code{min_per_time} finite observations are removed. +\item If \code{standardize = "row"}, each unit is scaled by its observed standard deviation. +\item If \code{demean_time = TRUE}, each time slice is demeaned across available units. +} +} + +\subsection{Why this preprocessing matters}{ + +CD-type tests are sensitive to scale heterogeneity and sparse columns in +unbalanced panels. This helper creates a better-conditioned input matrix while +preserving as much usable information as possible. +} +} +\examples{ +data(PWT_60_07, package = "csdm") +df <- PWT_60_07 +ids <- unique(df$id)[1:10] +df_small <- df[df$id \%in\% ids & df$year >= 1970, ] +fit <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df_small, + id = "id", + time = "year", + model = "cce", + csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +) +E <- get_residuals(fit) +prep <- prepare_cd_input(E, standardize = "row", demean_time = TRUE, min_per_time = 3) +dim(prep$Z) + } \keyword{internal} diff --git a/man/print.csdm_fit.Rd b/man/print.csdm_fit.Rd new file mode 100644 index 0000000..f6cd6b4 --- /dev/null +++ b/man/print.csdm_fit.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/csdm_methods.R +\name{print.csdm_fit} +\alias{print.csdm_fit} +\title{Compact print method for fitted csdm models} +\usage{ +\method{print}{csdm_fit}(x, digits = 4, ...) +} +\arguments{ +\item{x}{A fitted object of class \code{csdm_fit}.} + +\item{digits}{Number of printed digits.} + +\item{...}{Currently unused.} +} +\value{ +Invisibly returns \code{x}. +} +\description{ +Prints a concise overview of a fitted \code{csdm_fit} object, including the +model type, formula, panel dimensions, and a coefficient table with standard +errors when available. +} +\seealso{ +\code{\link[=summary.csdm_fit]{summary.csdm_fit()}}, \code{\link[=coef.csdm_fit]{coef.csdm_fit()}}, \code{\link[=residuals.csdm_fit]{residuals.csdm_fit()}} +} diff --git a/man/print.summary.csdm_fit.Rd b/man/print.summary.csdm_fit.Rd index 4f1054c..6fb07c8 100644 --- a/man/print.summary.csdm_fit.Rd +++ b/man/print.summary.csdm_fit.Rd @@ -2,21 +2,30 @@ % Please edit documentation in R/csdm_methods.R \name{print.summary.csdm_fit} \alias{print.summary.csdm_fit} -\title{Print summary of csdm_fit model} +\title{Print method for csdm summary objects} \usage{ \method{print}{summary.csdm_fit}(x, digits = 4, ...) } \arguments{ -\item{x}{A summary.csdm_fit object.} +\item{x}{A \code{summary.csdm_fit} object.} \item{digits}{Number of digits to print.} \item{...}{Further arguments passed to methods.} } +\value{ +Invisibly returns \code{x}. +} \description{ -Print summary of csdm_fit model +Formats and prints a \code{summary.csdm_fit} object. Output adapts to model +type and includes coefficient tables, selected goodness-of-fit diagnostics, +and compact model metadata. } \details{ -Displays classic Pesaran CD test statistics in the summary output. For extended CD diagnostics -(CDw, CDw+, CD*), call `cd_test()` on the fitted model object. +The printout includes classic Pesaran CD diagnostics from the summary object. +For a full CD diagnostic panel (CD, CDw, CDw+, CD*), use \code{\link[=cd_test]{cd_test()}} on the +fitted model. +} +\seealso{ +\code{\link[=summary.csdm_fit]{summary.csdm_fit()}}, \code{\link[=cd_test]{cd_test()}} } diff --git a/man/residuals.csdm_fit.Rd b/man/residuals.csdm_fit.Rd new file mode 100644 index 0000000..f9f4aa3 --- /dev/null +++ b/man/residuals.csdm_fit.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/csdm_methods.R +\name{residuals.csdm_fit} +\alias{residuals.csdm_fit} +\title{Extract residual matrix from a fitted csdm model} +\usage{ +\method{residuals}{csdm_fit}(object, type = c("e", "u"), ...) +} +\arguments{ +\item{object}{A fitted object of class \code{csdm_fit}.} + +\item{type}{Residual type. Currently only \code{"e"} is implemented.} + +\item{...}{Currently unused.} +} +\value{ +A numeric matrix of residuals with dimensions \eqn{N x T}. +} +\description{ +Returns residuals as an \eqn{N x T} matrix (rows are units, columns are time). +This method is designed for panel diagnostics and downstream tools such as +\code{\link[=cd_test]{cd_test()}}. +} +\seealso{ +\code{\link[=get_residuals]{get_residuals()}}, \code{\link[=cd_test]{cd_test()}}, \code{\link[=predict.csdm_fit]{predict.csdm_fit()}} +} diff --git a/man/summary.csdm_fit.Rd b/man/summary.csdm_fit.Rd index b689fca..bc2ff35 100644 --- a/man/summary.csdm_fit.Rd +++ b/man/summary.csdm_fit.Rd @@ -2,24 +2,58 @@ % Please edit documentation in R/csdm_methods.R \name{summary.csdm_fit} \alias{summary.csdm_fit} -\title{Summarize csdm_fit model results} +\title{Summarize csdm model estimation results} \usage{ \method{summary}{csdm_fit}(object, digits = 4, ...) } \arguments{ -\item{object}{A csdm_fit model object.} +\item{object}{A fitted model object of class \code{csdm_fit}.} \item{digits}{Number of digits to print.} \item{...}{Further arguments passed to methods.} } \value{ -An object of class 'summary.csdm_fit'. +An object of class \code{summary.csdm_fit} with core metadata +(call/formula/model/N/T), coefficient tables, fit statistics, and +model-specific components for printing and downstream inspection. } \description{ -Summarize csdm_fit model results +Computes post-estimation summaries for \code{csdm_fit} objects, including +mean-group coefficient inference, model-level diagnostics, and model-specific +summary tables (for example, short-run and long-run blocks for CS-ARDL). } \details{ -The summary displays classic Pesaran CD test statistics. For additional CD diagnostics -(CDw, CDw+, CD*), use `cd_test()` on the fitted model object. +\subsection{Reported inference}{ + +For each coefficient \eqn{\hat\beta_k}, the summary reports standard errors, +\eqn{z}-statistics, and two-sided normal-approximation p-values: +\deqn{z_k = \frac{\hat\beta_k}{\operatorname{se}(\hat\beta_k)}, \qquad +p_k = 2\{1-\Phi(|z_k|)\}.} +} + +\subsection{Diagnostics}{ + +The printed summary shows the classic Pesaran CD diagnostic by default. Extended +diagnostics (CDw, CDw+, CD*) are available through \code{\link[=cd_test]{cd_test()}}. +} +} +\examples{ +data(PWT_60_07, package = "csdm") +df <- PWT_60_07 +ids <- unique(df$id)[1:10] +df_small <- df[df$id \%in\% ids & df$year >= 1970, ] +fit <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df_small, + id = "id", + time = "year", + model = "cce", + csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +) +s <- summary(fit) +s +} +\seealso{ +\code{\link[=print.summary.csdm_fit]{print.summary.csdm_fit()}}, \code{\link[=cd_test]{cd_test()}}, \code{\link[=coef.csdm_fit]{coef.csdm_fit()}}, \code{\link[=vcov.csdm_fit]{vcov.csdm_fit()}} } diff --git a/man/vcov.csdm_fit.Rd b/man/vcov.csdm_fit.Rd new file mode 100644 index 0000000..b60e121 --- /dev/null +++ b/man/vcov.csdm_fit.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/csdm_methods.R +\name{vcov.csdm_fit} +\alias{vcov.csdm_fit} +\title{Extract coefficient covariance matrix from a fitted csdm model} +\usage{ +\method{vcov}{csdm_fit}(object, ...) +} +\arguments{ +\item{object}{A fitted object of class \code{csdm_fit}.} + +\item{...}{Currently unused.} +} +\value{ +A numeric variance-covariance matrix aligned with \code{coef(object)} +for models where this is available. +} +\description{ +Extract coefficient covariance matrix from a fitted csdm model +} +\seealso{ +\code{\link[=coef.csdm_fit]{coef.csdm_fit()}}, \code{\link[=summary.csdm_fit]{summary.csdm_fit()}} +} diff --git a/renv.lock b/renv.lock index fdc6e7d..33348ce 100644 --- a/renv.lock +++ b/renv.lock @@ -9,17 +9,6 @@ ] }, "Packages": { - "Formula": { - "Package": "Formula", - "Version": "1.2-5", - "Source": "Repository", - "Repository": "RSPM", - "Requirements": [ - "R", - "stats" - ], - "Hash": "7a29697b75e027767a53fde6c903eca7" - }, "MASS": { "Package": "MASS", "Version": "7.3-60", @@ -45,31 +34,6 @@ ], "Hash": "d4335fe7207f1c01ab8c41762f5840d4" }, - "Rcpp": { - "Package": "Rcpp", - "Version": "1.0.14", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "methods", - "utils" - ], - "Hash": "e7bdd9ee90e96921ca8a0f1972d66682" - }, - "Rdpack": { - "Package": "Rdpack", - "Version": "2.6.4", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "methods", - "rbibutils", - "tools", - "utils" - ], - "Hash": "1b2ca1972e3b00cd0bb5a98e16403028" - }, "base64enc": { "Package": "base64enc", "Version": "0.1-3", @@ -80,17 +44,6 @@ ], "Hash": "543776ae6848fde2f48ff3816d0628bc" }, - "bdsmatrix": { - "Package": "bdsmatrix", - "Version": "1.3-7", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "methods" - ], - "Hash": "d36e416e5a8f91cf90b5edeb3306703a" - }, "brio": { "Package": "brio", "Version": "1.1.5", @@ -158,27 +111,6 @@ ], "Hash": "16850760556401a2eeb27d39bd11c9cb" }, - "collapse": { - "Package": "collapse", - "Version": "2.1.1", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "Rcpp" - ], - "Hash": "a76a1c7af74cf7cb5b4dc0139d778612" - }, - "cpp11": { - "Package": "cpp11", - "Version": "0.5.2", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R" - ], - "Hash": "2720e3fd3dad08f34b19b56b3d6f073d" - }, "crayon": { "Package": "crayon", "Version": "1.5.3", @@ -230,29 +162,6 @@ ], "Hash": "33698c4b3127fc9f506654607fb73676" }, - "dplyr": { - "Package": "dplyr", - "Version": "1.1.4", - "Source": "Repository", - "Repository": "RSPM", - "Requirements": [ - "R", - "R6", - "cli", - "generics", - "glue", - "lifecycle", - "magrittr", - "methods", - "pillar", - "rlang", - "tibble", - "tidyselect", - "utils", - "vctrs" - ], - "Hash": "fedd9d00c2944ff00a0e2696ccf048ec" - }, "evaluate": { "Package": "evaluate", "Version": "1.0.3", @@ -263,18 +172,6 @@ ], "Hash": "e9651417729bbe7472e32b5027370e79" }, - "fansi": { - "Package": "fansi", - "Version": "1.0.6", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "grDevices", - "utils" - ], - "Hash": "962174cf2aeb5b9eea581522286a911f" - }, "fastmap": { "Package": "fastmap", "Version": "1.2.0", @@ -305,17 +202,6 @@ ], "Hash": "7eb1e342eee7e0a7449c49cdaa526d39" }, - "generics": { - "Package": "generics", - "Version": "0.1.3", - "Source": "Repository", - "Repository": "RSPM", - "Requirements": [ - "R", - "methods" - ], - "Hash": "15e9634c0fcd294799e9b2e929ed1b86" - }, "glue": { "Package": "glue", "Version": "1.8.0", @@ -390,21 +276,6 @@ ], "Hash": "5a07d8ec459d7b80bd4acca5f4a6e062" }, - "lattice": { - "Package": "lattice", - "Version": "0.21-9", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "grDevices", - "graphics", - "grid", - "stats", - "utils" - ], - "Hash": "5558c61e0136e247252f5f952cdaad6a" - }, "lifecycle": { "Package": "lifecycle", "Version": "1.0.4", @@ -418,19 +289,6 @@ ], "Hash": "b8552d117e1b808b09a832f589b79035" }, - "lmtest": { - "Package": "lmtest", - "Version": "0.9-40", - "Source": "Repository", - "Repository": "RSPM", - "Requirements": [ - "R", - "graphics", - "stats", - "zoo" - ], - "Hash": "c6fafa6cccb1e1dfe7f7d122efd6e6a7" - }, "magrittr": { "Package": "magrittr", "Version": "2.0.3", @@ -441,20 +299,6 @@ ], "Hash": "7ce2733a9826b3aeb1775d56fd305472" }, - "maxLik": { - "Package": "maxLik", - "Version": "1.5-2.1", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "generics", - "methods", - "miscTools", - "sandwich" - ], - "Hash": "b9cc31d9ed2ede075cb7b1c684c07b6e" - }, "memoise": { "Package": "memoise", "Version": "2.0.1", @@ -476,47 +320,6 @@ ], "Hash": "0ec19f34c72fab674d8f2b4b1c6410e1" }, - "miscTools": { - "Package": "miscTools", - "Version": "0.6-28", - "Source": "Repository", - "Repository": "RSPM", - "Requirements": [ - "R", - "digest" - ], - "Hash": "1f36c0edc10a5a5f512e424cb576a754" - }, - "nlme": { - "Package": "nlme", - "Version": "3.1-163", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "graphics", - "lattice", - "stats", - "utils" - ], - "Hash": "8d1938040a05566f4f7a14af4feadd6b" - }, - "pillar": { - "Package": "pillar", - "Version": "1.10.2", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "cli", - "glue", - "lifecycle", - "rlang", - "utf8", - "utils", - "vctrs" - ], - "Hash": "1098920a19b5cd5a15bacdc74a89979d" - }, "pkgbuild": { "Package": "pkgbuild", "Version": "1.4.7", @@ -532,16 +335,6 @@ ], "Hash": "ae47817501cafc99f57586b6e5241134" }, - "pkgconfig": { - "Package": "pkgconfig", - "Version": "2.0.3", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "utils" - ], - "Hash": "01f28d4278f15c76cddbea05899c5d6f" - }, "pkgload": { "Package": "pkgload", "Version": "1.4.0", @@ -564,28 +357,6 @@ ], "Hash": "2ec30ffbeec83da57655b850cf2d3e0e" }, - "plm": { - "Package": "plm", - "Version": "2.6-6", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "Formula", - "MASS", - "R", - "Rdpack", - "bdsmatrix", - "collapse", - "lattice", - "lmtest", - "maxLik", - "nlme", - "sandwich", - "stats", - "zoo" - ], - "Hash": "b33195ce3597e9bcaa2b193a07d01dec" - }, "praise": { "Package": "praise", "Version": "1.0.0", @@ -617,21 +388,6 @@ ], "Hash": "093688087b0bacce6ba2f661f36328e2" }, - "purrr": { - "Package": "purrr", - "Version": "1.0.4", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "cli", - "lifecycle", - "magrittr", - "rlang", - "vctrs" - ], - "Hash": "cc8b5d43f90551fa6df0a6be5d640a4f" - }, "rappdirs": { "Package": "rappdirs", "Version": "0.3.3", @@ -642,18 +398,6 @@ ], "Hash": "5e3c5dc0b071b21fa128676560dbe94d" }, - "rbibutils": { - "Package": "rbibutils", - "Version": "2.3", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "tools", - "utils" - ], - "Hash": "dfc034a172fd88fc66b1a703894c4185" - }, "renv": { "Package": "renv", "Version": "1.0.3", @@ -700,26 +444,13 @@ }, "rprojroot": { "Package": "rprojroot", - "Version": "2.0.4", + "Version": "2.1.1", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R" ], - "Hash": "4c8415e0ec1e29f3f4f6fc108bef0144" - }, - "sandwich": { - "Package": "sandwich", - "Version": "3.1-1", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "stats", - "utils", - "zoo" - ], - "Hash": "072bb2d27425f2a58fe71fe1080676ce" + "Hash": "b2453de2d29aa646afe4781defdc7903" }, "sass": { "Package": "sass", @@ -735,36 +466,6 @@ ], "Hash": "3fb78d066fb92299b1d13f6a7c9a90a8" }, - "stringi": { - "Package": "stringi", - "Version": "1.8.7", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "stats", - "tools", - "utils" - ], - "Hash": "2b56088e23bdd58f89aebf43a0913457" - }, - "stringr": { - "Package": "stringr", - "Version": "1.5.1", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "cli", - "glue", - "lifecycle", - "magrittr", - "rlang", - "stringi", - "vctrs" - ], - "Hash": "960e2ae9e09656611e0b8214ad543207" - }, "testthat": { "Package": "testthat", "Version": "3.2.3", @@ -794,64 +495,6 @@ ], "Hash": "42f889439ccb14c55fc3d75c9c755056" }, - "tibble": { - "Package": "tibble", - "Version": "3.2.1", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "fansi", - "lifecycle", - "magrittr", - "methods", - "pillar", - "pkgconfig", - "rlang", - "utils", - "vctrs" - ], - "Hash": "a84e2cc86d07289b3b6f5069df7a004c" - }, - "tidyr": { - "Package": "tidyr", - "Version": "1.3.1", - "Source": "Repository", - "Repository": "RSPM", - "Requirements": [ - "R", - "cli", - "cpp11", - "dplyr", - "glue", - "lifecycle", - "magrittr", - "purrr", - "rlang", - "stringr", - "tibble", - "tidyselect", - "utils", - "vctrs" - ], - "Hash": "915fb7ce036c22a6a33b5a8adb712eb1" - }, - "tidyselect": { - "Package": "tidyselect", - "Version": "1.2.1", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "cli", - "glue", - "lifecycle", - "rlang", - "vctrs", - "withr" - ], - "Hash": "829f27b9c4919c16b593794a6344d6c0" - }, "tinytex": { "Package": "tinytex", "Version": "0.57", @@ -862,30 +505,6 @@ ], "Hash": "02d65e0c0415bf36a7ddc0d2ba50a840" }, - "utf8": { - "Package": "utf8", - "Version": "1.2.4", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R" - ], - "Hash": "62b65c52671e6665f803ff02954446e9" - }, - "vctrs": { - "Package": "vctrs", - "Version": "0.6.5", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "cli", - "glue", - "lifecycle", - "rlang" - ], - "Hash": "c03fa420630029418f7e6da3667aac4a" - }, "waldo": { "Package": "waldo", "Version": "0.6.1", @@ -932,21 +551,6 @@ "Source": "Repository", "Repository": "CRAN", "Hash": "51dab85c6c98e50a18d7551e9d49f76c" - }, - "zoo": { - "Package": "zoo", - "Version": "1.8-14", - "Source": "Repository", - "Repository": "CRAN", - "Requirements": [ - "R", - "grDevices", - "graphics", - "lattice", - "stats", - "utils" - ], - "Hash": "d55a14a07e7f0b4a66f432198bcca194" } } } diff --git a/vignettes/introduction.Rmd b/vignettes/introduction.Rmd deleted file mode 100644 index 7374876..0000000 --- a/vignettes/introduction.Rmd +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: "introduction" -output: rmarkdown::html_vignette -vignette: > - %\VignetteIndexEntry{introduction} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r, include = FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>" -) -``` - -```{r setup} -library(csdm) -``` diff --git a/vignettes/introduction_to_csdm.Rmd b/vignettes/introduction_to_csdm.Rmd new file mode 100644 index 0000000..ac62a98 --- /dev/null +++ b/vignettes/introduction_to_csdm.Rmd @@ -0,0 +1,312 @@ +--- +title: "Introduction to csdm: Panel Data Models with Cross-Sectional Dependence" +author: "Joao Claudio Macosso" +date: "`r Sys.Date()`" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Introduction to csdm} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r setup, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + warning = FALSE, + message = FALSE +) +library(csdm) +``` + +## Overview + +The `csdm` package implements econometric methods for panel data with cross-sectional dependence (CSD). In many applications, observations across units (e.g., countries, firms, regions) are not independent—macroeconomic shocks, trade relationships, or spillovers create correlation across cross-sectional units. The `csdm` package provides robust estimators that account for this dependence structure, plus diagnostic tests to detect and characterize it. + +This vignette demonstrates four core estimation methods and related inference tools on real panel data from the Penn World Table (PWT). + +## Methodology: Four Estimators + + +### Model Specification + +Consider a panel model with $T$ time periods and $N$ cross-sectional units (e.g., countries): + +$$y_{it} = \alpha_i + \beta_i x_{it} + u_{it}, \quad i = 1, \ldots, N; \quad t = 1, \ldots, T$$ + +where: +- $y_{it}$ is the outcome variable for unit $i$ at time $t$ +- $\alpha_i$ is a unit-specific intercept +- $\beta_i$ is a unit-specific slope (heterogeneous across units) +- $x_{it}$ is explanatory variable(s) +- $u_{it}$ is the idiosyncratic error term + +The key feature is **heterogeneity in slopes** ($\beta_i$ varies by unit), which allows each unit to have its own relationship between $x$ and $y$. Four estimators are available to fit this model under different assumptions about cross-sectional dependence. + +### 1. Mean Group (MG) Estimator + +The Mean Group (MG) estimator fits unit-specific regressions separately and averages the results: + +$$\hat{\beta}_{MG} = \frac{1}{N} \sum_{i=1}^{N} \hat{\beta}_i$$ + +**Interpretation**: The MG coefficient is the simple average of individual unit slopes. It is consistent under mild regularity conditions and allows arbitrary cross-sectional dependence in errors $u_{it}$. + +**Use case**: When dependence is present but you only care about average effects. MG is robust to forms of CSD that would break other methods. + +### 2. Common Correlated Effects (CCE) Estimator + +The Common Correlated Effects (CCE) estimator augments the model with cross-sectional averages of regressors $\bar{x}_t = N^{-1} \sum_{i=1}^{N} x_{it}$: + +$$y_{it} = \alpha_i + \beta_i x_{it} + \gamma_i \bar{x}_t + \gamma_i \bar{y}_t + v_{it}$$ + +By including these cross-sectional mean terms, the estimator **controls for common factors** (unobserved shocks that affect all units similarly). The CCE approach is more efficient than MG when common factor structure is strong, while retaining robustness to CSD. + +**Interpretation**: After accounting for common shocks, the $\beta_i$ coefficients represent unit-specific sensitivities net of factor loadings $\gamma_i$. + +**Use case**: When cross-sectional dependence arises primarily from common shocks or latent factors. + +### 3. Dynamic CCE (DCCE) Estimator + +The Dynamic Common Correlated Effects (DCCE) estimator extends CCE to include lagged dependent variable: + +$$y_{it} = \alpha_i + \lambda_i y_{it-1} + \beta_i x_{it} + \gamma_i \bar{x}_t + \gamma_i \bar{y}_t + v_{it}$$ + +where $\lambda_i$ is the unit-specific autoregressive coefficient. DCCE is ideal for dynamic panel models (e.g., when studying persistence of outcomes over time). + +**Interpretation**: $\lambda_i$ captures dynamic adjustment within units, $\beta_i$ measures the long-run effect after accounting for dynamics, and $\gamma_i$ adjusts for common factors. + +**Use case**: When the outcome has substantial persistence (lagged effects) and cross-sectional dependence is suspected. + +### 4. Cross-Sectionally Augmented ARDL (CS-ARDL) + +The CS-ARDL model extends the ARDL framework with cross-sectional augmentation: + +$$\Delta y_{it} = \alpha_i + \lambda_i (y_{it-1} - \theta_i x_{it-1}) + \beta_i \Delta x_{it} + \hat{\gamma}_i \Delta \bar{x}_t + v_{it}$$ + +This model combines **autoregressive and distributed lag** dynamics. It separates short-run effects ($\beta_i$) from long-run cointegrating relationships ($\theta_i$), all while controlling for common factors. + +**Interpretation**: +- $\theta_i$ is the long-run equilibrium relationship (cointegrating coefficient) +- $\beta_i$ is the short-run adjustment to shocks +- $\lambda_i$ governs speed of reversion to equilibrium + +**Use case**: When studying long-run relationships in non-stationary panels with complex short-run dynamics. + +## Data: Penn World Table Subset + +The `PWT_60_07` dataset contains macroeconomic indicators for 93 countries covering 1960–2007 (48 years). Key variables include: + +- `id`: Country identifier +- `year`: Calendar year (1960–2007) +- `log_rgdpo`: Log real GDP per capita +- `log_hc`: Log human capital index +- `log_ck`: Log capital stock +- `log_ngd`: Log government debt (control variable) + +```{r load-data} +data(PWT_60_07, package = "csdm") +head(PWT_60_07, 10) +str(PWT_60_07) + +# For computational speed in this vignette, use a subset: +# first 15 countries, 1970-2007 +first_15_ids <- unique(PWT_60_07$id)[1:15] +df <- subset(PWT_60_07, id %in% first_15_ids & year >= 1970 & year <= 2007) +``` + +The panel is relatively balanced. We will use growth regressions: modeling log-GDP (`log_rgdpo`) as a function of human capital (`log_hc`), capital stock (`log_ck`), and government debt (`log_ngd`), and test cross-sectional dependence in residuals. + +## Package installation +To install the `csdm` package from CRAN, run: +```{r install-package, eval = FALSE} +install.packages("csdm") +``` + +To install the latest development version from GitHub, run: +```{r install-github, eval = FALSE} +install.packages("remotes") +remotes::install_github("Macosso/csdm") +``` + +## Model Estimation: Four Examples + + +All models are fitted with `csdm()`, which automatically detects the input structure and applies the appropriate methodology. The key arguments are `id` and `time` to specify the cross-sectional and time-period identifiers, and `model` to choose the estimator. For CCE and DCCE, additional arguments (`csa` and `lr`) specify treatment of cross-sectional averages and dynamics. + +### Example 1: Mean Group (MG) Estimation + +```{r mg-fit} +# MG: Separate regression per country, then average coefficients +fit_mg <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df, + id = "id", + time = "year", + model = "mg" +) + +print(fit_mg) +summary(fit_mg) +``` + +**Interpretation**: The MG estimate suggests that on average across countries, increases in human capital, capital stock, and changes in debt are associated with changes in real GDP. The standard errors reflect cross-country heterogeneity in these relationships. + +### Example 2: Common Correlated Effects (CCE) + +```{r cce-fit} +# CCE: Add cross-sectional means to control for common shocks +fit_cce <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df, + id = "id", + time = "year", + model = "cce", + csa = csdm_csa(vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd")) +) + +print(fit_cce) +summary(fit_cce) +``` + +**Interpretation**: After accounting for global shocks (via cross-sectional averages of all variables), the CCE coefficients and standard errors may differ from MG. This indicates whether common factors (e.g., technology, energy prices) are a major source of cross-sectional dependence. + +### Example 3: Dynamic CCE (DCCE) + +```{r dcce-fit} +# DCCE: Include dynamics and cross-sectional means +# Use lagged dependent variable to capture dynamic adjustment +fit_dcce <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df, + id = "id", + time = "year", + model = "dcce", + csa = csdm_csa( + vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), + lags = 3 + ), + lr = csdm_lr(type = "ardl", ylags = 1, xdlags = 0) +) + +print(fit_dcce) +summary(fit_dcce) +``` + +**Interpretation**: The DCCE model includes lagged GDP to capture dynamic adjustment. The lagged coefficient typically lies between 0.8–0.95, indicating strong income persistence. The coefficients on other variables represent short-run elasticities; to compute long-run effects, divide by $(1 - \text{lag coefficient})$. + +### Example 4: Cross-Sectionally Augmented ARDL (CS-ARDL) + +```{r csardl-fit} +# CS-ARDL: Separate short-run and long-run dynamics +# Includes lagged dependent and lagged regressors +fit_csardl <- csdm( + log_rgdpo ~ log_hc + log_ck + log_ngd, + data = df, + id = "id", + time = "year", + model = "cs_ardl", + csa = csdm_csa( + vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), + lags = 3 + ), + lr = csdm_lr(type = "ardl", ylags = 1, xdlags = 1) +) + +print(fit_csardl) +summary(fit_csardl) +``` + +**Interpretation**: The CS-ARDL model returns both short-run coefficients (immediate response to shocks) and long-run coefficients (equilibrium effect after full adjustment). The long-run elasticities are often larger than short-run responses, consistent with gradual accumulation effects in capital and human capital. + +## Cross-Sectional Dependence Testing + +After fitting a model, we can test whether residuals exhibit cross-sectional dependence using the Pesaran CD test and related variants. CSD tests detect whether residuals $u_{it}$ are correlated across units—a key assumption violation that can bias standard errors. + +### Four CD Test Types + +All CD tests have null hypothesis: **residuals are cross-sectionally independent**. + +#### 1. Pesaran CD Test + +The Pesaran CD statistic is: + +$$CD = \sqrt{\frac{2}{N(N-1)}} \sum_{i=1}^{N-1} \sum_{j=i+1}^{N} \hat{\rho}_{ij} \sqrt{T}$$ + +where $\hat{\rho}_{ij}$ is the cross-sectional correlation between residuals of units $i$ and $j$. The test statistic is approximately standard normal under the null. + +**Interpretation**: Large $|CD|$ rejects independence; both positive and negative correlations are flagged. This is the most general CD test and works even when $N$ is fixed and $T \to \infty$. + +#### 2. Pesaran CD Weighted (CDw) + +The CDw statistic applies unit-level random sign weights to the cross-sectional correlations: + +$$CD_w = \sqrt{\frac{2}{N(N-1)}} \sum_{i=1}^{N-1} \sum_{j=i+1}^{N} w_i w_j \hat{\rho}_{ij} \sqrt{T}$$ + +where weights $w_i \in \{-1,1\}$ are independent random sign flips assigned at the unit level and held fixed within a replication. This random-weighting scheme improves the behavior of the test in the presence of heteroskedasticity. + +#### 3. Pesaran CD Weighted Plus (CDw+) + +CDw+ uses the same unit-level random sign weights but applies them to a bias-adjusted version of the CD statistic: + +$$CD_w^+ = \sqrt{\frac{2}{N(N-1)}} \sum_{i=1}^{N-1} \sum_{j=i+1}^{N} w_i w_j \hat{\rho}_{ij}^+ \sqrt{T}$$ + +where $\hat{\rho}_{ij}^+$ denotes the adjusted cross-sectional correlation. CDw+ is designed to improve robustness in large panels with heteroskedasticity. + +#### 4. Pesaran CD*, Fan-Liao-Yao (FLY) + +The CD* statistic is a semiparametric refinement for large $N$ and $T$: + +$$CD^* = \frac{1}{\sqrt{N(N-1)}} \sum_{i=1}^{N-1} \sum_{j=i+1}^{N} (\hat{\rho}_{ij}^2 - \tau_T)$$ + +where $\tau_T$ is a variance adjustment. FLY-type tests are designed for large panel dimensions and provide robustness against certain forms of weak cross-sectional dependence. + +### Running CD Tests with Seed Selection + +The `cd_test()` function accepts the fitted model and computes all test variants. Tests use a **random seed** to initialize pseudo-random computations (for `cdw` and `cdw+`); setting a `seed` ensures reproducibility of numerical results across runs. + +```{r cd-tests} +# Test MG residuals for CSD +cd_mg <- cd_test(fit_mg, type = "CD") +print(cd_mg) + +# Test CCE residuals for CSD +set.seed(1234) +cd_cce <- cd_test(fit_cce, type = "all") +print(cd_cce) + +# Test DCCE residuals for CSD +set.seed(1234) +cd_dcce <- cd_test(fit_dcce, type = "CDw") +print(cd_dcce) + +# Test CS-ARDL residuals for CSD +set.seed(1234) +cd_csardl <- cd_test(fit_csardl, type = "all") +print(cd_csardl) +``` + +**Interpreting Results**: + +- **CD statistic p-value < 0.05**: Reject null of CSD independence; residuals are correlated across units. +- **CDw, CDw+, CD* variants**: Provide robustness checks; if all reject the null, CSD is strongly evidenced. +- **Magnitude**: Large $|CD|$ statistics (e.g., $|CD| > 3$) indicate substantial and economically meaningful dependence. + +In practice, models that do not account for cross-sectional dependence (like MG without augmentation) typically show significant CD test rejections, justifying the use of CSD-robust methods like CCE and DCCE. + +## References + +Chudik, A., & Pesaran, M. H. (2013). Common correlated effects estimation of heterogeneous dynamic panel data models with weakly exogenous regressors. *Journal of Business and Economic Statistics*, 33(2), 232–247. + +Ditzen, J. (2021). Estimating dynamic common-correlated effects in Stata. *The Stata Journal*, 21(1), 39–59. + +Fan, J., Liao, Y., & Yao, J. (2015). Power-enhanced simultaneous test for high-dimensional covariance matrix. *Journal of the American Statistical Association*, 110(510), 325–337. + +Juodis, A., & Reese, S. (2022). The role of the *N/T* ratio in large N, large T panel time-series models. *Econometric Reviews*, 41(2), 221–261. + +Pesaran, M. H. (2007). A simple unit root test in the presence of cross-section dependence. *Journal of Applied Econometrics*, 22(2), 265–312. + +Pesaran, M. H., & Xie, Y. (2021). A bias-adjusted LM test of error cross-section independence. *Econometric Reviews*, 40(1), 7–24. + +--- + +*For further details on the theoretical foundations and implementation of CSD-robust methods, see the documentation for `?csdm`, `?cd_test`, and `?summary.csdm_fit`.* diff --git a/vignettes/xtdcce2-mapping.Rmd b/vignettes/xtdcce2-mapping.Rmd deleted file mode 100644 index 1e94cc8..0000000 --- a/vignettes/xtdcce2-mapping.Rmd +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "Replicating xtdcce2 specifications in csdm" -output: rmarkdown::html_vignette -vignette: > - %\VignetteIndexEntry{Replicating xtdcce2 specifications in csdm} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r setup, include=FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>", - message = FALSE, - warning = FALSE -) -``` - -## Overview - -`csdm` provides Mean Group (MG), Common Correlated Effects (CCE), and Dynamic CCE (DCCE) estimators via `csdm()`. - -This vignette provides a **conceptual mapping** from common `xtdcce2` (Stata) specification concepts to runnable R usage with `csdm`. It does **not** claim numerical equivalence. - -## Quick mapping - -| Stata concept / xtdcce2 option (descriptive) | `csdm` syntax | -|---|---| -| Dynamic dependent-variable lag (e.g., `L.y`) | `lr = csdm_lr(type="ardl", ylags=1)` | -| Cross-sectional averages controls | `csa = csdm_csa(vars=c(...), lags=...)` | -| CSA lags (e.g., 3) | `csa = csdm_csa(..., lags=3)` | -| Scalar distributed lags for all RHS regressors | `lr = csdm_lr(type="ardl", xdlags=K)` | -| Pesaran CD test | `cd_test(fit)` | - -## Worked example with `PWT_60_07` - -```{r} -library(csdm) -data(PWT_60_07, package = "csdm") -df <- PWT_60_07 - -fit <- csdm( - log_rgdpo ~ log_hc + log_ck + log_ngd, - data = df, - id = "id", - time = "year", - model = "dcce", - csa = csdm_csa( - vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), - lags = 3 - ), - lr = csdm_lr(type = "ardl", ylags = 1) -) - -summary(fit) -cd_test(fit) -``` - -```{r} -fit_dx <- csdm( - log_rgdpo ~ log_hc + log_ck + log_ngd, - data = df, - id = "id", - time = "year", - model = "dcce", - csa = csdm_csa( - vars = c("log_rgdpo", "log_hc", "log_ck", "log_ngd"), - lags = 3 - ), - lr = csdm_lr(type = "ardl", ylags = 1, xdlags = 1) -) - -names(coef(fit_dx)) -``` - -## Notes on formula support - -- `xdlags` currently supports only **simple RHS variable names** (no transformations or interactions like `log(x)` or `x1:x2`). -- Generated lag columns follow the naming convention `lag1_`, `lag2_`, ...