pensynth: Penalized synthetic control estimator

View source: R/pensynth.R

pensynthR Documentation

Penalized synthetic control estimator

Description

For a given set of variable weights (v) this function estimates the unit weights for a synthetic control with penalization according to Abadie & L'Hour (2021). This function deals with only a single treated unit.

Usage

pensynth(
  X1,
  X0,
  v = 1,
  lambda = 0,
  opt_pars = clarabel::clarabel_control(),
  standardize = TRUE,
  verbose = interactive()
)

Arguments

X1

⁠N_covars by N_treated matrix⁠ of treated unit covariates

X0

⁠N_covars by N_donors matrix⁠ of donor unit covariates

v

⁠N_covars vector⁠ of variable weights (default 1)

lambda

numeric penalization parameter

opt_pars

clarabel settings using clarabel::clarabel_control()

standardize

boolean whether to standardize the input matrices (default TRUE)

verbose

boolean whether to print progress messages. Default on if in an interactive session.

Details

This routine uses the same notation of the original Synth::synth() implementation but uses a different, faster quadratic program solver (namely, clarabel::clarabel()). Additionally, it implements the penalization procedure described in Abadie & L'Hour (2021), such that the loss function is as in equation 5 of that paper.

Variable weights are not optimized by this function, meaning they need to be pre-specified. This is by design.

The original synthetic control method can be recovered by setting lambda = 0. For determining lambda based on hold-out data, see cv_pensynth().

Value

A list with two values: w, the estimated weights; and solution, the result of the optimization.

References

Abadie, A., & L’Hour, J. (2021). A penalized synthetic control estimator for disaggregated data. Journal of the American Statistical Association, 116(536), 1817-1834.

See Also

cv_pensynth(), placebo_test(), simulate_data_synth(), Synth::synth()

Examples

# generate some data
X0 <- matrix(
  c(1, 1.3,
    0.5, 1.8,
    1.1, 2.4,
    1.8, 1.8,
    1.3, 1.8), 2)
X1 <- matrix(c(0.8, 1.65), 2)

# run classic synthetic control (no penalization)
res <- pensynth(X1, X0)

# plot donor units in covariate space
plot(t(X0), asp = 1, xlab = "X1", ylab = "X2",
     main = "Covariate space plot")
# add the treated unit
points(t(X1), pch = 2)
# add the synthetic control
points(t(X0%*%res$w), pch = 3)

# run synthetic control with penalty
res <- pensynth(X1, X0, lambda = 0.5)
# the resulting synthetic control is
# biased towards its closest neighbours
points(t(X0 %*% res$w), pch = 4)

pensynth documentation built on May 7, 2026, 9:06 a.m.

Related to pensynth in pensynth...