Fixed-level parametric quantile regression for bounded responses in the open interval (0,1), using the five-parameter Generalized Kumaraswamy distribution and its six nested sub-families. For a quanti
翻譯準備中
資料R · C++GitHub @evandeilton上線中營運者未確認
試用過了嗎? 點一下就好,不需要登入。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Fixed-level parametric quantile regression for the Generalized Kumaraswamy family, for bounded responses in (0,1). Maximum likelihood via TMB.
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
Parametric quantile regression for the Generalized Kumaraswamy family
For a response in the open interval $(0,1)$ and a quantile level fixed in advance,
gkwqreg reparametrizes the Generalized Kumaraswamy distribution so that one of its
parameters is the conditional quantile at that level, and models that parameter
directly. Every coefficient then has a quantile interpretation and a standard error that
refers to one.
This is the sibling of gkwreg, which fits the
same seven families with mean semantics.
Why this is not predict(type = "quantile")檢視完整 README ↗Parametric quantile regression for the Generalized Kumaraswamy family
For a response in the open interval $(0,1)$ and a quantile level fixed in advance,
gkwqreg reparametrizes the Generalized Kumaraswamy distribution so that one of its
parameters is the conditional quantile at that level, and models that parameter
directly. Every coefficient then has a quantile interpretation and a standard error that
refers to one.
This is the sibling of gkwreg, which fits the
same seven families with mean semantics.
predict(type = "quantile")gkwreg and betareg can already report quantiles: fit a mean-oriented likelihood, then
apply the quantile function to the estimated parameters. That answers "given the fitted
distribution, what is its 90th percentile?"
It does not answer "how do covariates shift the 90th percentile?", because no parameter
in that model is the 90th percentile. gkwqreg closes exactly that gap.
# install.packages("remotes")
remotes::install_github("evandeilton/gkwqreg")
The TMB template is compiled at install time, so no C++ toolchain is needed at run time.
Seven steps. Copy each block in turn; everything is self-contained.
The response must lie strictly inside (0,1) — a share, a rate, an index. Here it is
"share of households with piped-water access", and we build it so the true 0.9-quantile
is plogis(0.20 + 1.60*income - 0.50*urban).
library(gkwqreg)
set.seed(2026)
n <- 600
income <- runif(n, 0, 1)
region <- factor(rbinom(n, 1, 0.5), labels = c("rural", "urban"))
mu90 <- plogis(0.20 + 1.60 * income - 0.50 * (region == "urban"))
access <- gkwdist::rkw(n, alpha = 2.5, beta = log1p(-0.90) / log1p(-mu90^2.5))
dat <- data.frame(access, income, region)
One line. tau = 0.9 says which quantile you are asking about; it is chosen by you and
never estimated.
fit <- gkwqreg(access ~ income + region, data = dat, tau = 0.9, family = "kw")
summary(fit)
Generalized Kumaraswamy quantile regression
family: kw tau: 0.9 anchor: beta
Conditional 0.9-quantile (link logit) -- coefficients are effects on the LOG QUANTILE ODDS log(mu/(1-mu)):
Estimate Std. Error z value Pr(>|z|)
mu:(Intercept) 0.14521 0.07983 1.819 0.0689 .
mu:income 1.73121 0.14868 11.644 < 2e-16 ***
mu:regionurban -0.49843 0.07893 -6.315 2.71e-10 ***
alpha (link log):
Estimate Std. Error z value Pr(>|z|)
alpha:(Intercept) 0.90635 0.03894 23.27 <2e-16 ***
Anchored parameter: beta (computed from the quantile, not estimated)
Log-likelihood: 230.6 on 4 Df AIC: -453.2 BIC: -435.7
Pinball loss: 0.02995 Pseudo-R1: 0.1603
Empirical coverage: 0.895 (target 0.9)
Covariance: expected Information condition number: 30.99
The true values were 0.20, 1.60, -0.50; every estimate is within about one standard
error. Line by line:
| Line | What it tells you |
|---|---|
mu: block | The quantile model. These are effects on the log quantile odds, not on a mean and not on the odds of an event |
alpha: block | A nuisance parameter. It controls the spread of the conditional distribution, not the quantile you are modelling |
Anchored parameter | Which parameter was eliminated to make room for the quantile. A modeling choice — see below |
Empirical coverage | Share of observations below the fitted quantile. Should sit at tau. 0.895 vs 0.900 — the model is doing its job |
Information condition number | Conditioning. Small (here 31) is healthy; above 1e8 means the standard errors are unreliable |
mu:income = 1.731 is on the log-quantile-odds scale, which nobody can interpret directly.
Convert it to the response scale:
marginal_effects(fit)
Marginal effects on the conditional 0.9-quantile (averaged over the sample)
dQ(tau|x)/dx_j, logit link
variable effect std.error lower upper
income 0.3640 0.02764 0.3099 0.41819
regionurban -0.1048 0.01609 -0.1363 -0.07327
Now you can write it down:
Moving income from 0 to 1 raises the 90th percentile of access by about 0.36 (95% CI 0.31 to 0.42). Urban regions sit about 0.10 lower at the 90th percentile than rural ones (95% CI 0.14 to 0.07 lower).
These describe conditional quantiles under the fitted model. They are not causal effects.
Three numbers, all in the summary above, plus one plot:
mean(dat$access <= fitted(fit)) # 0.8950 -- should be ~ tau
fit$cond_number # 31.0 -- small is good
mean(residuals(fit, type = "tau-sign"))# -0.0050 -- should be ~ 0
plot(fit, which = c(3, 4, 5)) # Q-Q, observed-vs-fitted, calibration
Panel 5 is the one to look at. It bins the residuals 1{y <= Q} - tau by fitted value;
under a correct model every bin sits at zero. A bin whose interval excludes zero says the
fit is miscalibrated there, which no mean-regression diagnostic can tell you.
nd <- data.frame(income = c(0.25, 0.75),
region = factor("rural", levels = c("rural", "urban")))
predict(fit, newdata = nd) # 0.6406 0.8090
1 - predict(fit, newdata = nd, type = "probability", at = 0.5) # 0.3227 0.6008
predict(fit, newdata = nd, type = "quantile", tau = 0.5) # 0.4165 0.5584
Read in order: the fitted 90th percentile at each profile; the probability that access exceeds 0.5 there; and the median for the same profiles, read off the same fitted distribution without refitting.
That third line is the thing check-function quantile regression cannot do. A gkwqreg fit
carries a whole conditional distribution per observation, so any quantile, any exceedance
probability and any moment is available from one fit — and the quantiles it reports can
never cross, because they come from one proper distribution function.
Every standard error and interval above is the Wald approximation: estimate plus or
minus z * se. confint() can instead invert the profile likelihood or bootstrap, and
gkwq_boot() — the bootstrap engine underneath it — is also useful on its own, to check
whether those Wald numbers can be trusted.
round(confint(fit), 4)
#> 2.5 % 97.5 %
#> mu:(Intercept) -0.0112 0.3017
#> mu:income 1.4398 2.0226
#> mu:regionurban -0.6531 -0.3437
#> alpha:(Intercept) 0.8300 0.9827
gkwq_boot(fit, R = 100, seed = 1)
#>
#> Bootstrap for a kw quantile regression (tau = 0.9, anchor beta)
#> pairs bootstrap, 100 of 100 replicates converged
#>
#> Estimate Boot SE 2.5% 97.5%
#> mu:(Intercept) 0.1452 0.0786 -0.0050 0.3039
#> mu:income 1.7312 0.1550 1.4189 2.0044
#> mu:regionurban -0.4984 0.0896 -0.6787 -0.3322
#> alpha:(Intercept) 0.9063 0.0370 0.8285 0.9780
gkwq_boot() resamples whole rows by default (type = "pairs"), so — unlike the Wald
and parametric-bootstrap alternatives — its spread does not assume the kw family is
correctly specified.
vignette("gkwqreg") # the fuller tour
vignette("gkwqreg-anchor") # what `anchor` means and why it is a modeling choice
vignette("gkwqreg-design") # the vocabulary and the design decisions
They form a nesting lattice, not a single chain, so a likelihood-ratio test applies
along a chain of containments. kw sits inside all of ekw, kkw, bkw and gkw;
ekw inside kkw and gkw; beta inside mc, bkw and gkw. But ekw and bkw
contain neither each other, and anova() returns NA with a warning for any such pair
rather than reporting a test that does not apply.
| family | free parameters | constraints | default anchor |
|---|---|---|---|
kw | α, β | γ=1, δ=0, λ=1 | β |
ekw | α, β, λ | γ=1, δ=0 | β |
kkw | α, β, δ, λ | γ=1 | β |
bkw | α, β, γ, δ | λ=1 | β |
gkw | α, β, γ, δ, λ | — | β |
mc | γ, δ, λ | α=β=1 | λ |
beta | γ, δ | α=β=λ=1 | γ |
compare_families(fit, families = c("kw", "ekw", "beta"))
#> family anchor df logLik AIC BIC pinball converged
#> 1 kw beta 4 230.6209 -453.2418 -435.6540 0.02995121 TRUE
#> 2 ekw beta 5 230.8573 -451.7146 -429.7299 0.02995948 TRUE
#> 3 beta gamma 4 210.5077 -413.0155 -395.4278 0.03196525 TRUE
Compare on pinball when choosing out of sample: the pinball loss is what a quantile estimate
actually targets.
anchor names the parameter eliminated in favour of the conditional quantile. It looks
like a reparametrization, and when the nuisance parameters are regressed on at least the
covariates used for the quantile, it is one — the likelihood is identical either way.
It stops being one as soon as the quantile varies with covariates while a nuisance
parameter is held constant. Anchoring on β then asserts "α constant, βᵢ = f(μᵢ, α)";
anchoring on α asserts the reverse. The two anchors then fit genuinely different
models: on simulated data they can differ substantially in both log-likelihood and in
the coefficient of interest, as vignette("gkwqreg-anchor") demonstrates live, under
"The finding that matters".
Two anchors give non-nested models of equal dimension. Compare them with vuong_test(),
never with anova() — which refuses:
fa <- gkwqreg(y ~ x, data = d, tau = 0.9, family = "kw", anchor = "alpha")
anova(fit, fa)
#> Error: models with different anchors cannot be compared by a likelihood-ratio
#> test: they are non-nested models of equal dimension. Compare them by AIC, BIC
#> or a Vuong test instead. Anchors seen: beta, alpha.
vuong_test(fit, fa)
The practical advice: regress the nuisance parameters on the same covariates as the
quantile (y ~ x | x) and the fit becomes largely anchor-insensitive.
fits <- gkwqreg(y ~ x, data = d, tau = seq(0.1, 0.9, by = 0.1), family = "kw")
plot(quantile_process(fits)) # coefficient paths, in the idiom of plot.rqs
check_crossing(fits) # crossing across independent fits
rearrange(fits) # Chernozhukov et al. (2010) monotonization
A single fit cannot cross, and the printed output says why:
rows with a crossing: 0 of 300 (0.00%)
Zero crossings is guaranteed here, not luck: these are quantiles of
a single proper distribution function.
That guarantee is what a parametric fit buys over independently fitted levels — and the price is paid under misspecification, where check-function quantile regression stays consistent and this does not.
The kw slice of this package is the Kumaraswamy quantile reparametrization of
Mitnik and Baek (2013), which the unitquantreg
package implements as its kum family. The general formula here contains that result
exactly as its two-parameter slice, and the test suite checks the identity.
What is new is the extension to the four- and five-parameter members, and the fact that
they are nested: unitquantreg's thirteen families are mutually non-nested and need
Vuong tests, while here kw ⊂ ekw ⊂ gkw are genuine nestings compared by ordinary LR
tests.
quantreg::rq stays consistent for the
conditional quantile and this does not. That is the central trade-off of parametric
quantile regression.unitquantreg is simpler and
established — it is tau-indexed exactly as this package is. cdfquantreg covers
location and median models, which are not tau-indexed at all.qgam is the right tool.gkw is weakly identified in any parametrization; the package warns
and summary() reports the information matrix's condition number.vignette("gkwqreg") # getting started
vignette("gkwqreg-anchor") # the reparametrization and identifiability
vignette("gkwqreg-comparison") # versus quantreg, unitquantreg, betareg
vignette("gkwqreg-case-study") # upper-quantile body-fat modelling
vignette("gkwqreg-design") # the vocabulary and the four design decisions
The last one is worth knowing about. It defines the terms this package commits to
(anchor, saturated, part, quantile level) and records the four decisions a reader
is most likely to question — including why the package ships its own incomplete-beta
derivatives instead of using TMB's qbeta, whose shape derivatives are silently zero
at whole-number shapes. It demonstrates that failure, and this package's fix, live.
Every DOI below was resolved against the registration agency's own record.
The distribution
The quantile reparametrization
Quantile regression
Related software and the comparison class
unitquantreg: Parametric Quantile
Regression Models for Bounded Data. R package.
doi:10.32614/CRAN.package.unitquantreggkwreg: An R package for generalized
Kumaraswamy regression models for bounded data. JOSS 11(117), 8991.
doi:10.21105/joss.08991Inference and numerics
MIT