| Title: | 'Constrained Quantile Regression with B-Splines' |
|---|---|
| Description: | Quantile regression with B-splines under shape constraints. The initial version with cubic splines is now augmented with splines of degree 1 to 4. Constraints for degrees 3 (monotone) and 4 (monotone and convex) use the Karlin-Studden SOCP characterization for the sign of the polynomial, while other constraints applied at the knots are added as linear problems. The method for cubic splines is described in 'Abbes (2025)' <doi:10.5281/zenodo.17427913>. Other formulations are simple consequences of the other given references. All B-spline and polynomial functions have been rewritten for consistency. This package provides an original B-spline library for conversion between PP-form and B-spline representation, evaluation, differentiation, callable and non-callable objects, print human readable pp forms, view basis, all based on "De Boor\'s" theory. It also extends to multiple knots to catch up singularities. This feature is robust in the package including for constrained regression. This R implementation is intended for demonstration and prototyping. An equivalent Python package is available at <https://pypi.org/project/BsplineQuantRegpy/>. |
| Authors: | Alexandre Abbes [aut, cre] |
| Maintainer: | Alexandre Abbes <[email protected]> |
| License: | GPL-3 |
| Version: | 0.2.6 |
| Built: | 2026-10-10 19:21:25 UTC |
| Source: | https://github.com/alexandreabbes/bsplinequantreg |
For a quadratic polynomial p(u) = a*u^2 + b*u + c on [0,1], this function applies the Karlin-Studden SOCP constraints to ensure p(u) >= 0 or p(u) <= 0 on [0,1].
apply_karlin_quadratic(p2, p1, p0, z0, sign = 1)apply_karlin_quadratic(p2, p1, p0, z0, sign = 1)
p2 |
Coefficient of u^2 |
p1 |
Coefficient of u |
p0 |
Constant term |
z0 |
Auxiliary SOCP variable |
sign |
Sign of the constraint (+1 for >= 0, -1 for <= 0) |
List of 'CVXR' constraints
Computes the values of all B-spline basis functions at given points.
bs_direct(Basis, x_values = NULL, verbose = FALSE)bs_direct(Basis, x_values = NULL, verbose = FALSE)
Basis |
Object returned by |
x_values |
Vector of evaluation points |
verbose |
set to TRUE increases verbosity |
Matrix of basis function values (n_splines x length(x_values))
Build B-spline basis in piecewise polynomial form Computes local polynomial coefficients for each B-spline basis function on each interval. Polynomials are expressed in the canonical basis Uses De Boor's recursion formula.
Bspline_base(sn, degree = 3, der = 0, verbose = FALSE)Bspline_base(sn, degree = 3, der = 0, verbose = FALSE)
sn |
Extended knot vector (including endpoint repetitions) This means if t0..tkn it the set of knot then sn should be given as a vector with "degree" times t_0 and t_kn at the beginning and the ends. its length is number of intervals+1+2*degree. |
degree |
'B-spline' degree (default = 3 for cubic) |
der |
Derivative order (0 = original basis) |
verbose |
boolean FALSE (default) or TRUE. |
A list containing:
base |
Coefficients in the local bases, in the form of an 3-d array [j,nu,coeff], j : the number of the spline in the basis, nu: the number of the interval in the extended notation, coeff : the coefficients in decreasing order Decresing (matlab) convention on the local bases (t-s_nu)^l, l=3.2.1 base[j,,] is a matrix of piecewise polynomial function compatible with the pp-form. |
base0 |
Coefficients in canonical basis (centered at 0) (1, t, t^2, t^3) centered at the interval origin. |
ext_knot |
Extended knot vector |
knot |
Effective knot partition including ends) |
degree |
Spline degree |
n_splines |
Number of basis functions |
deriv_order |
Applied derivative order |
sn <- c(0,0,0,0,1,2,3,4,5,5,5,5) basis <- Bspline_base(sn, degree=3) x=(0:(5*100))/100 y=bs_direct(basis,x) matplot(x,t(y)) #or simple: #view_basis(basis)sn <- c(0,0,0,0,1,2,3,4,5,5,5,5) basis <- Bspline_base(sn, degree=3) x=(0:(5*100))/100 y=bs_direct(basis,x) matplot(x,t(y)) #or simple: #view_basis(basis)
Computes the basis of order der derivatives of a B-spline basis.
Bspline_base_deriv(Bsbasis, der = 1, verbose = FALSE)Bspline_base_deriv(Bsbasis, der = 1, verbose = FALSE)
Bsbasis |
Object returned by |
der |
Derivative order |
verbose |
boolean FALSE (default) or TRUE. |
A list similar to Bspline_base for the derivative basis
Given a B-spline of given degree, coefficients, knots, compute the coefficients of the derivative of order 'der' in the B-spline basis of degree d-der. Uses the standard algorithm for differentiating bsplines
Bspline_deriv(bspline, der = 1, callable = NULL, verbose = FALSE)Bspline_deriv(bspline, der = 1, callable = NULL, verbose = FALSE)
bspline |
callable_spline or non_callable_spline class list or function, or list with variable names 'degree', 'knot' ,'coeff'. |
der |
Derivative order (default = 1) |
callable |
Boolean, if TRUE returns a callable Bspline. If not provided |
verbose |
Boolean gives output messages when TRUE return the same class as input : 'callable' or 'non_callable' |
Coefficients of the derivative B-spline (degree = degree - der)
normalized first and second derivative coefficients on each interval. for a cubic B-spline basis
bspline_to_deriv_coeffs_cubic( tn = NULL, degree = 3, x_values = 0, Bsbasis = NULL, verbose = FALSE )bspline_to_deriv_coeffs_cubic( tn = NULL, degree = 3, x_values = 0, Bsbasis = NULL, verbose = FALSE )
tn |
Knot vector (effective partition, not extended. OPtionnal if Bsbasis is given) |
degree |
Spline degree (default = 3) |
x_values |
Evaluation points for design matrix (0 = no evaluation) |
Bsbasis |
Bspline basis structure if already computed. Optional if knots are given. |
verbose |
boolean FALSE (default) or TRUE. |
A list containing (kn: Nb intervals, N=kn+3: Nb basis functions):
d0 |
Design matrix (if x_values provided) |
d1 |
First derivative coefficients [a3, a2, a1] for each interval: (kn x N x 3) array |
d2 |
Second derivative values at knot: ((kn+1) x N) matrix |
d3 |
Third derivative values at knots: (kn x N) matrix |
Derivative coefficients for linear B-spline Computes normalized first derivative coefficients for linear B-splines. For linear splines, the derivative is constant on each interval.
bspline_to_deriv_coeffs_lin(tn, degree = 1, x_values = 0, verbose = FALSE)bspline_to_deriv_coeffs_lin(tn, degree = 1, x_values = 0, verbose = FALSE)
tn |
Knot vector (effective partition) |
degree |
Spline degree (should be 1) |
x_values |
Evaluation points for design matrix (0 = no evaluation) |
verbose |
logical; if TRUE, print progress messages |
A list containing:
d0 |
Design matrix (if x_values provided) |
d1 |
First derivative values (constant per interval) |
Computes normalized first and second derivative coefficients for quadratic B-splines on each interval.
bspline_to_deriv_coeffs_quad(tn, degree = 2, x_values = 0, verbose = FALSE)bspline_to_deriv_coeffs_quad(tn, degree = 2, x_values = 0, verbose = FALSE)
tn |
Knot vector (effective partition) |
degree |
Spline degree (should be 2) |
x_values |
Evaluation points for design matrix (0 = no evaluation) |
verbose |
logical; if TRUE, print progress messages |
A list containing:
d0 |
Design matrix (if x_values provided) |
d1 |
First derivative coefficients [a1, a0] for each interval |
d2 |
Second derivative values (constant per interval) |
Computes normalized first, second, and third derivative coefficients for quartic B-splines on each interval.
bspline_to_deriv_coeffs_quart(knot, degree = 4, x_values = 0)bspline_to_deriv_coeffs_quart(knot, degree = 4, x_values = 0)
knot |
Knot vector (effective partition) |
degree |
Spline degree (should be 4) |
x_values |
Evaluation points for design matrix |
A list containing:
d0 |
Design matrix (if x_values provided) |
d1 |
First derivative coefficients [a3, a2, a1, a0] for each interval |
d2 |
Second derivative coefficients [a2, a1, a0] for each interval |
d3 |
Third derivative values at knot (linear constraints) |
Transforms a B-spline object (callable or non-callable) into a piecewise polynomial representation. The resulting PP object contains the polynomial coefficients for each interval between knots.
Bsplinetopp(Bspline, Bsbasis = NULL, callable = FALSE, verbose = FALSE)Bsplinetopp(Bspline, Bsbasis = NULL, callable = FALSE, verbose = FALSE)
Bspline |
A B-spline object (list, non_callable_spline, or callable_spline) containing at least 'coeff', 'degree', and 'knot'. |
Bsbasis |
Optional pre-computed B-spline basis object from Bspline_base(). If NULL, the basis is computed automatically. |
callable |
Logical; if TRUE, returns a callable function for evaluation. If FALSE (default), returns a non_callable_pp object. If a callable spline is given as input, then by default is return a callable pp. |
verbose |
Logical; if TRUE, print progress messages. |
A PP object (piecewise polynomial) with class: - "callable_pp" if callable = TRUE - "non_callable_pp" if callable = FALSE The object can be evaluated with evalpp() or directly if callable.
## Not run: # Create a B-spline sn <- c(0,0,0,0,1,2,3,4,5,5,5,5) basis <- Bspline_base(sn, degree = 3) basis$coeff <- runif(basis$n_splines) # Convert to PP (non-callable) pp <- Bsplinetopp(basis, callable = FALSE) y <- evalpp(pp, seq(0, 5, length.out = 100)) # Convert to PP (callable) pp_call <- Bsplinetopp(basis, callable = TRUE) y <- pp_call(seq(0, 5, length.out = 100)) ## End(Not run)## Not run: # Create a B-spline sn <- c(0,0,0,0,1,2,3,4,5,5,5,5) basis <- Bspline_base(sn, degree = 3) basis$coeff <- runif(basis$n_splines) # Convert to PP (non-callable) pp <- Bsplinetopp(basis, callable = FALSE) y <- evalpp(pp, seq(0, 5, length.out = 100)) # Convert to PP (callable) pp_call <- Bsplinetopp(basis, callable = TRUE) y <- pp_call(seq(0, 5, length.out = 100)) ## End(Not run)
Converts a polynomial expressed in the basis (t-a)^k to its representation in the basis (t-b)^k using Taylor's formula. P(t) = sum c_k (t-a)^k P(t) = sum c"_k (t-b)^k
change_polynomial_base_taylor(coeffs_a, a, b)change_polynomial_base_taylor(coeffs_a, a, b)
coeffs_a |
Coefficients in basis centered at a (decreasing powers) |
a |
Original expansion point |
b |
New expansion point |
Coefficients in basis centered at b
Evaluates a piecewise polynomial (PP form) function at given points.
evalpp(p, x_values)evalpp(p, x_values)
p |
List with components |
x_values |
Vector of evaluation points |
Function values at the requested points
Get parameters from a callable spline or a callable pp object
get_parameters(x)get_parameters(x)
x |
A callable spline object |
A list with degree, knots, coefficients, and 'Bspline' object
Transforms a list container 'Bspline' that may result from any of the regression functions associated to 'quantile_spline' into a callable function that is the spline function with given knots and coefficients on the corresponding B-spline basis. It can be evaluated at any point of the knot range transfering the call to the 'spline_eval()' function, while preserving access to parameters. Outside the knots range, it extrapolates the side part of the spline.
make_spline(Bspline, verbose = FALSE, callable = TRUE)make_spline(Bspline, verbose = FALSE, callable = TRUE)
Bspline |
A list containing at least (knot, coefficients, degree) like the one returned by quantile_spline or one of the degree-specific functions. If it already contains a 'spline' element, returns the object unchanged. |
verbose |
Boolean. If TRUE : output the attributes of the 'Bspline' |
callable |
is a Boolean flag that allows to return a simple spline list with class 'non_callable_spline'. |
Either a callable function can be called as 'Bspline(x)', with class ('callable_spline'), and all parameters as attributes or the list of parameters with an additional 'non_callable_spline' classe.
Creates a PP structure from polynomial coefficients and knots. If callable = TRUE, returns a function that evaluates the PP.
makpp(coeff, tn = NULL, callable = FALSE, verbose = FALSE)makpp(coeff, tn = NULL, callable = FALSE, verbose = FALSE)
coeff |
matrix (coefficents) or pp polynomial. Coefficient matrix (kn x (degree+1)) |
tn |
vector (knots) of length kn+1. Needed if coefficient is not pp |
callable |
Boolean; if TRUE, returns a callable function |
verbose |
Boolean |
A PP object or a callable function
Evaluates a polynomial at one or more points.
poly_eval(p, xvalues)poly_eval(p, xvalues)
p |
Coefficient vector (decreasing powers) |
xvalues |
vector at which to evaluate the polynomial |
Vector of same length as xvalues : polynomial values at the points xvalues
# P(x) = 1 + x + x^2 poly_eval(c(1, 1, 1), c(0, 1, 2)) # returns c(1, 3, 7)# P(x) = 1 + x + x^2 poly_eval(c(1, 1, 1), c(0, 1, 2)) # returns c(1, 3, 7)
Adds two polynomials represented by coefficients in decreasing power order.
polyadd(p1, p2, verbose = FALSE)polyadd(p1, p2, verbose = FALSE)
p1 |
First polynomial (coefficient vector) |
p2 |
Second polynomial (coefficient vector) |
verbose |
boolean FALSE (default) or TRUE. |
Coefficient vector of the sum
polyadd(c(1, 1), c(1, -1)) # returns c(2, 0)polyadd(c(1, 1), c(1, -1)) # returns c(2, 0)
der of a polynomial.Polynomial derivative
Computes the derivative of order der of a polynomial.
polyderiv(p, der = 1)polyderiv(p, der = 1)
p |
Coefficient vector (decreasing powers) |
der |
Derivative order (default = 1) |
Coefficients of the derivative polynomial
# P(x) = x^2 -> P'(x) = 2x polyderiv(c(1, 0, 0), 1) # returns c(2, 0)# P(x) = x^2 -> P'(x) = 2x polyderiv(c(1, 0, 0), 1) # returns c(2, 0)
Multiplies two polynomials represented by coefficients in decreasing power order.
polymul(p1, p2, ord = 0, verbose = FALSE)polymul(p1, p2, ord = 0, verbose = FALSE)
p1 |
First polynomial (coefficient vector, decreasing powers) |
p2 |
Second polynomial (coefficient vector, decreasing powers) |
ord |
Unused (compatibility parameter) |
verbose |
boolean FALSE (default) or TRUE. |
Coefficient vector of the product polynomial (decreasing powers)
# (1 + x) * (1 + x) = 1 + 2x + x^2 polymul(c(1, 1), c(1, 1)) # returns c(1, 2, 1)# (1 + x) * (1 + x) = 1 + 2x + x^2 polymul(c(1, 1), c(1, 1)) # returns c(1, 2, 1)
Print method for callable_pp objects
## S3 method for class 'callable_pp' print(x, ...)## S3 method for class 'callable_pp' print(x, ...)
x |
A callable_pp object |
... |
Additional arguments |
Print method for callable spline
## S3 method for class 'callable_spline' print(x, ...)## S3 method for class 'callable_spline' print(x, ...)
x |
A callable spline object |
... |
Additional arguments |
Print method for non_callable_pp objects
## S3 method for class 'non_callable_pp' print(x, ...)## S3 method for class 'non_callable_pp' print(x, ...)
x |
A non_callable_pp object |
... |
Additional arguments |
Print method for non_callable_spline results
## S3 method for class 'non_callable_spline' print(x, ...)## S3 method for class 'non_callable_spline' print(x, ...)
x |
Result object from quantile_spline when callable=FALSE |
... |
Additional arguments |
This function provides a unified interface for quantile regression with B-splines of degrees 1 to 4, with shape constraints (monotonicity, convexity, third derivative).
quantile_spline( xtab, ytab, knot = NULL, tau = 0.5, degree = 3, monot = 0, convcons = 0, der3cons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE, callable = TRUE, type_reg = "quantile" )quantile_spline( xtab, ytab, knot = NULL, tau = 0.5, degree = 3, monot = 0, convcons = 0, der3cons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE, callable = TRUE, type_reg = "quantile" )
xtab |
Predictor vector (x) |
ytab |
Response vector (y) |
knot |
Knot vector or number of knots (quantiles are then used) |
tau |
Quantile (between 0 and 1) |
degree |
Spline degree: 1 (linear), 2 (quadratic), 3 (cubic), or 4 (quartic) |
monot |
Monotonicity constraint vector per interval: 1 = increasing, -1 = decreasing, 0 = unconstrained. If scalar, repeated. |
convcons |
Convexity constraint vector: For degree 1: not available (ignored) For degree 2: per interval (1 = convex, -1 = concave) For degree 3: per knot (1 = convex, -1 = concave) For degree 4: per interval (1 = convex, -1 = concave) |
der3cons |
Third derivative constraint: For degree 1: not available (third derivative = 0) For degree 2: not available (third derivative = 0) For degree 3: per interval (1 = positive, -1 = negative) For degree 4: per knot (1 = positive, -1 = negative) |
solver |
'CVXR' solver to use (default = 'CLARABEL') |
weight |
Observation weights (default = 1 for all) |
verbose |
logical; if TRUE, print progress messages |
callable |
render the final container object callable: 'y=Bspline(x)' or 'y=Bspline(x,Bvalues)' for evaluation at x |
type_reg |
'quantile' or 'mean_square' type of regression |
A list containing coefficients, degree, and knots
Abbes, A. (2025). Quantile regression with cubic polynomial splines under shape constraints with applications. Zenodo. doi:10.5281/zenodo.16999784
Karlin, S., & Studden, W. J. (1966). Tchebycheff Systems: With Applications in Analysis and Statistics. Interscience.
SplineLinearQuant, SplineQuadraticQuant,
SplineCubicQuant, SplineQuarticQuant
# Generate data x <- seq(0, 1, length.out = 100) y <- 2*x + sin(6*pi*x)/2 + rnorm(100, 0, 0.05) knot <- quantile(x, probs = seq(0, 1, length.out = 10)) # Linear spline (degree 1) with increasing constraint fit_lin <- quantile_spline(x, y, knot, tau = 0.5, degree = 1, monot = 1) # Quadratic spline (degree 2) with convexity constraint fit_quad <- quantile_spline(x, y, knot, tau = 0.5, degree = 2, convcons = 1) # Cubic spline (degree 3) with both constraints fit_cubic <- quantile_spline(x, y, knot, tau = 0.5, degree = 3, monot = 1, convcons = 1) # Quartic spline (degree 4) with all constraints fit_quart <- quantile_spline(x, y, knot, tau = 0.5, degree = 4, monot = 1, convcons = 1, der3cons = 1)# Generate data x <- seq(0, 1, length.out = 100) y <- 2*x + sin(6*pi*x)/2 + rnorm(100, 0, 0.05) knot <- quantile(x, probs = seq(0, 1, length.out = 10)) # Linear spline (degree 1) with increasing constraint fit_lin <- quantile_spline(x, y, knot, tau = 0.5, degree = 1, monot = 1) # Quadratic spline (degree 2) with convexity constraint fit_quad <- quantile_spline(x, y, knot, tau = 0.5, degree = 2, convcons = 1) # Cubic spline (degree 3) with both constraints fit_cubic <- quantile_spline(x, y, knot, tau = 0.5, degree = 3, monot = 1, convcons = 1) # Quartic spline (degree 4) with all constraints fit_quart <- quantile_spline(x, y, knot, tau = 0.5, degree = 4, monot = 1, convcons = 1, der3cons = 1)
Removes leading zeros from a polynomial coefficient vector.
reduce_pol(p, verbose = FALSE)reduce_pol(p, verbose = FALSE)
p |
Polynomial coefficient vector(coefficients are in decreasing order) |
verbose |
Boolean FALSE (default) or TRUE. |
Reduced vector (without leading zeros)
reduce_pol(c(0,0, 1, 1))reduce_pol(c(0,0, 1, 1))
Vérifier et configurer le solveur CVXR
setup_solver(solver = "OSQP", install = FALSE)setup_solver(solver = "OSQP", install = FALSE)
solver |
Nom du solveur ('OSQP', 'ECOS', 'SCS', 'CLARABEL') |
install |
Si TRUE, tente d'installer le solveur manquant |
Logical indiquant si le solveur est disponible
Displays the equation of a polynomial in a given basis
show_poly(obj, a = 0, b = 0, digits = 4)show_poly(obj, a = 0, b = 0, digits = 4)
obj |
Polynomial object (coeff vector), decreasing power |
a |
: the base in which the coefficients are given is (x-a)^i, default 0 for canonical |
b |
: the base for output is (x-b)^i, default b=0 |
digits |
Nombre de chiffres significatifs à afficher |
the polynomial written on the base (x-b)^i
# Simple polynomial p <- c(3, -2, 1) # 3 - 2x + x^2 show_poly(p) # or show_poly(p,a=0, b=0) # base not zero p <- c(3, -2, 1) # 3 - 2(x-2) + (x-2)^2 show_poly(p, a=2, b=2)# Simple polynomial p <- c(3, -2, 1) # 3 - 2x + x^2 show_poly(p) # or show_poly(p,a=0, b=0) # base not zero p <- c(3, -2, 1) # 3 - 2(x-2) + (x-2)^2 show_poly(p, a=2, b=2)
Display a Piecewise Polynomial (PP) object as readable equations
show_pp(ppol, local = TRUE, digits = 4, verbose = FALSE)show_pp(ppol, local = TRUE, digits = 4, verbose = FALSE)
ppol |
A PP object (callable_pp, non_callable_pp) or spline (callable_spline, non_callable_spline) |
local |
Logical. If TRUE (default), uses the local basis (x-a)^i. If FALSE, uses the canonical basis 1, x, x², ... |
digits |
Number of significant digits for display (default: 4) |
verbose |
Logical. If TRUE, displays additional information |
This function takes a PP object (callable or non-callable) or a spline and displays the polynomial equations on each interval. Polynomials can be displayed in the canonical basis (1, x, x², ...) or in the local basis (1, (x-t_k), (x-t_k)², ...) centered at each knot t_k.
A matrix or vector containing the formatted equations. If a single interval, returns a character vector. If multiple intervals, returns a matrix with each row: [interval, equation].
## Not run: # Example with a simple PP knot <- c(0, 0.5, 1) coeff <- matrix(c(1, 2, 0.5, 0, 1, -1), nrow = 2, ncol = 3, byrow = TRUE) pp <- makpp(coeff, knot) show_pp(pp, local = FALSE) # Output: # [0.000, 0.500] 0.5x^2 + 2x + 1 # [0.500, 1.000] -1x^2 + 1x + 0 # With local basis show_pp(pp, local = TRUE) # Output: # [0.000, 0.500] 0.5(x-0)^2 + 2(x-0) + 1 # [0.500, 1.000] -1(x-0.5)^2 + 1(x-0.5) + 0 # With a spline sn <- c(0,0,0,0,1,2,3,4,5,5,5,5) basis <- Bspline_base(sn, degree = 3) basis$coeff <- runif(basis$n_splines) show_pp(basis, local = TRUE, verbose = TRUE) ## End(Not run)## Not run: # Example with a simple PP knot <- c(0, 0.5, 1) coeff <- matrix(c(1, 2, 0.5, 0, 1, -1), nrow = 2, ncol = 3, byrow = TRUE) pp <- makpp(coeff, knot) show_pp(pp, local = FALSE) # Output: # [0.000, 0.500] 0.5x^2 + 2x + 1 # [0.500, 1.000] -1x^2 + 1x + 0 # With local basis show_pp(pp, local = TRUE) # Output: # [0.000, 0.500] 0.5(x-0)^2 + 2(x-0) + 1 # [0.500, 1.000] -1(x-0.5)^2 + 1(x-0.5) + 0 # With a spline sn <- c(0,0,0,0,1,2,3,4,5,5,5,5) basis <- Bspline_base(sn, degree = 3) basis$coeff <- runif(basis$n_splines) show_pp(basis, local = TRUE, verbose = TRUE) ## End(Not run)
Computes derivative values of a B-spline at knot (efficient because it directly uses polynomial coefficients).
Spline_der_knot(Bsbase, der = 1)Spline_der_knot(Bsbase, der = 1)
Bsbase |
Object returned by |
der |
Derivative order (default = 1) |
Matrix of derivative values (n_splines x n_knot)
Evaluates a spline (linear combination of B-splines) at given points.
spline_eval(Bspline, x_values = NULL, der = 0, Bvalues = NULL, verbose = FALSE)spline_eval(Bspline, x_values = NULL, der = 0, Bvalues = NULL, verbose = FALSE)
Bspline |
Spline object (list with coefficients on the 'Bspline' basis, degree, extended knot) A 'Bspline' can also be rendered callable witk 'make_spline(BSpline)' |
x_values |
Vector of evaluation points. By default, evaluation is calculated at the knots |
der |
integer 0 (defalut)...degree is the order of derivative |
Bvalues |
: the values of the 'Bspline' basis evaluated at the values x this increases the speed by avoiding re-doing the same calculations of the basis for each spline with the same knots. |
verbose |
boollean, if TRUE output more messages |
vector of same length as x_values, with Spline values at the requested points
{ # Create and evaluate a spline # This function is also used when a 'Bspline' object is rendered callable as a function # with make_spline() tn<-c(0,1,2,3,4,5) x_values<-seq(0,5,length=100) Bspline=list(degree=3, knot=tn,coeffs=runif(length(tn)+3-1)) y <- spline_eval(Bspline, x_values) #alternatively compute the base before to optimize if needed sn <- c(0,0,0,0,1,2,3,4,5,5,5,5) Bsbase <- Bspline_base(sn, degree=3) Bvalues <-bs_direct(Bsbase,x_values) y <- spline_eval(Bspline=Bspline,x_values=x_values, Bvalues=Bvalues )}{ # Create and evaluate a spline # This function is also used when a 'Bspline' object is rendered callable as a function # with make_spline() tn<-c(0,1,2,3,4,5) x_values<-seq(0,5,length=100) Bspline=list(degree=3, knot=tn,coeffs=runif(length(tn)+3-1)) y <- spline_eval(Bspline, x_values) #alternatively compute the base before to optimize if needed sn <- c(0,0,0,0,1,2,3,4,5,5,5,5) Bsbase <- Bspline_base(sn, degree=3) Bvalues <-bs_direct(Bsbase,x_values) y <- spline_eval(Bspline=Bspline,x_values=x_values, Bvalues=Bvalues )}
' Performs quantile/mean regression using constant B-splines with monotonicity constraints. No solver is needed, since for the degree 0, the B-splines in the basis are independent piece-wise constants.
SplineConstantQuant( xtab, ytab, knot = NULL, tau = 0.5, monot = 0, weight = NULL, verbose = FALSE, type_reg = "quantile" )SplineConstantQuant( xtab, ytab, knot = NULL, tau = 0.5, monot = 0, weight = NULL, verbose = FALSE, type_reg = "quantile" )
xtab |
Predictor vector (x) |
ytab |
Response vector (y) |
knot |
Knot vector or number of knots |
tau |
Quantile (between 0 and 1) |
monot |
Monotonicity constraint vector: Monotonicity is expressed at knots 1 || k>0 = increasing, -1 ||k<0 = decreasing, 0 = unconstrained. kn-1 constraints are taken into account, kn=length(knot)-1 If monot is a single number, it is repaeated as uniform coonstraint. if length(monot)<kn-1 then it is completed with zeros. |
weight |
Observation weights (default = 1 for all) |
verbose |
logical; if TRUE, print progress messages |
type_reg |
'quantile' or 'mean_square' type of regression i.e form of the objective. |
A list containing coefficients, degree, and knots
This is a convenience wrapper for SplineLinearQuant.
SplineConstQuantRegBs1( xtab, ytab, knot, tau, monot = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE )SplineConstQuantRegBs1( xtab, ytab, knot, tau, monot = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE )
xtab |
Predictor vector (x) |
ytab |
Response vector (y) |
knot |
Knot vector or number of knots |
tau |
Quantile (between 0 and 1) |
monot |
Monotonicity constraint vector per interval: 1 = increasing, -1 = decreasing, 0 = unconstrained |
solver |
CVXR solver to use (default = "OSQP") |
weight |
Observation weights (default = 1 for all) |
verbose |
logical; if TRUE, print progress messages |
Same as SplineLinearQuant
Wrapper function for quadratic spline quantile regression Previous version notation style This is a convenience wrapper for SplineQuadraticQuant.
SplineConstQuantRegBs2( xtab, ytab, knot, tau, monot = 0, convcons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE )SplineConstQuantRegBs2( xtab, ytab, knot, tau, monot = 0, convcons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE )
xtab |
Predictor vector (x) |
ytab |
Response vector (y) |
knot |
Knot vector or number of knots |
tau |
Quantile (between 0 and 1) |
monot |
Monotonicity constraint vector per interval: 1 = increasing, -1 = decreasing, 0 = unconstrained. Although constraints are set at knots; we apply them on each interval, at both extremities. kn+1 knots, kn constraints taken into account. |
convcons |
Convexity constraint vector per interval: 1 = convex, -1 = concave, 0 = unconstrained. kn constraints are considered for kn+1 knots. |
solver |
'CVXR' solver to use (default = 'CLARABEL') |
weight |
Observation weights (default = 1 for all) |
verbose |
logical; if TRUE, print progress messages |
Same as SplineQuadraticQuant
This is a convenience wrapper for SplineCubicQuant with convention of previous versions SplineConstQuantRegBs3.
SplineConstQuantRegBs3( xtab, ytab, knot, tau, monot = 0, convcons = 0, der3cons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE )SplineConstQuantRegBs3( xtab, ytab, knot, tau, monot = 0, convcons = 0, der3cons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE )
xtab |
Predictor vector (x) |
ytab |
Response vector (y) |
knot |
Knot vector or number of knot (quantiles are then used) |
tau |
Quantile (between 0 and 1) |
monot |
Monotonicity constraint vector per interval: 1 = increasing, -1 = decreasing, 0 = unconstrained. If scalar, repeated. |
convcons |
Convexity constraint vector per knot: 1 = convex, -1 = concave, 0 = unconstrained. If scalar, repeated. |
der3cons |
Constraint on the 3rd derivative (on esach intervall: -1: negative, 0: no constraint, 1: positive constraint |
solver |
'CVXR' solver to use (default = 'CLARABEL') |
weight |
Observation weights (default = 1 for all) |
verbose |
boolean FALSE (default) or TRUE. |
Same as SplineCubicQuant
This is a convenience wrapper for SplineQuarticQuant that follows the same naming convention as SplineConstQuantRegBs3.
SplineConstQuantRegBs4( xtab, ytab, knot, tau, monot = 0, convcons = 0, der3cons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE )SplineConstQuantRegBs4( xtab, ytab, knot, tau, monot = 0, convcons = 0, der3cons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE )
xtab |
Predictor vector (x) |
ytab |
Response vector (y) |
knot |
Knot vector or number of knot |
tau |
Quantile (between 0 and 1) |
monot |
Monotonicity constraint vector per interval: 1 = increasing, -1 = decreasing, 0 = unconstrained |
convcons |
Convexity constraint vector per interval: 1 = convex, -1 = concave, 0 = unconstrained |
der3cons |
Third derivative constraint vector at knot: 1 = positive third derivative, -1 = negative, 0 = unconstrained |
solver |
'CVXR' solver to use (default = "OSQP") |
weight |
Observation weights (default = 1 for all) |
verbose |
Logical; if TRUE, print progress messages |
Same as SplineQuarticQuant
Constrained quantile regression with cubic splines Performs quantile regression using cubic B-splines, with optional monotonicity constraints (via Karlin-Studden) and convexity constraints.
SplineCubicQuant( xtab, ytab, knot = NULL, tau = 0.5, monot = 0, convcons = 0, der3cons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE, type_reg = "quantile" )SplineCubicQuant( xtab, ytab, knot = NULL, tau = 0.5, monot = 0, convcons = 0, der3cons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE, type_reg = "quantile" )
xtab |
Predictor vector (x) |
ytab |
Response vector (y) |
knot |
Knot vector or number of knot (quantiles are then used) |
tau |
Quantile (between 0 and 1) |
monot |
Monotonicity constraint vector per interval: 1 = increasing, -1 = decreasing, 0 = unconstrained. If scalar, repeated. |
convcons |
Convexity constraint vector per knot: 1 = convex, -1 = concave, 0 = unconstrained. If scalar, repeated. |
der3cons |
Constraint on the 3rd derivative (on esach intervall: -1: negative, 0: no constraint, 1: positive constraint |
solver |
'CVXR' solver to use (default = 'CLARABEL') |
weight |
Observation weights (default = 1 for all) |
verbose |
boolean FALSE (default) or TRUE. |
type_reg |
'quantile' or 'mean_square' type of regression |
A list containing:
coefficients |
B-spline coefficients (including y mean) |
degree |
Spline degree (always 3) |
ext_knot |
ext_knot vector used |
int_knot |
knot vector |
Abbes, A. (2025). Quantile regression with cubic polynomial splines under shape constraints with applications . Zenodo. doi:10.5281/zenodo.17427913
de Boor, C. (1978). A Practical Guide to Splines. Springer-Verlag. doi:10.1007/978-1-4612-6333-3
Karlin, S., & Studden, W. J. (1966). Tchebycheff Systems: With Applications in Analysis and Statistics. Interscience.
Koenker, R. G. (1978). Regression Quantiles. Econometrica, 46(1), 33-50. doi:10.2307/1913643
Koenker, R. (2025). quantreg: Quantile Regression. R package version 5.99. https://CRAN.R-project.org/package=quantreg
Ng, P., & Maechler, M. (2024). cobs: Constrained B-Splines. R package version 1.3-8. https://CRAN.R-project.org/package=cobs
Related 'R' packages:
quantreg - Quantile regression with linear programming
cobs - Constrained B-sines (linear and quadratic only)
Other implementations:
MATLAB/Python versions: https://github.com/alexandreabbes/Constrained-Quantile-Regression-with-cubic-splines
Python package : https://pypi.org/project/BsplineQuantRegpy/
#optional set.seed(42) x <- seq(0, 1, length=100) y <- 2*x + sin(6*pi*x)/2 + rnorm(100, 0, 0.05) knot <- as.numeric(quantile(x, probs=seq(0,1,length.out=10))) # Median quantile regression without constraints fit <- SplineConstQuantRegBs3(x, y, knot, tau=0.5) # With increasing monotonicity constraint fit_monot <- SplineConstQuantRegBs3(x, y, knot, tau=0.5, monot=1) # With convexity constraint fit_convex <- SplineConstQuantRegBs3(x, y, knot, tau=0.5, convcons=1)#optional set.seed(42) x <- seq(0, 1, length=100) y <- 2*x + sin(6*pi*x)/2 + rnorm(100, 0, 0.05) knot <- as.numeric(quantile(x, probs=seq(0,1,length.out=10))) # Median quantile regression without constraints fit <- SplineConstQuantRegBs3(x, y, knot, tau=0.5) # With increasing monotonicity constraint fit_monot <- SplineConstQuantRegBs3(x, y, knot, tau=0.5, monot=1) # With convexity constraint fit_convex <- SplineConstQuantRegBs3(x, y, knot, tau=0.5, convcons=1)
Performs quantile regression using linear B-splines with monotonicity constraints. For linear splines, the derivative is constant on each interval, so monotonicity is a simple linear constraint on the derivative.
SplineLinearQuant( xtab, ytab, knot = NULL, tau = 0.5, monot = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE, type_reg = "quantile" )SplineLinearQuant( xtab, ytab, knot = NULL, tau = 0.5, monot = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE, type_reg = "quantile" )
xtab |
Predictor vector (x) |
ytab |
Response vector (y) |
knot |
Knot vector or number of knots |
tau |
Quantile (between 0 and 1) |
monot |
Monotonicity constraint vector per interval: 1 = increasing, -1 = decreasing, 0 = unconstrained |
solver |
CVXR solver to use (default = "OSQP") |
weight |
Observation weights (default = 1 for all) |
verbose |
logical; if TRUE, print progress messages |
type_reg |
'quantile' or 'mean_square' type of regression i.e form of the objective. |
A list containing coefficients, degree, and knots
Performs quantile regression using quartic (degree 4) B-splines with monotonicity (Karlin-Studden constraints on the cubic derivative), convexity (Karlin-Studden constraints on the quadratic second derivative), and third derivative constraints (linear at knot).
SplinePolynQuant( xtab, ytab, knot = NULL, convcons = 0, der3cons = 0, tau = 0.5, degree = 5, solver = "CLARABEL", weight = NULL, verbose = FALSE, type_reg = "quantile" )SplinePolynQuant( xtab, ytab, knot = NULL, convcons = 0, der3cons = 0, tau = 0.5, degree = 5, solver = "CLARABEL", weight = NULL, verbose = FALSE, type_reg = "quantile" )
xtab |
Predictor vector (x) |
ytab |
Response vector (y) |
knot |
Knot vector or number of knot |
convcons |
not yet implemented Convexity constraint vector per interval: 1 = convex, -1 = concave, 0 = unconstrained |
der3cons |
Not yet implemented Third derivative constraint vector at knot: 1 = positive third derivative, -1 = negative, 0 = unconstrained |
tau |
Quantile (between 0 and 1) |
degree |
the degree of the polynomial spline degree>=5 |
solver |
'CVXR' solver to use (default = "OSQP") |
weight |
Observation weights (default = 1 for all) |
verbose |
Logical; if TRUE, print progress messages |
type_reg |
'quantile' or 'mean_square' type of regression |
A list containing coefficients, degree, and knot
Performs quantile regression using quadratic B-splines with: - Monotonicity: Karlin-Studden constraints on the derivative (linear) - Convexity: Karlin-Studden constraints on the second derivative (constant)
SplineQuadraticQuant( xtab, ytab, knot = NULL, tau = 0.5, monot = 0, convcons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE, type_reg = "quantile" )SplineQuadraticQuant( xtab, ytab, knot = NULL, tau = 0.5, monot = 0, convcons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE, type_reg = "quantile" )
xtab |
Predictor vector (x) |
ytab |
Response vector (y) |
knot |
Knot vector or number of knots |
tau |
Quantile (between 0 and 1) |
monot |
Monotonicity constraint vector per interval: 1 = increasing, -1 = decreasing, 0 = unconstrained. Although constraints are set at knots; we apply them on each interval, at both extremities. kn+1 knots, kn constraints taken into account. |
convcons |
Convexity constraint vector per interval: 1 = convex, -1 = concave, 0 = unconstrained. kn constraints are considered for kn+1 knots. |
solver |
'CVXR' solver to use (default = 'CLARABEL') |
weight |
Observation weights (default = 1 for all) |
verbose |
logical; if TRUE, print progress messages |
type_reg |
'quantile' or 'mean_square' type of regression, |
A list containing coefficients, degree, and knots
Performs quantile regression using quartic (degree 4) B-splines with monotonicity (Karlin-Studden constraints on the cubic derivative), convexity (Karlin-Studden constraints on the quadratic second derivative), and third derivative constraints (linear at knot).
SplineQuarticQuant( xtab, ytab, knot = NULL, tau = 0.5, monot = 0, convcons = 0, der3cons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE, type_reg = "quantile" )SplineQuarticQuant( xtab, ytab, knot = NULL, tau = 0.5, monot = 0, convcons = 0, der3cons = 0, solver = "CLARABEL", weight = NULL, verbose = FALSE, type_reg = "quantile" )
xtab |
Predictor vector (x) |
ytab |
Response vector (y) |
knot |
Knot vector or number of knot |
tau |
Quantile (between 0 and 1) |
monot |
Monotonicity constraint vector per interval: 1 = increasing, -1 = decreasing, 0 = unconstrained |
convcons |
Convexity constraint vector per interval: 1 = convex, -1 = concave, 0 = unconstrained |
der3cons |
Third derivative constraint vector at knot: 1 = positive third derivative, -1 = negative, 0 = unconstrained |
solver |
'CVXR' solver to use (default = "OSQP") |
weight |
Observation weights (default = 1 for all) |
verbose |
Logical; if TRUE, print progress messages |
type_reg |
'quantile' or 'mean_square' type of regression |
A list containing coefficients, degree, and knot
Runs quantile regression tests with and without constraints, and displays results. Demo function. This example also shows that solution may be evaluated (extrapolation) out of the knot range
test_karlin_simple(degree = 3, seed = NULL, verbose = FALSE)test_karlin_simple(degree = 3, seed = NULL, verbose = FALSE)
degree |
1, 2, 3 or 4 (default 3). The degree of the regression spline. |
seed |
(default=NULL) value for the random generator. |
verbose |
boolean FALSE (default) or TRUE. |
Visualize a B-spline functions basis Visualize a B-spline basis Plots all basis functions of a B-spline basis with improved styling.
view_basis(BB, x_values = 0, main = NULL, view_knot = TRUE, add_knot = NULL)view_basis(BB, x_values = 0, main = NULL, view_knot = TRUE, add_knot = NULL)
BB |
Object returned by |
x_values |
Vector of evaluation points for plotting. If length is 1 (default = 0), generates 200 points in the knot range. |
main |
Title to print over the plot. |
view_knot |
Logical; if TRUE, adds vertical lines at knot positions. |
add_knot |
logical, same value as 'view_knot' for retro compatibility |
No return value, called for side effects (generates a plot)