This vignette follows Qu, Oka and Messer, “QR.break: An R Package for Structural Breaks in Quantile Regression”, which should be consulted for further detail. It outlines the methods implemented in the package and then works through the two datasets: a time series on U.S. real GDP growth and a repeated cross-section on youth drinking and driving. All numerical output shown here was produced with version 1.0.3 of the package.
The issue of structural breaks has been extensively studied. Much of the literature has focused on the conditional mean, but in many cases structural change in the conditional quantile function is more informative. For example, in studying income inequality, it is important to assess whether the wage gap between racial groups, conditional on covariates, has changed over time. Inequality may increase conditional dispersion without affecting the mean. Similarly, when evaluating a policy aimed at improving outcomes for low-performing students, attention should focus on lower quantiles. In both cases it is desirable to estimate break dates from the data: in the former, the cause of change may be unclear a priori; in the latter, the policy effect may exhibit an unknown time lag.
To address these issues, Qu (2008) and Su and Xiao (2008) developed tests for detecting structural change in conditional quantile functions with unknown break dates, but did not consider estimation and inference for the number of breaks or their locations. Oka and Qu (2011) studied the estimation of multiple structural breaks at unknown dates in conditional quantile functions for two models: a time series model, useful for analyzing macroeconomic data, and a repeated cross-section model, relevant for evaluating social programs and policy effects. Their framework allows for structural change in single or multiple quantiles. Analyzing multiple quantiles requires stronger assumptions but can improve estimation efficiency.
Key aspects of Oka and Qu’s (2011) procedure are as follows. Assuming a known number of breaks, the methods construct estimates of break dates and coefficients as global minimizers of the check function over admissible break points. For multiple quantiles, the check function is integrated over the set of quantiles chosen by the user. The assumptions permit dynamic models and impose restrictions only in neighborhoods around the quantiles of interest, leaving other quantiles unspecified. This flexibility allows researchers to examine slices of the conditional distribution without imposing global distributional assumptions. The distributions of the break estimators were derived following Picard (1985) and Yao (1987); they involve consistently estimable parameters, which enables confidence interval construction without simulation. Oka and Qu (2011) also propose a test for the number of breaks based on the subgradient methods of Qu (2008). These tests do not require variance estimation and have monotonic power even with multiple breaks.
The package’s main function, rq.break(), returns all
testing and estimation results based on user-specified quantiles of
interest, the maximum number of allowed breaks, and the minimum length
of a single regime:
We illustrate the function through the two empirical examples of Oka and Qu (2011). The first revisits the “Great Moderation” in U.S. GDP growth using quarterly data; the results suggest the decline in volatility mainly affected the upper tail, with the median and lower quantiles remaining stable, implying that expansions became less rapid while recessions remained as severe. The second analyzes blood alcohol levels of young drivers in California from 1983 to 2007; two breaks are detected, consistent with the 1984 National Minimum Drinking Age Act and a 1991 beer tax increase, with effects more pronounced at lower quantiles, indicating a greater impact on lighter drinkers than on heavier ones.
This section explains (1) the model and the econometric issues of interest; (2) estimating break locations and regression coefficients when the number of breaks is known, based on a single quantile; (3) the same based on multiple quantiles; (4) a procedure for determining the number of breaks; and (5) inference on quantile regression coefficients after estimating the breaks. Section 2.6 covers the normalization option introduced in package version 1.0.3.
Let \(y_{it}\) be the outcome for unit \(i\) in period \(t\), \(x_{it}\) a \(p\)-dimensional vector of covariates, and \(Q_{y_{it}}(\tau \mid x_{it})\) the conditional \(\tau\)-quantile of \(y_{it}\) given \(x_{it}\). Let \(N\) be the number of cross-sectional units, assumed constant over time, and \(T\) the number of periods. For a single time series \(N = 1\) and the index \(i\) is dropped throughout. Assume the conditional quantile function is linear and potentially affected by \(m\) structural breaks:
\[ Q_{y_{it}}(\tau \mid x_{it})= \begin{cases} x_{it}^{\prime }\beta _{1}^{0}(\tau ), & t=1,\dots ,T_{1}^{0}, \\ x_{it}^{\prime }\beta _{2}^{0}(\tau ), & t=T_{1}^{0}+1,\dots ,T_{2}^{0}, \\ \qquad \vdots & \qquad \vdots \\ x_{it}^{\prime }\beta _{m+1}^{0}(\tau ), & t=T_{m}^{0}+1,\dots ,T, \end{cases} \]
where \(\tau \in (0,1)\), the \(\beta_j^0(\tau)\) \((j = 1,\dots,m+1)\) are unknown parameters, and the \(T_j^0\) \((j = 1,\dots,m)\) are unknown break dates. The regressors may include discrete as well as continuous variables. A column of ones is automatically added to the regression when applying the methods.
The following examples, taken from Oka and Qu (2011), illustrate the model.
Example 1 (time series). Oka and Qu (2011) studied a quantile autoregression for U.S. quarterly real GDP growth rates over 1947:Q2 to 2009:Q2, in which the regressors are lagged values of the growth rate and the intercept and autoregressive coefficients are allowed to shift across regimes. They detect a structural break in 1984 that affects only the upper quantiles of the distribution. The coefficient estimates suggest that growth was slower during expansions, while recessions remained just as severe when they occurred. This dataset is included in the package and is used in Section 4.
Example 2 (repeated cross-sections). Motor vehicle crashes are the leading cause of death among youth aged 15–20, a high proportion of which involve drunk driving. Blood alcohol concentration (BAC) is a key measure of alcohol impairment, and changes in BAC among young drivers provide useful information on how their drinking behavior has changed over time. Oka and Qu (2011) studied structural change in BAC among young drivers involved in traffic accidents, using age, gender, and a dummy for the fourth quarter as regressors. They detect breaks in 1985 and 1992. The changes are negative and meaningful in magnitude; however, the change is smaller for higher quantiles, suggesting the policies are more effective for “light drinkers” than for “heavy drinkers” in the sample. This is encouraging but falls short of expectations, as heavy drinkers are more likely to cause accidents, suggesting that additional policies are needed to deter heavy drinking. This dataset is included in the package and is used in Section 5.
The methods address the following issues.
Estimation based on a single quantile when the number of breaks is known. The method estimates both the break locations and the regression coefficients. If the user specifies more than one quantile level, the analysis is performed independently for each quantile, allowing break locations to differ across quantiles. The program returns the estimated break locations, their confidence intervals, and the corresponding estimates and intervals for the regression coefficients.
Estimation based on multiple quantiles when the number of breaks is known. Here the break locations are assumed common across quantiles and are estimated using information from all specified quantiles. The program returns the same set of objects.
Selection of the number of breaks. The user specifies the maximum number of breaks, and the program determines the number of breaks using a dynamic programming algorithm.
A single main function performs all of these tasks.
Suppose the \(\tau\)th quantile is affected by \(m\) structural changes. For a set of candidate break dates \(T^b = (T_1,\dots,T_m)\), the break dates and the coefficients are estimated jointly by minimizing the check function over admissible partitions:
\[ (\hat{\beta}(\tau ),\hat{T}^{b})=\arg \min_{\beta (\tau ),\,T^{b}\in \Lambda _{\varepsilon }}\ \sum_{j=0}^{m}\ \sum_{t=T_{j}+1}^{T_{j+1}}\ \sum_{i=1}^{N}\rho _{\tau }(y_{it}-x_{it}^{\prime }\beta _{j+1}(\tau )), \]
where \(\rho_\tau(u) = u(\tau - 1(u <
0))\) is the check function (Koenker, 2005), \(\beta(\tau) =
(\beta_1(\tau)',\dots,\beta_{m+1}(\tau)')'\), \(T_0 = 0\), \(T_{m+1} = T\), and the summation over \(i\) is absent for a single time series. The
set \(\Lambda_\varepsilon\) collects
the admissible partitions, ensuring each estimated regime is a positive
fraction of the sample: every regime must be at least \(\varepsilon T\) periods long, and no break
may fall within \(\varepsilon T\) of
either end of the sample. The user specifies \(\varepsilon\) through the argument
trim.e.
The computation is carried out using a dynamic programming algorithm as in Bai and Perron (2003), so that the computation is of order \(O(T^2)\) irrespective of the number of breaks allowed in the model.
Suppose the quantiles in \(\mathcal{T}_\omega = [\omega_1, \omega_2]\) with \(0 < \omega_1 < \omega_2 < 1\) are affected by structural changes. A natural approach is to consider a partition of this interval, examine a set of quantiles \(\tau_h\), \(h = 1,\dots,q\), and minimize the check function summed over them as well:
\[ (\hat{\beta}(\mathcal{T}_{\omega }),\hat{T}^{b})=\arg \min_{\beta (\mathcal{T}% _{\omega }),\,T^{b}\in \Lambda _{\varepsilon }}\ \sum_{h=1}^{q}\ \sum_{j=0}^{m}\ \sum_{t=T_{j}+1}^{T_{j+1}}\ \sum_{i=1}^{N}\rho _{\tau _{h}}(y_{it}-x_{it}^{\prime }\beta _{j+1}(\tau _{h})), \]
with \(\Lambda_\varepsilon\) as before. The estimated break dates are now common across quantiles, while the coefficients remain quantile-specific. Regarding the partition, a coarse partition, such as quantiles spaced by 0.1, is sufficient to deliver informative results. The computation is once more \(O(T^2)\) irrespective of the number of breaks allowed.
For all cases above, confidence intervals for the break dates are computed from the limiting distribution of the break point estimates derived in Oka and Qu (2011). That distribution has an analytical density function, so no simulation is needed to obtain the critical values, which keeps the computational cost down; see Bai (1995) and Oka and Qu (2011) for details.
The package uses the two test statistics \(SQ_\tau\) (single quantile) and \(DQ\) (multiple quantiles) proposed in Qu (2008).
The \(SQ_\tau\) test detects the presence of a structural break in a given quantile \(\tau\):
\[ SQ_{\tau }=\sup_{\lambda \in \lbrack 0,1]}\left\Vert (\tau (1-\tau ))^{-1/2}\left[ H_{\lambda ,T}(\hat{\beta}(\tau ))-\lambda H_{1,T}(\hat{\beta}% (\tau ))\right] \right\Vert _{\infty }, \]
where
\[ H_{\lambda ,T}(\hat{\beta}(\tau ))=\left( \sum_{t=1}^{T}\sum_{i=1}^{N}x_{it}x_{it}^{\prime }\right) ^{-1/2}\sum_{t=1}^{% [\lambda T]}\sum_{i=1}^{N}x_{it}\psi _{\tau }(y_{it}-x_{it}^{\prime }\hat{\beta}% (\tau )), \]
with \(\psi_\tau(u) = \tau - 1(u < 0)\) and, as before, the summation over \(i\) absent for a single time series. Here \(\hat\beta(\tau)\) is the full-sample estimate assuming no structural change, and \(\|\cdot\|_\infty\) is the sup norm, revealing the strongest evidence against the null.
The \(DQ\) test detects structural changes in quantiles in an interval \(\mathcal{T}_\omega\), taking a further supremum over \(\tau\):
\[ DQ=\sup_{\tau \in \mathcal{T}_{\omega }}\sup_{\lambda \in \lbrack 0,1]}\left\Vert H_{\lambda ,T}(\hat{\beta}(\tau ))-\lambda H_{1,T}(\hat{\beta}% (\tau ))\right\Vert _{\infty }. \]
These correspond to the exported functions
sq.test.0vs1() and dq.test.0vs1().
Suppose a model with \(l\) breaks has been estimated, with break estimates \(\hat{T}_1,\dots,\hat{T}_l\). These partition the sample into \(l+1\) segments, the \(j\)th being \([\hat{T}_{j-1}+1, \hat{T}_j]\). The strategy tests each of the \(l+1\) segments for the presence of an additional break. Letting \(SQ_{\tau,j}\) and \(DQ_j\) denote the tests applied to the \(j\)th segment,
\[ SQ_{\tau }(l+1\mid l)=\max_{1\leq j\leq l+1}SQ_{\tau ,j},\qquad DQ(l+1\mid l)=\max_{1\leq j\leq l+1}DQ_{j}, \]
where the segment statistics replace the full-sample sums by sums
running from \(T_{j-1}+1\) to \(T_j\), and \(\hat\beta_j(\tau)\) is estimated using the
\(j\)th regime only. We reject the null
in favor of a model with \(l+1\) breaks
if the resulting value exceeds the corresponding critical value. These
correspond to sq.test.lvsl_1() and
dq.test.lvsl_1().
These tests are asymptotically nuisance parameter free, and tables of critical values are provided in Qu (2008). They do not require the estimation of any variance parameter, hence have monotonic power even when multiple breaks are present.
The package has built-in critical values for common configurations:
for the \(SQ\) test when the number of
coefficients is below 100, and for the \(DQ\) test when the number of coefficients
is below 20 and the quantile trimming is symmetric (\(\omega_2 = 1 - \omega_1\)), via a response
surface (res.surface()). Outside those cases — asymmetric
trimming, more than 20 coefficients, or m.max above 5 — the
\(DQ\) critical values are computed by
simulation, which can add a few minutes or more to the running time.
Consider the interval \(\mathcal{T}_\omega\) and the quantile grid \(\tau_1,\dots,\tau_q \in \mathcal{T}_\omega\).
rq.break() prints the single-quantile analysis first and
the joint analysis second, which is the order of computation rather than
the order of reading. When interpreting output, consider follow the
steps above.
After determining the break dates, the coefficients are estimated conditional on those dates. This is equivalent to partitioning the sample using the break dates and running standard quantile regression on each subsample. These results are reported automatically by the main function.
Oka and Qu (2011) showed that if the break size is of higher order
than \(T^{-1/2}\), so that breaks are
not confounded with estimation uncertainty of order \(T^{-1/2}\), then the break dates are
estimated fast enough that the asymptotic distribution of the estimated
coefficients is the same as if the break dates were known — a familiar
result in the structural break literature. This permits computing
confidence intervals treating the estimated break dates as known. The
asymptotic variance involves the within-regime second moment matrix of
the regressors and the same matrix weighted by the conditional density
of the dependent variable at the quantile of interest; the density is
estimated by a difference quotient, as described in Qu (2008,
pp. 176–177). Instead of using the package, users can obtain the same
confidence intervals directly from the quantreg package
with the standard error option set to "nid".
The \(SQ\) and \(DQ\) statistics normalize the subgradient
process by an inverse square root of \(W =
\sum_t \sum_i x_{it} x_{it}'\) (the sums over \(i\) being absent for a single time series).
Such a matrix is not unique, and the argument norm.method
selects which one is used.
"cholesky" (the default) uses \((R')^{-1}\), where \(R\) is the Cholesky factor returned by
chol(), with \(R'R =
W\). This reproduces the results of versions 1.0.2 and earlier
exactly. Because the factor is constructed sequentially, it implicitly
gives more weight to regressors appearing earlier in the regression. It
is suitable when there is a natural ordering — for instance a quantile
autoregression in which low lags are listed first, as in the GDP
application. It is invariant to the units in which the regressors are
measured and to their signs.
"spectral" uses \(C^{-1/2}D^{-1}\), where \(D =
\mathrm{diag}(\sqrt{\mathrm{diag}(W)})\) and \(C = D^{-1}WD^{-1}\) is the correlation
matrix of the regressors, with \(C^{-1/2}\) its symmetric square root from
the spectral decomposition (Kessy, Lewin and Strimmer, 2018). This
treats the regressors symmetrically, yielding invariance to their order
as well as to their units and signs. It is the appropriate choice when
the regressors have no natural ordering, as with the age, gender and
winter regressors of the second application.
Both choices give the same limiting null distribution, so the same critical values apply and both tests are valid. The second option might yield lower power. Estimated break dates are unaffected by this argument, since they are obtained by minimizing the check function, which does not depend on the normalization. A numerical comparison is given in Section 4.7.
These invariance properties refer to the normalization itself. Because the quantile regression is re-estimated, the computed statistics can still differ slightly when the regressors are reordered or rescaled, by an amount that decreases with the sample size.
| Argument | Meaning |
|---|---|
y |
The dependent variable, a vector of length \(NT\) |
x |
The regressors, an \(NT \times p\) matrix or data frame. A column of ones should not be included; it is added automatically |
vec.tau |
The quantiles of interest,
e.g. seq(0.1, 0.9, by = 0.1). A coarse grid is generally
sufficient |
N |
The size of the cross-section; set to 1 for time series data |
trim.e |
The minimum length of any regime as a fraction of the total time span. Values between 0.10 and 0.20 are recommended |
vec.time |
The time indices, of length \(T\),
used for reporting the estimated break dates; or NULL to
report indices |
m.max |
The maximum number of breaks allowed (at most 10) |
v.a |
Significance level for determining the number of breaks: 1, 2 or 3 for 10%, 5% or 1% |
v.b |
Coverage level for the confidence intervals of break dates: 1 or 2 for 90% and 95% |
verbose |
TRUE displays results in the console; the default is
FALSE |
norm.method |
"cholesky" (default) or "spectral"; see
Section 2.6 |
Whether or not verbose is set, all estimation and
testing results are saved in the returned object.
y is a single vector of length \(NT\), stacked by period:
the first \(N\) elements are the units
observed in the first period, the next \(N\) the second period, and so forth.
x is stacked identically. For a time series \(N = 1\) and y is simply the
series in time order.
vec.time is different: it has length \(T\), not \(NT\), being one label per period.
For repeated cross-sections use unique() to reduce the
period column accordingly.
A break date is the final date of the existing regime, not the starting date of a new regime. An estimate of 1984 Q1 means the first regime ends in 1984 Q1 and the second begins in 1984 Q2.
The result is a list with two components: $s.out, based
on individual quantiles, and $m.out, based on all quantiles
jointly. Entries in $s.out are ordered according to
vec.tau, and for each quantile the break testing results
come first; if at least one significant break is detected, the break
locations and parameter estimates follow. Element names carry the
quantile they refer to:
| Element | Contents |
|---|---|
test_<tau>, test_joint |
Test statistics and critical values |
nbreak_<tau>, nbreak_joint |
Number of breaks detected |
br_est_<tau>, br_est_joint |
Break dates and confidence intervals, as indices |
br_est_time_<tau>,
br_est_joint_time |
The same in calendar format |
coef_<tau> |
Regime-by-regime coefficient estimates |
bsize_<tau>_Regime_j+1_minus_Regime_j |
Break sizes between adjacent regimes |
After loading the package, the U.S. GDP data are loaded with
data(gdp). The yq column contains the dates,
gdp the dependent variable, and the remaining two columns
the first and second lagged values of gdp, used as
regressors. The estimation sample runs from 1947 Q4 to 2009 Q2 — the raw
series begins in 1947 Q2, with the first two observations consumed by
the lags.
data(gdp)
str(gdp)
#> 'data.frame': 247 obs. of 4 variables:
#> $ yq : chr "1947 Q4" "1948 Q1" "1948 Q2" "1948 Q3" ...
#> $ gdp : num 6.066 6.357 7.363 2.15 0.614 ...
#> $ lag1: num -0.329 6.066 6.357 7.363 2.15 ...
#> $ lag2: num -0.613 -0.329 6.066 6.357 7.363 ...
head(gdp, 3)
#> yq gdp lag1 lag2
#> 1 1947 Q4 6.06552 -0.32868 -0.61348
#> 2 1948 Q1 6.35664 6.06552 -0.32868
#> 3 1948 Q2 7.36332 6.35664 6.06552The following commands define y and x:
A column of ones is always added to the regressors, so the model has three parameters allowed to be affected by structural breaks: the intercept, the coefficient on the first lag, and that on the second lag.
The next command specifies the quantiles of interest:
Given these inputs the function performs two sets of calculations.
First it analyzes the quantiles in vec.tau independently,
so the number of breaks and their locations may differ across quantiles.
Then it analyzes all quantiles simultaneously, assuming breaks are
common across quantiles and pooling information to estimate the break
dates.
Since this is a time series regression, N = 1. The
minimum regime length matters because if a regime is too short the model
fit may be non-unique and the estimation may pick up spurious breaks;
trim.e = 0.15 implies a regime is at least 15% of the
sample, or 37 quarters. Related to this is the maximum number of breaks,
m.max = 3, allowing at most three breaks and hence four
regimes. Finally v.a = 2 selects the 5% level for
determining the number of breaks and v.b = 2 selects 95%
confidence intervals for the break dates.
Setting vec.time = gdp[, "yq"] makes the program report
break dates using those labels; setting it to NULL reports
integers instead.
For \(\tau = 0.2\) the results are:
$s.out$test_0.2 # testing results at the chosen level
1 Breaks 2 Breaks 3 Breaks
SQ test 1.423269 1.373012 0
Critical values 1.529859 1.637547 0
$s.out$nbreak_0.2 # number of breaks detected
[1] 0
For this quantile the test of no break against a single break equals 1.423269, while the critical value is 1.529859. The value is insignificant at the chosen level, so no break is detected. The final column is zero because the test is not computed when the previous tests are insignificant at the 10% level. No break estimation results are produced.
The results for the other quantiles also show insignificance until \(\tau = 0.65\). At that point one significant break is detected, followed by its confidence interval reported first as index values and then as dates:
$s.out$test_0.65
1 Breaks 2 Breaks 3 Breaks
SQ test 1.817933 1.023126 0
Critical values 1.529859 1.637547 0
$s.out$nbreak_0.65
[1] 1
$s.out$br_est_0.65
Estimate CI_Lower_Bound CI_Upper_Bound
Break 1 147 83 161
$s.out$br_est_time_0.65
Estimate CI_Lower_Bound CI_Upper_Bound
Break 1 "1984 Q2" "1968 Q2" "1987 Q4"
One break is detected with a point estimate of \(t = 147\), corresponding to the second quarter of 1984, with a confidence interval of \([83, 161]\), or equivalently [1968 Q2, 1987 Q4]. The output also includes the estimated coefficients for the two regimes:
$s.out$coef_0.65$Regime_1
Value Std. Error t value Pr(>|t|)
Intercept 4.5169837 0.63003316 7.169438 3.625833e-11
x1 0.4199469 0.09643037 4.354924 2.512308e-05
x2 -0.1051057 0.09458095 -1.111277 2.683010e-01
$s.out$coef_0.65$Regime_2
Value Std. Error t value Pr(>|t|)
Intercept 2.2855100 0.4866286 4.696620 8.711282e-06
x1 0.1724133 0.1218581 1.414869 1.603091e-01
x2 0.2386392 0.1320517 1.807164 7.383669e-02
The sum of the autoregressive coefficients changes little, but the intercept decreases significantly, indicating a notably lower 0.65 quantile after the break:
$s.out$bsize_0.65_Regime_2_minus_Regime_1
Value Std. Error t value Pr(>|t|)
Intercept -2.2314737 0.7957371 -2.804285 0.005453863
x1 -0.2475336 0.1375265 -1.799898 0.073127343
x2 0.3437448 0.1418386 2.423492 0.016109478
The method similarly detects a break in the 0.80 quantile, where the pattern is sharper still:
$s.out$test_0.8
1 Breaks 2 Breaks 3 Breaks
SQ test 2.170968 1.064567 0
Critical values 1.529859 1.637547 0
$s.out$br_est_time_0.8
Estimate CI_Lower_Bound CI_Upper_Bound
Break 1 "1984 Q1" "1978 Q4" "1990 Q1"
$s.out$bsize_0.8_Regime_2_minus_Regime_1
Value Std. Error t value Pr(>|t|)
Intercept -3.0893051 0.7719650 -4.001872 8.367631e-05
x1 -0.2108298 0.1159821 -1.817778 7.033963e-02
x2 0.4047554 0.1420980 2.848425 4.773147e-03
Collecting the number of breaks across quantiles:
| \(\tau\) | 0.20 | 0.35 | 0.50 | 0.65 | 0.80 |
|---|---|---|---|---|---|
| \(SQ_\tau\) (1 break) | 1.423 | 1.479 | 1.001 | 1.818 | 2.171 |
| 5% critical value | 1.530 | 1.530 | 1.530 | 1.530 | 1.530 |
| Breaks detected | 0 | 0 | 0 | 1 | 1 |
At the median the statistic is 1.001 against a critical value of 1.530 — no evidence of a break at all — while the upper quantiles reject clearly.
The results are structured similarly, now based on all chosen quantiles:
$m.out$test_joint
1 Breaks 2 Breaks 3 Breaks
DQ test 1.0275870 0.5892746 0
Critical values 0.9098714 0.9584567 0
$m.out$nbreak_joint
[1] 1
$m.out$br_est_joint
Estimate CI_Lower_Bound CI_Upper_Bound
Break 1 146 120 147
$m.out$br_est_joint_time
Estimate CI_Lower_Bound CI_Upper_Bound
Break 1 "1984 Q1" "1977 Q3" "1984 Q2"
A single break is detected, as in the analysis based on the individual upper quantiles. Note that the joint confidence interval, [1977 Q3, 1984 Q2], is considerably tighter than the single-quantile interval at \(\tau = 0.65\), [1968 Q2, 1987 Q4]: pooling information across quantiles buys precision in the date. The rest of the output contains the coefficient estimates and their confidence intervals as in the single-quantile case.
In summary, the findings shed light on the “Great Moderation” debate on U.S. GDP growth. The decline in volatility mainly affected the upper tail, with the median and lower quantiles remaining stable. This implies that expansions became less rapid, while recessions remained as severe. A test on the conditional mean, which averages over the distribution, would understate the change and misdescribe its nature.
tt <- seq_len(nrow(gdp))
brk <- 146; lo <- 120; hi <- 147 # DQ estimate and its 95% interval
op <- par(mar = c(3.5, 4, 2.5, 1))
plot(tt, gdp$gdp, type = "n", xaxt = "n", bty = "n", ylim = c(-12, 18),
xlab = "", ylab = "Real GDP growth (%, annualized)")
rect(lo, -12, hi, 18, col = "#EDE7F6", border = NA)
abline(h = 0, col = "#CFCFD4")
lines(tt, gdp$gdp, col = "#5A5A66", lwd = 1.4)
segments(brk, -12, brk, 15, col = "#6C4FB8", lwd = 2)
text(brk, 16.5, " break: 1984 Q1", adj = c(0, 0.5), col = "#6C4FB8", cex = 0.85)
text(lo, 16.5, "95% CI ", adj = c(1, 0.5), col = "#8E7BC6", cex = 0.8)
at <- seq(2, nrow(gdp), by = 40)
axis(1, at = at, labels = sub(" Q[1-4]$", "", gdp$yq[at]), col = "#CFCFD4")The shaded band is the 95% confidence interval for the break date and the vertical rule the point estimate. The visible narrowing of the series after it is the compression that the upper-quantile results quantify.
Re-running the analysis with norm.method = "spectral"
changes the statistics somewhat but not the conclusions:
| \(\tau\) | \(SQ_\tau\),
"cholesky" |
\(SQ_\tau\),
"spectral" |
5% critical value |
|---|---|---|---|
| 0.20 | 1.423 | 1.158 | 1.530 |
| 0.35 | 1.479 | 1.461 | 1.530 |
| 0.50 | 1.001 | 0.962 | 1.530 |
| 0.65 | 1.818 | 1.845 | 1.530 |
| 0.80 | 2.171 | 2.332 | 1.530 |
| \(DQ\) | 1.028 | 1.043 | 0.910 |
Every rejection decision is unchanged, and the estimated break date remains 1984 Q1 with the identical confidence interval [1977 Q3, 1984 Q2] — as it must, since break dates do not depend on the normalization.
The dynamic programming algorithm determines the globally optimal break partitions at a cost growing with the square of the sample size, regardless of the number of breaks allowed. In this example the program finishes within a few minutes on a typical desktop computer with a single processor. Because the quantile trimming here is symmetric (\(\omega_1 = 0.2\), \(\omega_2 = 0.8\)) and there are only three coefficients, the \(DQ\) critical values come from the response surface and no simulation is required.
The function displays error messages if the inputs are not configured
properly. Suppose we set trim.e = 0.2 and
m.max = 6. The product exceeds 1, because it is not
possible to allow six breaks when each regime is at least 20% of the
sample:
rq.break(y, x, vec.tau, N = 1, trim.e = 0.2, vec.time = gdp[, "yq"],
m.max = 6, v.a = 2, v.b = 2)
#> Error in rq.break(y, x, vec.tau, N = 1, trim.e = 0.2, vec.time = gdp[, : Error: m.max*trim.e exceeds 1. This occurs because too many regimes are allowed or the minimum length of a regime is too large. Consider decreasing m.max, trim.e, or both.As another example, if trim.e is too small the message
suggests increasing it:
rq.break(y, x, vec.tau, N = 1, trim.e = 0.01, vec.time = gdp[, "yq"],
m.max = 3, v.a = 2, v.b = 2)
#> Error in rq.break(y, x, vec.tau, N = 1, trim.e = 0.01, vec.time = gdp[, : Error: trim.e * nrow(x) must be at least the number of regressors; otherwise, the estimation results are not unique. Consider increasing trim.e.When an error message is produced the program exits with no saved results, and the user can modify the inputs and restart.
The main steps and the output structure are similar to the time series case. The data record the blood alcohol concentration of drivers under 21 involved in motor vehicle accidents in California from 1983 Q1 to 2007 Q4, together with age, a gender dummy, and a dummy for the fourth quarter. There are \(N = 108\) drivers per quarter over \(T = 100\) quarters, giving \(NT = 10{,}800\) observations. The data are organized so that the first \(N\) rows are for the first time period, the next \(N\) rows for the next period, and so forth.
data(driver)
str(driver)
#> 'data.frame': 10800 obs. of 5 variables:
#> $ yq : chr "1983 Q1" "1983 Q1" "1983 Q1" "1983 Q1" ...
#> $ bac : num 0.23 0 0 0 0 0 0.04 0.22 0 0 ...
#> $ age : int 20 17 20 20 18 16 20 19 20 20 ...
#> $ gender: int 1 1 1 1 1 1 1 1 0 1 ...
#> $ winter: int 0 0 0 0 0 0 0 0 0 0 ...y <- driver[, "bac"]
x <- driver[, c("age", "gender", "winter")]
vec.time <- unique(driver[, "yq"]) # length T = 100, one label per quarter
length(vec.time)
#> [1] 100The choice of quantiles is dictated by the data. BAC is exactly zero for most of these drivers:
mean(driver$bac == 0)
#> [1] 0.6187037
quantile(driver$bac, c(0.50, 0.60, 0.65, 0.70, 0.80, 0.85))
#> 50% 60% 65% 70% 80% 85%
#> 0.00 0.00 0.04 0.07 0.13 0.16About 62% of the observations sit at zero, so every quantile below roughly \(\tau = 0.62\) falls inside that point mass and carries no information about drinking behaviour. Attention is therefore restricted to \(\tau \in \{0.70, 0.75, 0.80, 0.85\}\) — high enough to clear the mass point, low enough to be estimated reliably.
res.d <- rq.break(y, x,
vec.tau = seq(0.70, 0.85, by = 0.05),
N = 108,
trim.e = 0.05,
vec.time = vec.time,
m.max = 3,
v.a = 2,
v.b = 2,
verbose = TRUE,
norm.method = "cholesky")Two features differ from the time series case. First,
N = 108 changes the meaning of the sample: regime lengths,
trimming and break dates are counted in periods. Second, the
quantile range is asymmetric (\(\omega_1 = 0.70\), \(\omega_2 = 0.85\), so \(\omega_2 \neq 1 - \omega_1\)), so the
response surface does not apply and the function prints
The critical values of the DQ test is obtained via simulations
before generating them by simulation, with 50,000 replications, for this specific design matrix. This is accurate but noticeably slower, and is the dominant cost of this example.
The first quantile is \(\tau = 0.7\), for which two breaks are detected along with their confidence intervals:
$s.out$test_0.7
1 Breaks 2 Breaks 3 Breaks
SQ test 5.179373 2.205150 1.339123
Critical values 1.574681 1.679331 1.737955
$s.out$nbreak_0.7
[1] 2
$s.out$br_est_0.7
Estimate CI_Lower_Bound CI_Upper_Bound
Break 1 10 6 15
Break 2 38 35 39
$s.out$br_est_time_0.7
Estimate CI_Lower_Bound CI_Upper_Bound
Break 1 "1985 Q2" "1984 Q2" "1986 Q3"
Break 2 "1992 Q2" "1991 Q3" "1992 Q3"
The tests reject far more decisively than in the time series case — the statistics are several times their critical values — which is what a cross-section of 108 per period buys in power. The output continues with the parameter estimates for the three regimes and then moves to the next quantile.
The number of breaks varies across the range:
| \(\tau\) | 0.70 | 0.75 | 0.80 | 0.85 |
|---|---|---|---|---|
| \(SQ_\tau\) (1 break) | 5.179 | 4.613 | 3.503 | 3.258 |
| \(SQ_\tau(2 \mid 1)\) | 2.205 | 1.931 | 1.392 | 1.056 |
| 5% critical values | 1.575 / 1.679 | 1.575 / 1.679 | 1.575 / 1.679 | 1.575 / 1.679 |
| Breaks detected | 2 | 2 | 1 | 1 |
At \(\tau = 0.80\) and \(0.85\) only the 1992 break is found; the mid-1980s break appears only at the two lower quantiles. This is the pattern behind the substantive conclusion below.
$m.out$test_joint
1 Breaks 2 Breaks 3 Breaks
DQ test 2.3734870 1.0105268 0.5995825
Critical values 0.7717347 0.8162768 0.8428049
$m.out$nbreak_joint
[1] 2
$m.out$br_est_joint
Estimate CI_Lower_Bound CI_Upper_Bound
Break 1 9 5 13
Break 2 38 34 39
$m.out$br_est_joint_time
Estimate CI_Lower_Bound CI_Upper_Bound
Break 1 "1985 Q1" "1984 Q1" "1986 Q1"
Break 2 "1992 Q2" "1991 Q2" "1992 Q3"
The joint analysis recovers both breaks. The rest of the output contains the coefficient estimates for each quantile followed by the break size estimates at each quantile. At \(\tau = 0.7\):
$m.out$bsize_0.7_Regime_2_minus_Regime_1
Value Std. Error t value Pr(>|t|)
Intercept -2.200000e-01 0.086392487 -2.546518e+00 0.01089414
x1 1.000000e-02 0.004616669 2.166064e+00 0.03032812
x2 1.000000e-02 0.015634579 6.396079e-01 0.52244114
x3 -2.674365e-17 0.013993342 -1.911170e-15 1.00000000
$m.out$bsize_0.7_Regime_3_minus_Regime_2
Value Std. Error t value Pr(>|t|)
Intercept 0.103333333 0.054260043 1.9044093 0.05688347
x1 -0.008333333 0.003023686 -2.7560181 0.00586080
x2 0.003333333 0.010360097 0.3217473 0.74765036
x3 0.020000000 0.010266885 1.9480105 0.05143960
Note that in $m.out the coefficients and break sizes are
reported for every quantile in vec.tau at
the \(DQ\) break dates, including \(\tau = 0.80\) and \(0.85\) where the single-quantile analysis
found only one break. This is by construction: the joint procedure
decides the number and location of the breaks once, using all quantiles
together, and then estimates each quantile’s coefficients subject to
that common partition.
The two dates are consistent with the 1984 National Minimum Drinking Age Act and a 1991 beer tax increase. The changes are negative and meaningful in magnitude, but smaller for higher quantiles — the policies were more effective for “light drinkers” than for “heavy drinkers”. This is encouraging but falls short of expectations, since heavy drinkers are more likely to cause accidents, suggesting that additional policies are needed to deter heavy drinking.
rq.break() is a wrapper around exported components, each
of which can be used on its own — to test at a date decided in advance,
to reuse an expensive computation, or to inspect intermediate
quantities.
sq.test.0vs1() implements \(SQ_\tau\) of Section 2.4.1 with no search
over the number of breaks:
y <- gdp[, "gdp"]
x <- gdp[, c("lag1", "lag2")]
sq.test.0vs1(y, x, v.tau = 0.8, n.size = 1)
#> [1] 2.170968At the 5% level with three coefficients the critical value is 1.530,
so this rejects. dq.test.0vs1() is the corresponding \(DQ\) test over a quantile range:
For a symmetric range its critical values come from the response surface:
res.surface(p = 3, l = 0, q.L = 0.2, q.R = 0.8, d.Sym = TRUE) # 10%, 5%, 1%
#> [,1]
#> [1,] 0.8580936
#> [2,] 0.9098714
#> [3,] 1.0223330The sequential versions of Section 2.4.2 take the break dates estimated under the null and test for one more:
sq.test.lvsl_1(y, x, v.tau = 0.8, n.size = 1, vec.date = 146)
#> [1] 1.064567
dq.test.lvsl_1(y, x, q.L = 0.2, q.R = 0.8, n.size = 1, vec.date = 146)
#> [1] 0.5892746Both fall below their critical values (1.638 and 0.958 at the 5% level), confirming a single break.
rq.est.regime() fits each regime separately:
rq.est.regime(y, x, v.tau = 0.8, vec.date = 146, n.size = 1)
#> $Regime_1
#> Value Std. Error t value Pr(>|t|)
#> Intercept 6.1285339 0.58621285 10.454452 0.000000e+00
#> x1 0.3744357 0.07818645 4.789010 4.142365e-06
#> x2 -0.0906033 0.07957956 -1.138525 2.568052e-01
#>
#> $Regime_2
#> Value Std. Error t value Pr(>|t|)
#> Intercept 3.0392288 0.4220644 7.200865 1.231277e-10
#> x1 0.1636059 0.1187198 1.378084 1.713156e-01
#> x2 0.3141521 0.1122296 2.799192 6.170306e-03rq.est.full() fits all regimes in a single quantile
regression, which is what makes the differences between adjacent regimes
and their standard errors available:
fit <- rq.est.full(y, x, v.tau = 0.8, vec.date = 146, n.size = 1)
summary(fit, se = "nid", covariance = TRUE)ci.date.m() builds the confidence intervals of Section
2.3 for dates supplied by the user; the three columns are the estimate
and the lower and upper bounds:
ci.date.m(y, x, vec.tau = 0.8, vec.date = 146, n.size = 1, v.b = 2)
#> [,1] [,2] [,3]
#> [1,] 146 125 170Passing a vector to vec.tau gives the multi-quantile
interval instead.
The expensive step is gen.long(), which evaluates the
objective function over every admissible segment. brdate()
then runs the dynamic program of Bai and Perron (2003) over those
values, and sq() / dq() apply the sequential
tests. Splitting them apart allows the gen.long() output to
be reused across several settings of m.max,
v.a or norm.method:
T.size <- length(y)
trim.size <- round(T.size * 0.15)
out.long <- gen.long(y, x, vec.tau, n.size = 1, trim.size) # the expensive step
mat.long.s <- out.long$mat.long # one column per quantile
vec.long.m <- out.long$vec.long # quantiles combined
mat.date <- brdate(y, x, n.size = 1, m = 3, trim.size, vec.long.m)
dq(y, x, vec.tau, q.L = 0.2, q.R = 0.8, n.size = 1, m.max = 3,
trim.size, mat.date, d.Sym = TRUE, table.cv = NULL)d.Sym = TRUE asserts a symmetric quantile range so that
the response surface applies, in which case table.cv = NULL
is correct. For an asymmetric range set d.Sym = FALSE and
supply simulated critical values.
Runtime. The cost is dominated by
gen.long(), which is \(O(T^2)\) per quantile and does not depend
on m.max. Raising m.max adds only the cheap
search over precomputed values and a few more sequential tests, so there
is little to gain by keeping it artificially small. What drives the cost
is \(T\) (quadratically) and the number
of quantiles (linearly).
Warnings about non-unique fits. rq()
warns when a quantile regression solution is not unique, which happens
routinely on short segments and on data with many tied values — the
driver BAC data especially. These warnings are benign here;
options(warn = -1) suppresses them.
“confidence interval is out of the range”. This
warning means an interval extends past the start or end of the sample.
The date estimate is still reported, but is not converted to calendar
form, so br_est_time_* will be missing for that quantile.
It usually signals a break estimated close to a sample boundary, or one
estimated imprecisely.
Reproducibility. When the \(DQ\) critical values come from tables or
the response surface they are fixed and repeated runs give identical
output. When they are simulated instead, they carry Monte Carlo noise,
and the package does not set a seed internally. In the
driver example the simulated 5% critical values move by
roughly \(\pm 0.003\) across runs — far
too small to change the number of breaks detected, but enough that the
printed critical values will not match to the last digit from one
session to the next. Call set.seed() before
rq.break() if byte-identical output is required. Everything
else — break dates, coefficients, and the \(SQ\) and \(DQ\) statistics themselves — is
deterministic.
Bai, J. (1995). Least Absolute Deviation Estimation of a Shift. Econometric Theory, 11, 403–436.
Bai, J. and P. Perron (2003). Computation and Analysis of Multiple Structural Change Models. Journal of Applied Econometrics, 18, 1–22.
Kessy, A., A. Lewin and K. Strimmer (2018). Optimal Whitening and Decorrelation. The American Statistician, 72(4), 309–314.
Koenker, R. (2005). Quantile Regression. Cambridge University Press.
Oka, T. and Z. Qu (2011). Estimating Structural Changes in Regression Quantiles. Journal of Econometrics, 162, 248–267. doi:10.1016/j.jeconom.2011.01.005
Picard, D. (1985). Testing and Estimating Change-Points in Time Series. Advances in Applied Probability, 17, 841–867.
Qu, Z. (2008). Testing for Structural Change in Regression Quantiles. Journal of Econometrics, 146, 170–184. doi:10.1016/j.jeconom.2008.08.006
Su, L. and Z. Xiao (2008). Testing for Parameter Stability in Quantile Regression Models. Statistics and Probability Letters, 78, 2768–2775.
Yao, Y. C. (1987). Approximating the Distribution of the Maximum Likelihood Estimate of the Change-Point in a Sequence of Independent Random Variables. The Annals of Statistics, 15, 1321–1328.