Type: Package
Title: Variance Function Panel Regression
Version: 1.1.0
Description: Implements an iterative mean-variance panel regression estimator that allows both the mean and variance of the dependent variable to be functions of covariates. The method alternates between estimating a mean equation (using generalized linear models with Gaussian family) and a variance equation (using generalized linear models with Gamma family on squared within-group residuals) until convergence. Based on the methodology in Mooi-Reci and Liao (2025) <doi:10.1093/esr/jcae052>.
License: MIT + file LICENSE
Encoding: UTF-8
LazyData: true
Depends: R (≥ 3.6.0)
Imports: stats, rlang
Suggests: haven, ggplot2, knitr, gt, modelsummary
RoxygenNote: 7.3.3
NeedsCompilation: no
Packaged: 2025-11-22 14:56:52 UTC; tfliao
Author: Tim F. Liao [aut, cre]
Maintainer: Tim F. Liao <tfliao@illinois.edu>
Repository: CRAN
Date/Publication: 2025-11-26 20:40:02 UTC

Calculate variance decomposition

Description

Calculate variance decomposition

Usage

calculate_variance_decomposition(data, depvar, mean_model, s2, verbose = TRUE)

Coefficient extraction method for xtvfreg objects

Description

Coefficient extraction method for xtvfreg objects

Usage

## S3 method for class 'xtvfreg'
coef(object, equation = "mean", group = NULL, ...)

Arguments

object

An object of class "xtvfreg"

equation

Character; "mean" or "variance"

group

Optional; specific group to extract. If NULL, returns all groups

...

Additional arguments (currently unused)

Value

Named vector or list of coefficient vectors

Examples

set.seed(456)
n_id <- 30
n_time <- 4
panel_data <- data.frame(
id = factor(rep(1:n_id, each = n_time)),  # Convert to factor here
group = rep(c("A", "B"), length.out = n_id * n_time),
x = rnorm(n_id * n_time)
)
panel_data$m_x <- ave(panel_data$x, panel_data$id, FUN = mean)
panel_data$d_x <- panel_data$x - panel_data$m_x
panel_data$y <- 1 + panel_data$m_x + rnorm(n_id * n_time)

result <- xtvfreg(
  formula = y ~ 1,
  data = panel_data,
  group = "group",
  panel_id = "id",
  mean_vars = c("m_x", "d_x"),
  var_vars = "m_x",
  verbose = FALSE
)

# Extract coefficients
coef(result, equation = "mean")
coef(result, equation = "mean", group = "A")

Create comparison table across groups

Description

Create comparison table across groups

Usage

comparison_table(object, equation = "mean", output = "data.frame", ...)

Arguments

object

An object of class "xtvfreg"

equation

Character; "mean" or "variance"

output

Character; "data.frame", "kable", or "gt"

...

Additional arguments passed to formatting functions

Value

A formatted table (type depends on output parameter)

Examples

# Create small simulated dataset
set.seed(456)
n_id <- 30
n_time <- 4
panel_data <- data.frame(
  id = factor(rep(1:n_id, each = n_time)),
  group = factor(rep(c("A", "B"), length.out = n_id * n_time)),
  x = rnorm(n_id * n_time)
)
panel_data$m_x <- ave(panel_data$x, panel_data$id, FUN = mean)
panel_data$d_x <- panel_data$x - panel_data$m_x
panel_data$y <- 1 + panel_data$m_x + rnorm(n_id * n_time)

result <- xtvfreg(
  formula = y ~ 1,
  data = panel_data,
  group = "group",
  panel_id = "id",
  mean_vars = c("m_x", "d_x"),
  var_vars = "m_x",
  verbose = FALSE
)

# Create comparison table
comparison_table(result, equation = "mean")

Estimate model for a single group

Description

Estimate model for a single group

Usage

estimate_group(
  data,
  depvar,
  panel_id,
  mean_vars,
  var_vars,
  weights = NULL,
  converge = 1e-06,
  max_iter = 100,
  verbose = TRUE
)

Export results to LaTeX or CSV

Description

Export results to LaTeX or CSV

Usage

export_table(object, file, format = "csv", equation = "both")

Arguments

object

An object of class "xtvfreg"

file

Character; output file name

format

Character; "latex" or "csv"

equation

Character; "mean", "variance", or "both"

Value

Invisibly returns NULL; called for side effects

Examples


# Create temporary file
set.seed(456)
n_id <- 30
n_time <- 4
panel_data <- data.frame(
  id = rep(1:n_id, each = n_time),
  group = rep(c("A", "B"), length.out = n_id * n_time),
  x = rnorm(n_id * n_time)
)
panel_data$m_x <- ave(panel_data$x, panel_data$id, FUN = mean)
panel_data$d_x <- panel_data$x - panel_data$m_x
panel_data$y <- 1 + panel_data$m_x + rnorm(n_id * n_time)

result <- xtvfreg(
  formula = y ~ 1,
  data = panel_data,
  group = "group",
  panel_id = "id",
  mean_vars = c("m_x", "d_x"),
  var_vars = "m_x",
  verbose = FALSE
)

# Export to CSV
temp_file <- tempfile(fileext = ".csv")
export_table(result, file = temp_file, format = "csv", equation = "mean")

# Clean up
unlink(temp_file)


Get variance decomposition

Description

Get variance decomposition

Usage

get_variance_decomp(object, group = NULL)

Arguments

object

An object of class "xtvfreg"

group

Optional; specific group to extract. If NULL, returns all groups

Value

A data frame with variance decomposition results

Examples

set.seed(456)
n_id <- 30
n_time <- 4
panel_data <- data.frame(
  id = factor(rep(1:n_id, each = n_time)),
  group = factor(rep(c("A", "B"), length.out = n_id * n_time)),
  x = rnorm(n_id * n_time)
)
panel_data$m_x <- ave(panel_data$x, panel_data$id, FUN = mean)
panel_data$d_x <- panel_data$x - panel_data$m_x
panel_data$y <- 1 + panel_data$m_x + rnorm(n_id * n_time)

result <- xtvfreg(
  formula = y ~ 1,
  data = panel_data,
  group = "group",
  panel_id = "id",
  mean_vars = c("m_x", "d_x"),
  var_vars = "m_x",
  verbose = FALSE
)

# Get variance decomposition
get_variance_decomp(result)

National Longitudinal Survey of Young Women (Subset)

Description

A subset of 300 randomly sampled women from the National Longitudinal Survey of Young Women, 1968-1988. This is a subsample of the full nlswork dataset commonly used in Stata examples. The data contains labor market information for young women tracked over multiple years.

Usage

nlswork_subset

Format

A data frame with approximately 2,400-2,700 observations (depending on sampling) and the following variables:

idcode

Individual identifier (numeric)

year

Survey year (numeric)

birth_yr

Year of birth (numeric)

age

Age in current year (numeric)

race

Race: 1=white, 2=black, 3=other (numeric or labeled)

msp

Marital status: 1=never married, 2=married, 3=separated/divorced/widowed (numeric or labeled)

nev_mar

1 if never married (numeric)

grade

Current grade completed (numeric)

collgrad

1 if college graduate (numeric)

not_smsa

1 if not in SMSA (Standard Metropolitan Statistical Area) (numeric)

c_city

1 if in central city (numeric)

south

1 if in south (numeric)

ind_code

Industry code (numeric)

occ_code

Occupation code (numeric)

union

1 if union member (numeric)

wks_ue

Weeks unemployed last year (numeric)

ttl_exp

Total work experience (years) (numeric)

tenure

Job tenure in years (numeric)

hours

Usual hours worked per week (numeric)

wks_work

Weeks worked last year (numeric)

ln_wage

Natural log of hourly wage (numeric)

Details

This dataset is a subset of the nlswork data available from Stata Press. It contains 300 randomly sampled individuals from the original 5,159 women, preserving all time periods for the selected individuals. The data is an unbalanced panel with varying numbers of observations per individual.

The subset was created using:

set.seed(123)
unique_ids <- unique(nlswork$idcode)
sampled_ids <- sample(unique_ids, size = 300, replace = FALSE)
nlswork_subset <- nlswork[nlswork$idcode %in% sampled_ids, ]

Source

Original data from Stata Press: https://www.stata-press.com/data/r19/nlswork.dta

National Longitudinal Survey of Young Women, 1968-1988. U.S. Bureau of Labor Statistics.

References

Center for Human Resource Research. (2002). NLS Handbook 2001. Columbus, OH: The Ohio State University.

Examples

# Load the data
data(nlswork_subset)

# Examine structure
str(nlswork_subset)

# Summary statistics
summary(nlswork_subset$ln_wage)

# Panel structure
table(table(nlswork_subset$idcode))  # Distribution of obs per individual

## Not run: 
# Example analysis with xtvfreg
# Create race groups
nlswork_subset$race_group <- factor(nlswork_subset$race,
                                    levels = 1:2,
                                    labels = c("white", "black"))

# Create within and between components for tenure
nlswork_subset$m_tenure <- ave(nlswork_subset$tenure,
                               nlswork_subset$idcode,
                               FUN = function(x) mean(x, na.rm = TRUE))
nlswork_subset$d_tenure <- nlswork_subset$tenure - nlswork_subset$m_tenure

# Estimate varying effects model
result <- xtvfreg(
  formula = ln_wage ~ 1,
  data = subset(nlswork_subset, !is.na(ln_wage) & race %in% 1:2),
  group = "race_group",
  panel_id = "idcode",
  mean_vars = c("m_tenure", "d_tenure", "age"),
  var_vars = c("m_tenure", "age"),
  verbose = TRUE
)

# View results
summary(result)

## End(Not run)


Plot coefficient comparison across groups

Description

Plot coefficient comparison across groups

Usage

plot_coefficients(object, equation = "mean", variable = NULL)

Arguments

object

An object of class "xtvfreg"

equation

Character; "mean" or "variance"

variable

Optional; specific variable to plot. If NULL, plots all

Value

A ggplot2 object

Examples


# Requires ggplot2 package
if (requireNamespace("ggplot2", quietly = TRUE)) {
  set.seed(456)
  n_id <- 30
  n_time <- 4
  panel_data <- data.frame(
    id = rep(1:n_id, each = n_time),
    group = rep(c("A", "B"), length.out = n_id * n_time),
    x = rnorm(n_id * n_time)
  )
  panel_data$m_x <- ave(panel_data$x, panel_data$id, FUN = mean)
  panel_data$d_x <- panel_data$x - panel_data$m_x
  panel_data$y <- 1 + panel_data$m_x + rnorm(n_id * n_time)
  
  result <- xtvfreg(
    formula = y ~ 1,
    data = panel_data,
    group = "group",
    panel_id = "id",
    mean_vars = c("m_x", "d_x"),
    var_vars = "m_x",
    verbose = FALSE
  )
  
  # Plot coefficients
  plot_coefficients(result, equation = "mean")
}


Print method for xtvfreg objects

Description

Print method for xtvfreg objects

Usage

## S3 method for class 'xtvfreg'
print(x, ...)

Arguments

x

An object of class "xtvfreg"

...

Additional arguments (currently unused)

Value

Invisibly returns the input object

Examples

set.seed(456)
n_id <- 30
n_time <- 4
panel_data <- data.frame(
  id = rep(1:n_id, each = n_time),
  group = rep(c("A", "B"), length.out = n_id * n_time),
  x = rnorm(n_id * n_time)
)
panel_data$m_x <- ave(panel_data$x, panel_data$id, FUN = mean)
panel_data$d_x <- panel_data$x - panel_data$m_x
panel_data$y <- 1 + panel_data$m_x + rnorm(n_id * n_time)

result <- xtvfreg(
  formula = y ~ 1,
  data = panel_data,
  group = "group",
  panel_id = "id",
  mean_vars = c("m_x", "d_x"),
  var_vars = "m_x",
  verbose = FALSE
)

print(result)

Summary method for xtvfreg objects

Description

Summary method for xtvfreg objects

Usage

## S3 method for class 'xtvfreg'
summary(object, ...)

Arguments

object

An object of class "xtvfreg"

...

Additional arguments (currently unused)

Value

Invisibly returns the input object

Examples

set.seed(456)
n_id <- 30
n_time <- 4
panel_data <- data.frame(
  id = rep(1:n_id, each = n_time),
  group = rep(c("A", "B"), length.out = n_id * n_time),
  x = rnorm(n_id * n_time)
)
panel_data$m_x <- ave(panel_data$x, panel_data$id, FUN = mean)
panel_data$d_x <- panel_data$x - panel_data$m_x
panel_data$y <- 1 + panel_data$m_x + rnorm(n_id * n_time)

result <- xtvfreg(
  formula = y ~ 1,
  data = panel_data,
  group = "group",
  panel_id = "id",
  mean_vars = c("m_x", "d_x"),
  var_vars = "m_x",
  verbose = FALSE
)

summary(result)

Variance-covariance matrix extraction method

Description

Variance-covariance matrix extraction method

Usage

## S3 method for class 'xtvfreg'
vcov(object, equation = "mean", group = NULL, ...)

Arguments

object

An object of class "xtvfreg"

equation

Character; "mean" or "variance"

group

Optional; specific group to extract. If NULL, returns all groups

...

Additional arguments (currently unused)

Value

Matrix or list of matrices

Examples

set.seed(456)  
n_id <- 30     
n_time <- 4    
panel_data <- data.frame(
  id = rep(1:n_id, each = n_time),
  group = rep(c("A", "B"), length.out = n_id * n_time),
  x = rnorm(n_id * n_time)
)
panel_data$m_x <- ave(panel_data$x, panel_data$id, FUN = mean)
panel_data$d_x <- panel_data$x - panel_data$m_x
panel_data$y <- 1 + panel_data$m_x + rnorm(n_id * n_time)

result <- xtvfreg(
  formula = y ~ 1,
  data = panel_data,
  group = "group",
  panel_id = "id",
  mean_vars = c("m_x", "d_x"),
  var_vars = "m_x",
  verbose = FALSE
)

# Extract variance-covariance matrix
vcov(result, equation = "mean", group = "A")

Variance Function Panel Regression

Description

Implements an iterative mean-variance panel regression estimator that allows both the mean and variance of the dependent variable to be functions of covariates. Based on Mooi-Reci and Liao (2025).

Usage

xtvfreg(
  formula,
  data,
  group,
  panel_id,
  mean_vars,
  var_vars,
  weights = NULL,
  subset = NULL,
  converge = 1e-06,
  max_iter = 100,
  verbose = TRUE
)

Arguments

formula

A formula specifying the dependent variable

data

A data frame containing the variables

group

A character string naming the grouping variable

panel_id

A character string naming the panel identifier

mean_vars

A character vector of variable names for the mean equation

var_vars

A character vector of variable names for the variance equation

weights

Optional character string naming the weight variable

subset

Optional logical vector for subsetting

converge

Convergence tolerance (default: 1e-6)

max_iter

Maximum iterations (default: 100)

verbose

Logical; print iteration history? (default: TRUE)

Value

An object of class "xtvfreg" containing:

results

List of results for each group

groups

Vector of group values

call

The matched call

convergence

Convergence information for each group

variance_decomp

Variance decomposition for each group

depvar

Name of dependent variable

panel_id

Name of panel identifier

group_var

Name of grouping variable

mean_vars

Variables in mean equation

var_vars

Variables in variance equation

References

Mooi-Reci, I., and Liao, T. F. (2025). Unemployment: a hidden source of wage inequality? European Sociological Review, 41(3), 382-401. doi:10.1093/esr/jcae052

Examples

# Example using nlswork subset data
data(nlswork_subset)

# Prepare the data
# Keep only observations with complete wage data and white/black race
analysis_data <- subset(nlswork_subset, 
                        !is.na(ln_wage) & 
                        !is.na(tenure) & 
                        race %in% 1:2)

# Create race grouping variable
analysis_data$race_group <- factor(analysis_data$race,
                                   levels = 1:2,
                                   labels = c("white", "black"))

# Create within and between components for tenure
analysis_data$m_tenure <- ave(analysis_data$tenure,
                              analysis_data$idcode,
                              FUN = function(x) mean(x, na.rm = TRUE))
analysis_data$d_tenure <- analysis_data$tenure - analysis_data$m_tenure

# Estimate varying effects model
result <- xtvfreg(
  formula = ln_wage ~ 1,
  data = analysis_data,
  group = "race_group",
  panel_id = "idcode",
  mean_vars = c("m_tenure", "d_tenure", "age"),
  var_vars = c("m_tenure"),
  verbose = FALSE
)

# View a summary of results
summary(result)

# Extract coefficients for white group if needed
coef(result, equation = "mean", group = "white")