Asymmetric Poisson Pseudo-Maximum Likelihood (APPML)
library(capybara)
#> Registered S3 method overwritten by 'capybara':
#> method from
#> update.formula stats
Overview
Standard Poisson Pseudo-Maximum Likelihood (PPML) estimates the
conditional mean of the outcome variable.
fepoisson_asymmetric() extends this by fitting conditional
expectiles β a generalization that lets you examine different parts of
the conditional distribution with the same efficiency gains of
high-dimensional fixed effects.
The implementation follows Bergstrand et al.Β (2025): instead of
minimizing a symmetric loss, the estimator minimizes an
asymmetric weighted loss controlled by a single parameter
expectile (\(\tau \in (0,
1)\)):
- \(\tau = 0.5\) β standard PPML (symmetric, estimates the conditional mean).
- \(\tau < 0.5\) β places more weight on observations with negative residuals, pulling estimates toward the lower part of the distribution.
- \(\tau > 0.5\) β places more weight on observations with positive residuals, shifting estimates toward the upper part of the distribution.
The expectile is set through fit_control()
and defaults to 0.5, so if you donβt specify it,
fepoisson_asymmetric() will behave like standard PPML.
Estimating lower and upper expectiles
Shifting expectile away from 0.5 lets you trace how the
entire conditional distribution of mpg varies with
wt, after absorbing the cyl fixed effects.
# 10th expectile β sensitive to small values of mpg
mod_low <- fepoisson_asymmetric(
mpg ~ wt | cyl,
data = mtcars,
control = fit_control(expectile = 0.1)
)
# Standard PPML: expectile = 0.5 recovers the conditional mean
mod_ppml <- fepoisson_asymmetric(
mpg ~ wt | cyl,
data = mtcars,
control = fit_control(expectile = 0.5)
)
summary(mod_ppml)
#> Formula: mpg ~ wt | cyl
#> <environment: 0x5641bac33f88>
#>
#> Family: Poisson
#>
#> Estimates:
#>
#> | | Estimate | Std. Error | z value | Pr(>|z|) |
#> |----|----------|------------|---------|----------|
#> | wt | -0.1799 | 0.0716 | -2.5126 | 0.0120 * |
#>
#> Significance codes: ** p < 0.01; * p < 0.05; + p < 0.10
#>
#> Fixed effects:
#> cyl: 3
#>
#> Number of observations: Full 32; Missing 0; Perfect classification 0
#>
#> Number of Fisher Scoring iterations: 4
# 90th expectile β sensitive to large values of mpg
mod_high <- fepoisson_asymmetric(
mpg ~ wt | cyl,
data = mtcars,
control = fit_control(expectile = 0.9)
)
Comparing coefficients across expectiles
A natural use-case is comparing how the effect of a regressor changes
across the distribution. The table below collects the coefficient on
wt at the three expectile levels:
summary_table(
mod_low, mod_ppml, mod_high,
model_names = c("10th expectile", "PPML (50th expectile)", "90th expectile")
)
#> | Variable | 10th expectile | PPML (50th expectile) | 90th expectile |
#> |------------------|------------------|-------------------|------------------|
#> | wt | -0.197 | -0.180* | -0.160 |
#> | | (0.141) | (0.072) | (0.142) |
#> | | | | |
#> | Fixed effects | | | |
#> | cyl | Yes | Yes | Yes |
#> | | | | |
#> | N | 32 | 32 | 32 |
#>
#> Standard errors in parenthesis
#> Significance levels: ** p < 0.01; * p < 0.05; + p < 0.10
A negative coefficient that grows in magnitude from low
to high would indicate that heavier cars are
disproportionately associated with low mpg at the top of the
distribution β a pattern that standard PPML would average out.
Convergence diagnostics
The outer APPML loop updates observation weights until the coefficient vector stops changing. You can inspect convergence through the returned list elements:
cat("Outer loop converged:", mod_ppml$conv_outer, "\n")
#> Outer loop converged: TRUE
cat("Outer iterations: ", mod_ppml$iter_outer, "\n")
#> Outer iterations: 1
cat("Expectile used: ", mod_ppml$expectile, "\n")
#> Expectile used: 0.5
References
Bergstrand, Jeffrey H., Matthew W. Clance, and JMC Santos Silva. βThe tails of gravity: Using expectiles to quantify the trade-margins effects of economic integration agreements.β Journal of International Economics (2025): 104145.