| Title: | Generalized Additive Models for Bivariate Conditional Dependence Structures and Vine Copulas |
|---|---|
| Description: | Implementation of various inference and simulation tools to apply generalized additive models to bivariate dependence structures and non-simplified vine copulas. |
| Authors: | Thomas Nagler [aut], Thibault Vatter [aut, cre] |
| Maintainer: | Thibault Vatter <[email protected]> |
| License: | GPL-3 |
| Version: | 0.0-8 |
| Built: | 2026-05-18 10:26:31 UTC |
| Source: | https://github.com/tvatter/gamcopula |
This package implements inference and simulation tools to apply generalized additive models to bivariate dependence structures and vine copulas.
More details can be found in Vatter and Chavez-Demoulin (2015) and Vatter and Nagler (2016).
| Package: | gamCopula |
| Type: | Package |
| Version: | 0.0-8 |
| Date: | 2025-04-02 |
| License: | GPL-3 |
Thibault Vatter and Thomas Nagler
Maintainer: Thibault Vatter [email protected]
Aas, K., C. Czado, A. Frigessi, and H. Bakken (2009) Pair-copula constructions of multiple dependence. Insurance: Mathematics and Economics, 44(2), 182–198.
Brechmann, E. C., C. Czado, and K. Aas (2012) Truncated regular vines in high dimensions with applications to financial data. Canadian Journal of Statistics, 40(1), 68–85.
Dissmann, J. F., E. C. Brechmann, C. Czado, and D. Kurowicka (2013) Selecting and estimating regular vine copulae and application to financial returns. Computational Statistics & Data Analysis, 59(1), 52–69.
Vatter, T. and V. Chavez-Demoulin (2015) Generalized Additive Models for Conditional Dependence Structures. Journal of Multivariate Analysis, 141, 147–167.
Vatter, T. and T. Nagler (2016) Generalized additive models for non-simplified pair-copula constructions. https://arxiv.org/abs/1608.01593
Wood, S. N. (2004) Stable and efficient multiple smoothing parameter estimation for generalized additive models. Journal of the American Statistical Association, 99, 673–686.
Wood, S. N. (2006) Generalized Additive Models: an introduction with R. Chapman and Hall/CRC.
The present package heavily relies on the mgcv and VineCopula packages, as it basically extends and mixes both of them.
##### A gamBiCop example require(copula) require(mgcv) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 5e2 rho <- 0.5 fam <- 1 ### A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ### Display the calibration surface par(mfrow = c(1, 3), pty = "s", mar = c(1, 1, 4, 1)) u <- seq(0, 1, length.out = 100) sel <- matrix(c(1, 1, 2, 2, 3, 3), ncol = 2) jet.colors <- colorRamp(c( "#00007F", "blue", "#007FFF", "cyan", "#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000" )) jet <- function(x) { rgb(jet.colors(exp(x / 3) / (1 + exp(x / 3))), maxColorValue = 255 ) } for (k in 1:3) { tmp <- outer(u, u, function(x, y) { eta0 + calib.surf[[sel[k, 1]]](x) + calib.surf[[sel[k, 2]]](y) }) persp(u, u, tmp, border = NA, theta = 60, phi = 30, zlab = "", col = matrix(jet(tmp), nrow = 100), xlab = paste("X", sel[k, 1], sep = ""), ylab = paste("X", sel[k, 2], sep = ""), main = paste("eta0+f", sel[k, 1], "(X", sel[k, 1], ") +f", sel[k, 2], "(X", sel[k, 2], ")", sep = "" ) ) } ### 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) ### U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) { f(x) }, calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ### Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ### Display the data dev.off() plot(data[, "u1"], data[, "u2"], xlab = "U1", ylab = "U2") ### Model fit with a basis size (arguably) too small ### and unpenalized cubic spines pen <- FALSE basis0 <- c(3, 4, 4) formula <- ~ s(x1, k = basis0[1], bs = "cr", fx = !pen) + s(x2, k = basis0[2], bs = "cr", fx = !pen) + s(x3, k = basis0[3], bs = "cr", fx = !pen) system.time(fit0 <- gamBiCopFit(data, formula, fam)) ### Model fit with a better basis size and penalized cubic splines (via min GCV) pen <- TRUE basis1 <- c(3, 10, 10) formula <- ~ s(x1, k = basis1[1], bs = "cr", fx = !pen) + s(x2, k = basis1[2], bs = "cr", fx = !pen) + s(x3, k = basis1[3], bs = "cr", fx = !pen) system.time(fit1 <- gamBiCopFit(data, formula, fam)) ### Extract the gamBiCop objects and show various methods (res <- sapply(list(fit0, fit1), function(fit) { fit$res })) metds <- list("logLik" = logLik, "AIC" = AIC, "BIC" = BIC, "EDF" = EDF) lapply(res, function(x) sapply(metds, function(f) f(x))) ### Comparison between fitted, true smooth and spline approximation for each ### true smooth function for the two basis sizes fitted <- lapply(res, function(x) { gamBiCopPredict(x, data.frame(x1 = u, x2 = u, x3 = u), type = "terms" )$calib }) true <- vector("list", 3) for (i in 1:3) { y <- eta0 + calib.surf[[i]](u) true[[i]]$true <- y - eta0 temp <- gam(y ~ s(u, k = basis0[i], bs = "cr", fx = TRUE)) true[[i]]$approx <- predict.gam(temp, type = "terms") temp <- gam(y ~ s(u, k = basis1[i], bs = "cr", fx = FALSE)) true[[i]]$approx2 <- predict.gam(temp, type = "terms") } ### Display results par(mfrow = c(1, 3), pty = "s") yy <- range(true, fitted) yy[1] <- yy[1] * 1.5 for (k in 1:3) { plot(u, true[[k]]$true, type = "l", ylim = yy, xlab = paste("Covariate", k), ylab = paste("Smooth", k) ) lines(u, true[[k]]$approx, col = "red", lty = 2) lines(u, fitted[[1]][, k], col = "red") lines(u, fitted[[2]][, k], col = "green") lines(u, true[[k]]$approx2, col = "green", lty = 2) legend("bottomleft", cex = 0.6, lty = c(1, 1, 2, 1, 2), c("True", "Fitted", "Appox 1", "Fitted 2", "Approx 2"), col = c("black", "red", "red", "green", "green") ) } ###### A gamVine example set.seed(0) ### Simulation parameters ## Sample size n <- 1e3 ## Copula families familyset <- c(1:2, 301:304, 401:404) ## Define a 4-dimensional R-vine tree structure matrix d <- 4 Matrix <- c(2, 3, 4, 1, 0, 3, 4, 1, 0, 0, 4, 1, 0, 0, 0, 1) Matrix <- matrix(Matrix, d, d) nnames <- paste("X", 1:d, sep = "") ### A function factory eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ### Create the model ## Define gam-vine model list count <- 1 model <- vector(mode = "list", length = d * (d - 1) / 2) sel <- seq(d, d^2 - d, by = d) ## First tree for (i in 1:(d - 1)) { # Select a copula family family <- sample(familyset, 1) model[[count]]$family <- family # Use the canonical link and a randomly generated parameter if (is.element(family, c(1, 2))) { model[[count]]$par <- tanh(rnorm(1) / 2) if (family == 2) { model[[count]]$par2 <- 2 + exp(rnorm(1)) } } else { if (is.element(family, c(401:404))) { rr <- rnorm(1) model[[count]]$par <- sign(rr) * (1 + abs(rr)) } else { model[[count]]$par <- rnorm(1) } model[[count]]$par2 <- 0 } count <- count + 1 } ## A dummy dataset data <- data.frame(u1 = runif(1e2), u2 = runif(1e2), matrix(runif(1e2 * d), 1e2, d)) ## Trees 2 to (d-1) for (j in 2:(d - 1)) { for (i in 1:(d - j)) { # Select a copula family family <- sample(familyset, 1) # Select the conditiong set and create a model formula cond <- nnames[sort(Matrix[(d - j + 2):d, i])] tmpform <- paste("~", paste(paste("s(", cond, ", k=10, bs='cr')", sep = "" ), collapse = " + ")) l <- length(cond) temp <- sample(3, l, replace = TRUE) # Spline approximation of the true function m <- 1e2 x <- matrix(seq(0, 1, length.out = m), nrow = m, ncol = 1) if (l != 1) { tmp.fct <- paste("function(x){eta0+", paste(sapply(1:l, function(x) { paste("calib.surf[[", temp[x], "]](x[", x, "])", sep = "" ) }), collapse = "+"), "}", sep = "" ) tmp.fct <- eval(parse(text = tmp.fct)) x <- eval(parse(text = paste0("expand.grid(", paste0(rep("x", l), collapse = ","), ")", collapse = "" ))) y <- apply(x, 1, tmp.fct) } else { tmp.fct <- function(x) eta0 + calib.surf[[temp]](x) colnames(x) <- cond y <- tmp.fct(x) } # Estimate the gam model form <- as.formula(paste0("y", tmpform)) dd <- data.frame(y, x) names(dd) <- c("y", cond) b <- gam(form, data = dd) # plot(x[,1],(y-fitted(b))/y) # Create a dummy gamBiCop object tmp <- gamBiCopFit(data = data, formula = form, family = 1, n.iters = 1)$res # Update the copula family and the model coefficients attr(tmp, "model")$coefficients <- coefficients(b) attr(tmp, "model")$smooth <- b$smooth attr(tmp, "family") <- family if (family == 2) { attr(tmp, "par2") <- 2 + exp(rnorm(1)) } model[[count]] <- tmp count <- count + 1 } } ## Create the gamVineCopula object GVC <- gamVine(Matrix = Matrix, model = model, names = nnames) print(GVC) # ## Not run: ### Simulate and fit the model sim <- gamVineSimulate(n, GVC) fitGVC <- gamVineSeqFit(sim, GVC, verbose = TRUE) fitGVC2 <- gamVineCopSelect(sim, Matrix, verbose = TRUE) ### Plot the results par(mfrow = c(3, 4)) plot(GVC, ylim = c(-2.5, 2.5)) plot(fitGVC, ylim = c(-2.5, 2.5)) plot(fitGVC2, ylim = c(-2.5, 2.5)) ## End(Not run)##### A gamBiCop example require(copula) require(mgcv) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 5e2 rho <- 0.5 fam <- 1 ### A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ### Display the calibration surface par(mfrow = c(1, 3), pty = "s", mar = c(1, 1, 4, 1)) u <- seq(0, 1, length.out = 100) sel <- matrix(c(1, 1, 2, 2, 3, 3), ncol = 2) jet.colors <- colorRamp(c( "#00007F", "blue", "#007FFF", "cyan", "#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000" )) jet <- function(x) { rgb(jet.colors(exp(x / 3) / (1 + exp(x / 3))), maxColorValue = 255 ) } for (k in 1:3) { tmp <- outer(u, u, function(x, y) { eta0 + calib.surf[[sel[k, 1]]](x) + calib.surf[[sel[k, 2]]](y) }) persp(u, u, tmp, border = NA, theta = 60, phi = 30, zlab = "", col = matrix(jet(tmp), nrow = 100), xlab = paste("X", sel[k, 1], sep = ""), ylab = paste("X", sel[k, 2], sep = ""), main = paste("eta0+f", sel[k, 1], "(X", sel[k, 1], ") +f", sel[k, 2], "(X", sel[k, 2], ")", sep = "" ) ) } ### 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) ### U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) { f(x) }, calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ### Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ### Display the data dev.off() plot(data[, "u1"], data[, "u2"], xlab = "U1", ylab = "U2") ### Model fit with a basis size (arguably) too small ### and unpenalized cubic spines pen <- FALSE basis0 <- c(3, 4, 4) formula <- ~ s(x1, k = basis0[1], bs = "cr", fx = !pen) + s(x2, k = basis0[2], bs = "cr", fx = !pen) + s(x3, k = basis0[3], bs = "cr", fx = !pen) system.time(fit0 <- gamBiCopFit(data, formula, fam)) ### Model fit with a better basis size and penalized cubic splines (via min GCV) pen <- TRUE basis1 <- c(3, 10, 10) formula <- ~ s(x1, k = basis1[1], bs = "cr", fx = !pen) + s(x2, k = basis1[2], bs = "cr", fx = !pen) + s(x3, k = basis1[3], bs = "cr", fx = !pen) system.time(fit1 <- gamBiCopFit(data, formula, fam)) ### Extract the gamBiCop objects and show various methods (res <- sapply(list(fit0, fit1), function(fit) { fit$res })) metds <- list("logLik" = logLik, "AIC" = AIC, "BIC" = BIC, "EDF" = EDF) lapply(res, function(x) sapply(metds, function(f) f(x))) ### Comparison between fitted, true smooth and spline approximation for each ### true smooth function for the two basis sizes fitted <- lapply(res, function(x) { gamBiCopPredict(x, data.frame(x1 = u, x2 = u, x3 = u), type = "terms" )$calib }) true <- vector("list", 3) for (i in 1:3) { y <- eta0 + calib.surf[[i]](u) true[[i]]$true <- y - eta0 temp <- gam(y ~ s(u, k = basis0[i], bs = "cr", fx = TRUE)) true[[i]]$approx <- predict.gam(temp, type = "terms") temp <- gam(y ~ s(u, k = basis1[i], bs = "cr", fx = FALSE)) true[[i]]$approx2 <- predict.gam(temp, type = "terms") } ### Display results par(mfrow = c(1, 3), pty = "s") yy <- range(true, fitted) yy[1] <- yy[1] * 1.5 for (k in 1:3) { plot(u, true[[k]]$true, type = "l", ylim = yy, xlab = paste("Covariate", k), ylab = paste("Smooth", k) ) lines(u, true[[k]]$approx, col = "red", lty = 2) lines(u, fitted[[1]][, k], col = "red") lines(u, fitted[[2]][, k], col = "green") lines(u, true[[k]]$approx2, col = "green", lty = 2) legend("bottomleft", cex = 0.6, lty = c(1, 1, 2, 1, 2), c("True", "Fitted", "Appox 1", "Fitted 2", "Approx 2"), col = c("black", "red", "red", "green", "green") ) } ###### A gamVine example set.seed(0) ### Simulation parameters ## Sample size n <- 1e3 ## Copula families familyset <- c(1:2, 301:304, 401:404) ## Define a 4-dimensional R-vine tree structure matrix d <- 4 Matrix <- c(2, 3, 4, 1, 0, 3, 4, 1, 0, 0, 4, 1, 0, 0, 0, 1) Matrix <- matrix(Matrix, d, d) nnames <- paste("X", 1:d, sep = "") ### A function factory eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ### Create the model ## Define gam-vine model list count <- 1 model <- vector(mode = "list", length = d * (d - 1) / 2) sel <- seq(d, d^2 - d, by = d) ## First tree for (i in 1:(d - 1)) { # Select a copula family family <- sample(familyset, 1) model[[count]]$family <- family # Use the canonical link and a randomly generated parameter if (is.element(family, c(1, 2))) { model[[count]]$par <- tanh(rnorm(1) / 2) if (family == 2) { model[[count]]$par2 <- 2 + exp(rnorm(1)) } } else { if (is.element(family, c(401:404))) { rr <- rnorm(1) model[[count]]$par <- sign(rr) * (1 + abs(rr)) } else { model[[count]]$par <- rnorm(1) } model[[count]]$par2 <- 0 } count <- count + 1 } ## A dummy dataset data <- data.frame(u1 = runif(1e2), u2 = runif(1e2), matrix(runif(1e2 * d), 1e2, d)) ## Trees 2 to (d-1) for (j in 2:(d - 1)) { for (i in 1:(d - j)) { # Select a copula family family <- sample(familyset, 1) # Select the conditiong set and create a model formula cond <- nnames[sort(Matrix[(d - j + 2):d, i])] tmpform <- paste("~", paste(paste("s(", cond, ", k=10, bs='cr')", sep = "" ), collapse = " + ")) l <- length(cond) temp <- sample(3, l, replace = TRUE) # Spline approximation of the true function m <- 1e2 x <- matrix(seq(0, 1, length.out = m), nrow = m, ncol = 1) if (l != 1) { tmp.fct <- paste("function(x){eta0+", paste(sapply(1:l, function(x) { paste("calib.surf[[", temp[x], "]](x[", x, "])", sep = "" ) }), collapse = "+"), "}", sep = "" ) tmp.fct <- eval(parse(text = tmp.fct)) x <- eval(parse(text = paste0("expand.grid(", paste0(rep("x", l), collapse = ","), ")", collapse = "" ))) y <- apply(x, 1, tmp.fct) } else { tmp.fct <- function(x) eta0 + calib.surf[[temp]](x) colnames(x) <- cond y <- tmp.fct(x) } # Estimate the gam model form <- as.formula(paste0("y", tmpform)) dd <- data.frame(y, x) names(dd) <- c("y", cond) b <- gam(form, data = dd) # plot(x[,1],(y-fitted(b))/y) # Create a dummy gamBiCop object tmp <- gamBiCopFit(data = data, formula = form, family = 1, n.iters = 1)$res # Update the copula family and the model coefficients attr(tmp, "model")$coefficients <- coefficients(b) attr(tmp, "model")$smooth <- b$smooth attr(tmp, "family") <- family if (family == 2) { attr(tmp, "par2") <- 2 + exp(rnorm(1)) } model[[count]] <- tmp count <- count + 1 } } ## Create the gamVineCopula object GVC <- gamVine(Matrix = Matrix, model = model, names = nnames) print(GVC) # ## Not run: ### Simulate and fit the model sim <- gamVineSimulate(n, GVC) fitGVC <- gamVineSeqFit(sim, GVC, verbose = TRUE) fitGVC2 <- gamVineCopSelect(sim, Matrix, verbose = TRUE) ### Plot the results par(mfrow = c(3, 4)) plot(GVC, ylim = c(-2.5, 2.5)) plot(fitGVC, ylim = c(-2.5, 2.5)) plot(fitGVC2, ylim = c(-2.5, 2.5)) ## End(Not run)
Function calculating Akaike's 'An Information Criterion' (AIC) for an object
of the class gamBiCop
(note that the models are usually fitted by penalized likelihood
maximization).
## S4 method for signature 'gamBiCop' AIC(object, ..., k = 2)## S4 method for signature 'gamBiCop' AIC(object, ..., k = 2)
object |
An object of the class
|
... |
un-used in this class |
k |
numeric, the penalty per parameter to be used; the default
|
A numeric value with the corresponding AIC.
Function calculating the Schwarz's Bayesian Information Criterion (BIC)
for an object of the class
gamBiCop (note that the models are
usually fitted by penalized likelihood maximization).
## S4 method for signature 'gamBiCop' BIC(object, ...)## S4 method for signature 'gamBiCop' BIC(object, ...)
object |
An object of the class
|
... |
un-used in this class |
A numeric value with the corresponding BIC.
Computes the (first) copula parameter of a bivariate copula for a given value of the calibration function (eta).
BiCopEta2Par(family, eta)BiCopEta2Par(family, eta)
family |
A copula family:
|
eta |
The calibration function. |
The value of the first copula parameter, depending on the copula parameter and family as:
1 Gaussian, f(x) = tanh(x/2)
2 Student t, f(x) = tanh(x/2)
301 Double Clayton type I (standard and rotated 90 degrees),
f(x) = x
302 Double Clayton type II (standard and rotated 270 degrees),
f(x) = x
303 Double Clayton type III (survival and rotated 90 degrees),
f(x) = x
304 Double Clayton type IV (survival and rotated 270 degrees),
f(x) = x
401 Double Gumbel type I (standard and rotated 90 degrees),
f(x) = x*(1+abs(x))/abs(x)
402 Double Gumbel type II (standard and rotated 270 degrees),
f(x) = x*(1+abs(x))/abs(x)
403 Double Gumbel type III (survival and rotated 90 degrees),
f(x) = x*(1+abs(x))/abs(x)
404 Double Gumbel type IV (survival and rotated 270 degrees)
f(x) = x*(1+abs(x))/abs(x).
BiCopPar2Eta, BiCopPar2Tau,
and BiCopTau2Par from the VineCopula package.
Computes the calibration function (eta) of a bivariate copula for a given value of the (first) copula parameter.
BiCopPar2Eta(family, par)BiCopPar2Eta(family, par)
family |
A copula family:
|
par |
The (first) copula parameter |
The value of the calibration function, depending on the copula parameter and family as:
1 Gaussian, f(x) = 2*atanh(x)
2 Student t, f(x) = 2*atanh(x)
301 Double Clayton type I (standard and rotated 90 degrees),
f(x) = x
302 Double Clayton type II (standard and rotated 270 degrees),
f(x) = x
303 Double Clayton type III (survival and rotated 90 degrees),
f(x) = x
304 Double Clayton type IV (survival and rotated 270 degrees),
f(x) = x
401 Double Gumbel type I (standard and rotated 90 degrees),
f(x) = x*(1-1/abs(x))
402 Double Gumbel type II (standard and rotated 270 degrees),
f(x) = x*(1-1/abs(x))
403 Double Gumbel type III (survival and rotated 90 degrees),
f(x) = x*(1-1/abs(x))
404 Double Gumbel type IV (survival and rotated 270 degrees)
f(x) = x*(1-1/abs(x)).
BiCopEta2Par,
BiCopPar2Tau,
and BiCopTau2Par from the VineCopula package.
Simulates from a conditional bivariate copula, where each copula parameter takes a different value, depending on the calibration function and covariates.
condBiCopSim(family, calib.fnc, X, par2 = 0, return.par = TRUE, tau = TRUE)condBiCopSim(family, calib.fnc, X, par2 = 0, return.par = TRUE, tau = TRUE)
family |
family A copula family:
|
calib.fnc |
A calibration function. |
X |
A vector (if |
par2 |
The second copula parameter (for the Student t), default
|
return.par |
Should the parameter (and calibration function) be returned
as well (default |
tau |
Should the calibration function (and the model) be specified for
the copula parameter or Kendall's tau (default |
If return.par = TRUE, then the function returns a list with:
data, a matrix with two columns containing the simulated data,
par, a vector containing the values of the copula parameter,
and eta, a vector containing the values of the
calibration function.
If return.par = FALSE, then the function simply returns data,
a matrix with two columns containing the simulated data.
gamBiCopFit and gamBiCopSimulate.
require(copula) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 2e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## Display the calibration surface par(mfrow = c(1, 3), pty = "s", mar = c(1, 1, 4, 1)) u <- seq(0, 1, length.out = 100) sel <- matrix(c(1, 1, 2, 2, 3, 3), ncol = 2) jet.colors <- colorRamp(c( "#00007F", "blue", "#007FFF", "cyan", "#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000" )) jet <- function(x) rgb(jet.colors(exp(x / 3) / (1 + exp(x / 3))), maxColorValue = 255 ) for (k in 1:3) { tmp <- outer(u, u, function(x, y) eta0 + calib.surf[[sel[k, 1]]](x) + calib.surf[[sel[k, 2]]](y)) persp(u, u, tmp, border = NA, theta = 60, phi = 30, zlab = "", col = matrix(jet(tmp), nrow = 100), xlab = paste("X", sel[k, 1], sep = ""), ylab = paste("X", sel[k, 2], sep = ""), main = paste("eta0+f", sel[k, 1], "(X", sel[k, 1], ") +f", sel[k, 2], "(X", sel[k, 2], ")", sep = "" ) ) } ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Display the data dev.off() plot(data[, "u1"], data[, "u2"], xlab = "U1", ylab = "U2")require(copula) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 2e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## Display the calibration surface par(mfrow = c(1, 3), pty = "s", mar = c(1, 1, 4, 1)) u <- seq(0, 1, length.out = 100) sel <- matrix(c(1, 1, 2, 2, 3, 3), ncol = 2) jet.colors <- colorRamp(c( "#00007F", "blue", "#007FFF", "cyan", "#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000" )) jet <- function(x) rgb(jet.colors(exp(x / 3) / (1 + exp(x / 3))), maxColorValue = 255 ) for (k in 1:3) { tmp <- outer(u, u, function(x, y) eta0 + calib.surf[[sel[k, 1]]](x) + calib.surf[[sel[k, 2]]](y)) persp(u, u, tmp, border = NA, theta = 60, phi = 30, zlab = "", col = matrix(jet(tmp), nrow = 100), xlab = paste("X", sel[k, 1], sep = ""), ylab = paste("X", sel[k, 2], sep = ""), main = paste("eta0+f", sel[k, 1], "(X", sel[k, 1], ") +f", sel[k, 2], "(X", sel[k, 2], ")", sep = "" ) ) } ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Display the data dev.off() plot(data[, "u1"], data[, "u2"], xlab = "U1", ylab = "U2")
Retrieve the dimension of an object of the class
gamVine.
## S4 method for signature 'gamVine' dim(x)## S4 method for signature 'gamVine' dim(x)
x |
An object of the class
|
Dimension of the
gamVine object.
Function calculating the Equivalent Degrees of Freedom (EDF)
for a gamBiCop object.
It basically sums the edf of the gamObject
for each smooth component.
EDF(object)EDF(object)
object |
An object of the class
|
Estimated degrees of freedom for each smooth component.
Extracts the gam formula from an object of the class
gamBiCop.
This function is a wrapper to formula.gam
from the mgcv package.
## S4 method for signature 'gamBiCop' formula(x, ...)## S4 method for signature 'gamBiCop' formula(x, ...)
x |
An object of the class
|
... |
un-used in this class |
formula.gam function
from the mgcv package.
Constructs an object of the class
gamBiCop.
gamBiCop(family, model, par2 = 0, tau = TRUE)gamBiCop(family, model, par2 = 0, tau = TRUE)
family |
A copula family: |
model |
A |
par2 |
Second parameter for the Student t-copula. |
tau |
|
An object of the class
gamBiCop.
gamBiCop,
gamBiCopFit, gamBiCopPredict and
gamBiCopSimulate.
gamBiCop is an S4 class to store
a Generalized Additive Model for bivariate copula a parameter or
Kendall's tau. Objects can be created by calls of the form
new("gamBiCop", ...), or by function gamBiCop.
familyA copula family: 1 Gaussian,
2 Student t,
5 Frank,
301 Double Clayton type I (standard and rotated 90 degrees),
302 Double Clayton type II (standard and rotated 270 degrees),
303 Double Clayton type III (survival and rotated 90 degrees),
304 Double Clayton type IV (survival and rotated 270 degrees),
401 Double Gumbel type I (standard and rotated 90 degrees),
402 Double Gumbel type II (standard and rotated 270 degrees),
403 Double Gumbel type III (survival and rotated 90 degrees),
404 Double Gumbel type IV (survival and rotated 270 degrees).
modelA gamObject as return by the
gam function
from the mgcv package.
par2Second parameter for the Studen t-copula.
tauFALSE (default) for a calibration fonction
specified for the Copula parameter
or TRUE for a calibration function specified for Kendall's tau.
gamBiCopFit,
gamBiCopPredict and gamBiCopSimulate.
This function returns the distribution function of a bivariate conditional copula, where either the copula parameter or the Kendall's tau is modeled as a function of the covariates.
gamBiCopCDF(object, newdata = NULL)gamBiCopCDF(object, newdata = NULL)
object |
|
newdata |
(Same as in |
The conditional density.
gamBiCop and gamBiCopPredict.
require(copula) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 2e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) colnames(X) <- paste("x", 1:3, sep = "") ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Model fit with penalized cubic splines (via min GCV) basis <- c(3, 10, 10) formula <- ~ s(x1, k = basis[1], bs = "cr") + s(x2, k = basis[2], bs = "cr") + s(x3, k = basis[3], bs = "cr") system.time(fit <- gamBiCopFit(data, formula, fam)) ## Evaluate the conditional density gamBiCopCDF(fit$res)require(copula) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 2e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) colnames(X) <- paste("x", 1:3, sep = "") ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Model fit with penalized cubic splines (via min GCV) basis <- c(3, 10, 10) formula <- ~ s(x1, k = basis[1], bs = "cr") + s(x2, k = basis[2], bs = "cr") + s(x3, k = basis[3], bs = "cr") system.time(fit <- gamBiCopFit(data, formula, fam)) ## Evaluate the conditional density gamBiCopCDF(fit$res)
This function estimates the parameter(s) of a Generalized Additive model
(gam) for the copula parameter or Kendall's tau.
It solves the maximum penalized likelihood estimation for the copula families
supported in this package by reformulating each Newton-Raphson iteration as
a generalized ridge regression, which is solved using
the mgcv package.
gamBiCopFit( data, formula = ~1, family = 1, tau = TRUE, method = "FS", tol.rel = 0.001, n.iters = 10, verbose = FALSE, ... )gamBiCopFit( data, formula = ~1, family = 1, tau = TRUE, method = "FS", tol.rel = 0.001, n.iters = 10, verbose = FALSE, ... )
data |
A list, data frame or matrix containing the model responses, (u1,u2) in [0,1]x[0,1], and covariates required by the formula. |
formula |
A gam formula (see |
family |
A copula family: |
tau |
|
method |
|
tol.rel |
Relative tolerance for |
n.iters |
Maximal number of iterations for
|
verbose |
|
... |
gamBiCopFit returns a list consisting of
res |
S4 |
method |
|
tol.rel |
relative tolerance for |
n.iters |
maximal number of iterations for
|
trace |
the estimation procedure's trace. |
conv |
|
gamBiCop and gamBiCopSimulate.
require(copula) require(mgcv) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 5e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## Display the calibration surface par(mfrow = c(1, 3), pty = "s", mar = c(1, 1, 4, 1)) u <- seq(0, 1, length.out = 100) sel <- matrix(c(1, 1, 2, 2, 3, 3), ncol = 2) jet.colors <- colorRamp(c( "#00007F", "blue", "#007FFF", "cyan", "#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000" )) jet <- function(x) rgb(jet.colors(exp(x / 3) / (1 + exp(x / 3))), maxColorValue = 255 ) for (k in 1:3) { tmp <- outer(u, u, function(x, y) eta0 + calib.surf[[sel[k, 1]]](x) + calib.surf[[sel[k, 2]]](y)) persp(u, u, tmp, border = NA, theta = 60, phi = 30, zlab = "", col = matrix(jet(tmp), nrow = 100), xlab = paste("X", sel[k, 1], sep = ""), ylab = paste("X", sel[k, 2], sep = ""), main = paste("eta0+f", sel[k, 1], "(X", sel[k, 1], ") +f", sel[k, 2], "(X", sel[k, 2], ")", sep = "" ) ) } ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Display the data dev.off() plot(data[, "u1"], data[, "u2"], xlab = "U1", ylab = "U2") ## Model fit with a basis size (arguably) too small ## and unpenalized cubic spines pen <- FALSE basis0 <- c(3, 4, 4) formula <- ~ s(x1, k = basis0[1], bs = "cr", fx = !pen) + s(x2, k = basis0[2], bs = "cr", fx = !pen) + s(x3, k = basis0[3], bs = "cr", fx = !pen) system.time(fit0 <- gamBiCopFit(data, formula, fam)) ## Model fit with a better basis size and penalized cubic splines (via min GCV) pen <- TRUE basis1 <- c(3, 10, 10) formula <- ~ s(x1, k = basis1[1], bs = "cr", fx = !pen) + s(x2, k = basis1[2], bs = "cr", fx = !pen) + s(x3, k = basis1[3], bs = "cr", fx = !pen) system.time(fit1 <- gamBiCopFit(data, formula, fam)) ## Extract the gamBiCop objects and show various methods (res <- sapply(list(fit0, fit1), function(fit) { fit$res })) metds <- list("logLik" = logLik, "AIC" = AIC, "BIC" = BIC, "EDF" = EDF) lapply(res, function(x) sapply(metds, function(f) f(x))) ## Comparison between fitted, true smooth and spline approximation for each ## true smooth function for the two basis sizes fitted <- lapply(res, function(x) gamBiCopPredict(x, data.frame(x1 = u, x2 = u, x3 = u), type = "terms" )$calib) true <- vector("list", 3) for (i in 1:3) { y <- eta0 + calib.surf[[i]](u) true[[i]]$true <- y - eta0 temp <- gam(y ~ s(u, k = basis0[i], bs = "cr", fx = TRUE)) true[[i]]$approx <- predict.gam(temp, type = "terms") temp <- gam(y ~ s(u, k = basis1[i], bs = "cr", fx = FALSE)) true[[i]]$approx2 <- predict.gam(temp, type = "terms") } ## Display results par(mfrow = c(1, 3), pty = "s") yy <- range(true, fitted) yy[1] <- yy[1] * 1.5 for (k in 1:3) { plot(u, true[[k]]$true, type = "l", ylim = yy, xlab = paste("Covariate", k), ylab = paste("Smooth", k) ) lines(u, true[[k]]$approx, col = "red", lty = 2) lines(u, fitted[[1]][, k], col = "red") lines(u, fitted[[2]][, k], col = "green") lines(u, true[[k]]$approx2, col = "green", lty = 2) legend("bottomleft", cex = 0.6, lty = c(1, 1, 2, 1, 2), c("True", "Fitted", "Appox 1", "Fitted 2", "Approx 2"), col = c("black", "red", "red", "green", "green") ) }require(copula) require(mgcv) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 5e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## Display the calibration surface par(mfrow = c(1, 3), pty = "s", mar = c(1, 1, 4, 1)) u <- seq(0, 1, length.out = 100) sel <- matrix(c(1, 1, 2, 2, 3, 3), ncol = 2) jet.colors <- colorRamp(c( "#00007F", "blue", "#007FFF", "cyan", "#7FFF7F", "yellow", "#FF7F00", "red", "#7F0000" )) jet <- function(x) rgb(jet.colors(exp(x / 3) / (1 + exp(x / 3))), maxColorValue = 255 ) for (k in 1:3) { tmp <- outer(u, u, function(x, y) eta0 + calib.surf[[sel[k, 1]]](x) + calib.surf[[sel[k, 2]]](y)) persp(u, u, tmp, border = NA, theta = 60, phi = 30, zlab = "", col = matrix(jet(tmp), nrow = 100), xlab = paste("X", sel[k, 1], sep = ""), ylab = paste("X", sel[k, 2], sep = ""), main = paste("eta0+f", sel[k, 1], "(X", sel[k, 1], ") +f", sel[k, 2], "(X", sel[k, 2], ")", sep = "" ) ) } ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Display the data dev.off() plot(data[, "u1"], data[, "u2"], xlab = "U1", ylab = "U2") ## Model fit with a basis size (arguably) too small ## and unpenalized cubic spines pen <- FALSE basis0 <- c(3, 4, 4) formula <- ~ s(x1, k = basis0[1], bs = "cr", fx = !pen) + s(x2, k = basis0[2], bs = "cr", fx = !pen) + s(x3, k = basis0[3], bs = "cr", fx = !pen) system.time(fit0 <- gamBiCopFit(data, formula, fam)) ## Model fit with a better basis size and penalized cubic splines (via min GCV) pen <- TRUE basis1 <- c(3, 10, 10) formula <- ~ s(x1, k = basis1[1], bs = "cr", fx = !pen) + s(x2, k = basis1[2], bs = "cr", fx = !pen) + s(x3, k = basis1[3], bs = "cr", fx = !pen) system.time(fit1 <- gamBiCopFit(data, formula, fam)) ## Extract the gamBiCop objects and show various methods (res <- sapply(list(fit0, fit1), function(fit) { fit$res })) metds <- list("logLik" = logLik, "AIC" = AIC, "BIC" = BIC, "EDF" = EDF) lapply(res, function(x) sapply(metds, function(f) f(x))) ## Comparison between fitted, true smooth and spline approximation for each ## true smooth function for the two basis sizes fitted <- lapply(res, function(x) gamBiCopPredict(x, data.frame(x1 = u, x2 = u, x3 = u), type = "terms" )$calib) true <- vector("list", 3) for (i in 1:3) { y <- eta0 + calib.surf[[i]](u) true[[i]]$true <- y - eta0 temp <- gam(y ~ s(u, k = basis0[i], bs = "cr", fx = TRUE)) true[[i]]$approx <- predict.gam(temp, type = "terms") temp <- gam(y ~ s(u, k = basis1[i], bs = "cr", fx = FALSE)) true[[i]]$approx2 <- predict.gam(temp, type = "terms") } ## Display results par(mfrow = c(1, 3), pty = "s") yy <- range(true, fitted) yy[1] <- yy[1] * 1.5 for (k in 1:3) { plot(u, true[[k]]$true, type = "l", ylim = yy, xlab = paste("Covariate", k), ylab = paste("Smooth", k) ) lines(u, true[[k]]$approx, col = "red", lty = 2) lines(u, fitted[[1]][, k], col = "red") lines(u, fitted[[2]][, k], col = "green") lines(u, true[[k]]$approx2, col = "green", lty = 2) legend("bottomleft", cex = 0.6, lty = c(1, 1, 2, 1, 2), c("True", "Fitted", "Appox 1", "Fitted 2", "Approx 2"), col = c("black", "red", "red", "green", "green") ) }
This function returns the density of a bivariate conditional copula, where either the copula parameter or the Kendall's tau is modeled as a function of the covariates.
gamBiCopPDF(object, newdata = NULL)gamBiCopPDF(object, newdata = NULL)
object |
|
newdata |
(Same as in |
The conditional density.
gamBiCop and gamBiCopPredict.
require(copula) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 2e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) colnames(X) <- paste("x", 1:3, sep = "") ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Model fit with penalized cubic splines (via min GCV) basis <- c(3, 10, 10) formula <- ~ s(x1, k = basis[1], bs = "cr") + s(x2, k = basis[2], bs = "cr") + s(x3, k = basis[3], bs = "cr") system.time(fit <- gamBiCopFit(data, formula, fam)) ## Evaluate the conditional density gamBiCopPDF(fit$res)require(copula) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 2e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) colnames(X) <- paste("x", 1:3, sep = "") ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Model fit with penalized cubic splines (via min GCV) basis <- c(3, 10, 10) formula <- ~ s(x1, k = basis[1], bs = "cr") + s(x2, k = basis[2], bs = "cr") + s(x3, k = basis[3], bs = "cr") system.time(fit <- gamBiCopFit(data, formula, fam)) ## Evaluate the conditional density gamBiCopPDF(fit$res)
Predict method of a Generalized Additive model for the copula parameter or Kendall's tau
gamBiCopPredict( object, newdata = NULL, target = "calib", alpha = 0, type = "link" )gamBiCopPredict( object, newdata = NULL, target = "calib", alpha = 0, type = "link" )
object |
|
newdata |
(Same as in |
target |
Either |
alpha |
In (0,1) to return the corresponding confidence interval. |
type |
(Similar as in |
If target = 'calib', then a list with 1 item calib.
If target = 'par', target = 'tau' or
target = c('par', 'tau'),
then a list with 2, 2 or 3 items, namely calib and par,
tau and par, or calib, tau and par.
If alpha is in (0,1), then a additional items of the list are
calib.CI as well as e.g. par.CI and/or tau.CI depending
on the value of target.
Otherwise, if type = 'lpmatrix' (only active for
type = 'calib'), then a matrix is returned which will give a vector of
linear predictor values (minus any offset) at the supplied covariate values,
when applied to the model coefficient vector (similar as
predict.gam from the mgcv).
gamBiCop and gamBiCopFit.
require(copula) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Clayton copula family) n <- 5e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) colnames(X) <- paste("x", 1:3, sep = "") ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Model fit with penalized cubic splines (via min GCV) basis <- c(3, 10, 10) formula <- ~ s(x1, k = basis[1], bs = "cr") + s(x2, k = basis[2], bs = "cr") + s(x3, k = basis[3], bs = "cr") system.time(fit <- gamBiCopFit(data, formula, fam)) ## Extract the gamBiCop objects and show various methods (res <- fit$res) EDF(res) pred <- gamBiCopPredict(fit$res, X, target = c("calib", "par", "tau"))require(copula) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Clayton copula family) n <- 5e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) colnames(X) <- paste("x", 1:3, sep = "") ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Model fit with penalized cubic splines (via min GCV) basis <- c(3, 10, 10) formula <- ~ s(x1, k = basis[1], bs = "cr") + s(x2, k = basis[2], bs = "cr") + s(x3, k = basis[3], bs = "cr") system.time(fit <- gamBiCopFit(data, formula, fam)) ## Extract the gamBiCop objects and show various methods (res <- fit$res) EDF(res) pred <- gamBiCopPredict(fit$res, X, target = c("calib", "par", "tau"))
This function selects an appropriate bivariate copula family for given
bivariate copula data using one of a range of methods. The corresponding
parameter estimates are obtained by maximum penalized likelihood estimation,
where each Newton-Raphson iteration is reformulated as a generalized ridge
regression solved using the mgcv package.
gamBiCopSelect( udata, lin.covs = NULL, smooth.covs = NULL, familyset = NA, rotations = TRUE, familycrit = "AIC", level = 0.05, edf = 1.5, tau = TRUE, method = "FS", tol.rel = 0.001, n.iters = 10, parallel = FALSE, verbose = FALSE, select.once = TRUE, ... )gamBiCopSelect( udata, lin.covs = NULL, smooth.covs = NULL, familyset = NA, rotations = TRUE, familycrit = "AIC", level = 0.05, edf = 1.5, tau = TRUE, method = "FS", tol.rel = 0.001, n.iters = 10, parallel = FALSE, verbose = FALSE, select.once = TRUE, ... )
udata |
A matrix or data frame containing the model responses, (u1,u2) in [0,1]x[0,1] |
lin.covs |
A matrix or data frame containing the parametric (i.e., linear) covariates. |
smooth.covs |
A matrix or data frame containing the non-parametric (i.e., smooth) covariates. |
familyset |
(Similar to |
rotations |
If |
familycrit |
Character indicating the criterion for bivariate copula
selection. Possible choices: |
level |
Numerical; significance level of the test for removing individual
predictors (default: |
edf |
Numerical; if the estimated EDF for individual predictors is
smaller than |
tau |
|
method |
|
tol.rel |
Relative tolerance for |
n.iters |
Maximal number of iterations for
|
parallel |
|
verbose |
|
select.once |
if |
... |
Additional parameters to be passed to |
gamBiCopFit returns a list consisting of
res |
S4 |
method |
|
tol.rel |
relative tolerance for |
n.iters |
maximal number of iterations for
|
trace |
the estimation procedure's trace. |
conv |
|
gamBiCop and gamBiCopFit.
require(copula) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Student copula with 4 degrees of freedom) n <- 5e2 rho <- 0.9 fam <- 2 par2 <- 4 ## A calibration surface depending on four variables eta0 <- 1 calib.surf <- list( calib.lin <- function(t, Ti = 0, Tf = 1, b = 2) { return(-2 + 4 * t) }, calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## 6-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 6), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) colnames(X) <- paste("x", 1:6, sep = "") ## U in [0,1]x[0,1] depending on the four first columns of X U <- condBiCopSim(fam, function(x1, x2, x3, x4) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3, x4))) }, X[, 1:4], par2 = 4, return.par = TRUE) ## Not run: ## Selection using AIC (about 30sec on single core) ## Use parallel = TRUE to speed-up.... system.time(best <- gamBiCopSelect(U$data, smooth.covs = X)) print(best$res) EDF(best$res) ## The first function is linear ## Plot only the smooth component par(mfrow = c(2, 2)) plot(best$res) ## End(Not run)require(copula) set.seed(0) ## Simulation parameters (sample size, correlation between covariates, ## Student copula with 4 degrees of freedom) n <- 5e2 rho <- 0.9 fam <- 2 par2 <- 4 ## A calibration surface depending on four variables eta0 <- 1 calib.surf <- list( calib.lin <- function(t, Ti = 0, Tf = 1, b = 2) { return(-2 + 4 * t) }, calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## 6-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 6), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) colnames(X) <- paste("x", 1:6, sep = "") ## U in [0,1]x[0,1] depending on the four first columns of X U <- condBiCopSim(fam, function(x1, x2, x3, x4) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3, x4))) }, X[, 1:4], par2 = 4, return.par = TRUE) ## Not run: ## Selection using AIC (about 30sec on single core) ## Use parallel = TRUE to speed-up.... system.time(best <- gamBiCopSelect(U$data, smooth.covs = X)) print(best$res) EDF(best$res) ## The first function is linear ## Plot only the smooth component par(mfrow = c(2, 2)) plot(best$res) ## End(Not run)
gamBiCop-class objectSimulate from gamBiCop-class object
gamBiCopSimulate( object, newdata = NULL, N = NULL, return.calib = FALSE, return.par = FALSE, return.tau = FALSE )gamBiCopSimulate( object, newdata = NULL, N = NULL, return.calib = FALSE, return.par = FALSE, return.tau = FALSE )
object |
|
newdata |
(same as in |
N |
sample size. |
return.calib |
should the calibration function ( |
return.par |
should the copula parameter ( |
return.tau |
should the Kendall's tau ( |
A list with 1 item data. When N is smaller or larger than the newdata's number of rows
(or the number of rows in the original data if newdata is not provided),
then N observations are sampled uniformly (with replacement) among the row of newdata
(or the rows of the original data if newdata is not provided).
If return.calib = TRUE, return.par = TRUE
and/or return.tau = TRUE, then the list also contains respectively items
calib, par and/or tau.
require(copula) set.seed(1) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 5e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) colnames(X) <- paste("x", 1:3, sep = "") ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Model fit with penalized cubic splines (via min GCV) basis <- c(3, 10, 10) formula <- ~ s(x1, k = basis[1], bs = "cr") + s(x2, k = basis[2], bs = "cr") + s(x3, k = basis[3], bs = "cr") system.time(fit <- gamBiCopFit(data, formula, fam)) ## Extract the gamBiCop objects and show various methods (res <- fit$res) EDF(res) sim <- gamBiCopSimulate(fit$res, X)require(copula) set.seed(1) ## Simulation parameters (sample size, correlation between covariates, ## Gaussian copula family) n <- 5e2 rho <- 0.5 fam <- 1 ## A calibration surface depending on three variables eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## 3-dimensional matrix X of covariates covariates.distr <- mvdc(normalCopula(rho, dim = 3), c("unif"), list(list(min = 0, max = 1)), marginsIdentical = TRUE ) X <- rMvdc(n, covariates.distr) colnames(X) <- paste("x", 1:3, sep = "") ## U in [0,1]x[0,1] with copula parameter depending on X U <- condBiCopSim(fam, function(x1, x2, x3) { eta0 + sum(mapply(function(f, x) f(x), calib.surf, c(x1, x2, x3))) }, X[, 1:3], par2 = 6, return.par = TRUE) ## Merge U and X data <- data.frame(U$data, X) names(data) <- c(paste("u", 1:2, sep = ""), paste("x", 1:3, sep = "")) ## Model fit with penalized cubic splines (via min GCV) basis <- c(3, 10, 10) formula <- ~ s(x1, k = basis[1], bs = "cr") + s(x2, k = basis[2], bs = "cr") + s(x3, k = basis[3], bs = "cr") system.time(fit <- gamBiCopFit(data, formula, fam)) ## Extract the gamBiCop objects and show various methods (res <- fit$res) EDF(res) sim <- gamBiCopSimulate(fit$res, X)
Constructs an object of the class
gamVine.
gamVine(Matrix, model, names = NA, covariates = NA)gamVine(Matrix, model, names = NA, covariates = NA)
Matrix |
lower triangular d x d matrix that defines the tree structure. |
model |
list containing d x (d-1)/2 lists with three numeric items
(family, par and par2) and/or objects of the class
|
names |
vector of d names. |
covariates |
vector of names for the covariates. |
An object of the class
gamVine.
gamVine,
RVineMatrix, gamBiCop
gamVineSeqFit, gamVineCopSelect,
gamVineStructureSelect and gamVineSimulate.
gamVine is an S4 class to store a conditional and potentially
non-simplified pair-copula construction. Objects can be created by calls of
the form new("gamVine", ...), or by function gamVine.
MatrixLower triangular d x d matrix that defines the tree structure.
modellist containing d x (d-1)/2 lists with three numeric items
(family, par and par2) and/or
gamBiCop objects.
namesvector of d names.
covariatesvector of names for the exogenous covariates.
gamVine,
RVineMatrix,
gamBiCop
gamVineSeqFit, gamVineCopSelect,
gamVineStructureSelect and gamVineSimulate.
This function select the copula family and estimates the parameter(s) of a
Generalized Additive model
(GAM) Vine model, where GAMs for individual edges are specified either for
the copula parameter or Kendall's tau.
It solves the maximum penalized likelihood estimation for the copula families
supported in this package by reformulating each Newton-Raphson iteration as
a generalized ridge regression, which is solved using
the mgcv package.
gamVineCopSelect( data, Matrix, lin.covs = NULL, smooth.covs = NULL, simplified = FALSE, familyset = NA, rotations = TRUE, familycrit = "AIC", level = 0.05, trunclevel = NA, tau = TRUE, method = "FS", tol.rel = 0.001, n.iters = 10, parallel = FALSE, verbose = FALSE, select.once = TRUE, ... )gamVineCopSelect( data, Matrix, lin.covs = NULL, smooth.covs = NULL, simplified = FALSE, familyset = NA, rotations = TRUE, familycrit = "AIC", level = 0.05, trunclevel = NA, tau = TRUE, method = "FS", tol.rel = 0.001, n.iters = 10, parallel = FALSE, verbose = FALSE, select.once = TRUE, ... )
data |
A matrix or data frame containing the data in [0,1]^d. |
Matrix |
Lower triangular |
lin.covs |
A matrix or data frame containing the parametric (i.e.,
linear) covariates (default: |
smooth.covs |
A matrix or data frame containing the non-parametric
(i.e., smooth) covariates (default: |
simplified |
If |
familyset |
An integer vector of pair-copula families to select from
(the independence copula MUST NOT be specified in this vector unless one
wants to fit an independence vine!). The vector has to include at least one
pair-copula family that allows for positive and one that allows for negative
dependence. Not listed copula families might be included to better handle
limit cases. If |
rotations |
If |
familycrit |
Character indicating the criterion for bivariate copula
selection. Possible choices: |
level |
Numerical; Passed to |
trunclevel |
Integer; level of truncation. |
tau |
|
method |
|
tol.rel |
Relative tolerance for |
n.iters |
Maximal number of iterations for
|
parallel |
|
verbose |
|
select.once |
if |
... |
gamVineCopSelect returns a gamVine-class object.
gamVineSeqFit,gamVineStructureSelect,
gamVine-class, gamVineSimulate and
gamBiCopFit.
require(mgcv) set.seed(0) ## Simulation parameters # Sample size n <- 1e3 # Copula families familyset <- c(1:2, 301:304, 401:404) # Define a 4-dimensional R-vine tree structure matrix d <- 4 Matrix <- c(2, 3, 4, 1, 0, 3, 4, 1, 0, 0, 4, 1, 0, 0, 0, 1) Matrix <- matrix(Matrix, d, d) nnames <- paste("X", 1:d, sep = "") ## A function factory eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## Create the model # Define gam-vine model list count <- 1 model <- vector(mode = "list", length = d * (d - 1) / 2) sel <- seq(d, d^2 - d, by = d) # First tree for (i in 1:(d - 1)) { # Select a copula family family <- sample(familyset, 1) model[[count]]$family <- family # Use the canonical link and a randomly generated parameter if (is.element(family, c(1, 2))) { model[[count]]$par <- tanh(rnorm(1) / 2) if (family == 2) { model[[count]]$par2 <- 2 + exp(rnorm(1)) } } else { if (is.element(family, c(401:404))) { rr <- rnorm(1) model[[count]]$par <- sign(rr) * (1 + abs(rr)) } else { model[[count]]$par <- rnorm(1) } model[[count]]$par2 <- 0 } count <- count + 1 } # A dummy dataset data <- data.frame(u1 = runif(1e2), u2 = runif(1e2), matrix(runif(1e2 * d), 1e2, d)) # Trees 2 to (d-1) for (j in 2:(d - 1)) { for (i in 1:(d - j)) { # Select a copula family family <- sample(familyset, 1) # Select the conditiong set and create a model formula cond <- nnames[sort(Matrix[(d - j + 2):d, i])] tmpform <- paste("~", paste(paste("s(", cond, ", k=10, bs='cr')", sep = "" ), collapse = " + ")) l <- length(cond) temp <- sample(3, l, replace = TRUE) # Spline approximation of the true function m <- 1e2 x <- matrix(seq(0, 1, length.out = m), nrow = m, ncol = 1) if (l != 1) { tmp.fct <- paste("function(x){eta0+", paste(sapply(1:l, function(x) paste("calib.surf[[", temp[x], "]](x[", x, "])", sep = "" )), collapse = "+"), "}", sep = "" ) tmp.fct <- eval(parse(text = tmp.fct)) x <- eval(parse(text = paste0("expand.grid(", paste0(rep("x", l), collapse = ","), ")", collapse = "" ))) y <- apply(x, 1, tmp.fct) } else { tmp.fct <- function(x) eta0 + calib.surf[[temp]](x) colnames(x) <- cond y <- tmp.fct(x) } # Estimate the gam model form <- as.formula(paste0("y", tmpform)) dd <- data.frame(y, x) names(dd) <- c("y", cond) b <- gam(form, data = dd) # plot(x[,1],(y-fitted(b))/y) # Create a dummy gamBiCop object tmp <- gamBiCopFit(data = data, formula = form, family = 1, n.iters = 1)$res # Update the copula family and the model coefficients attr(tmp, "model")$coefficients <- coefficients(b) attr(tmp, "model")$smooth <- b$smooth attr(tmp, "family") <- family if (family == 2) { attr(tmp, "par2") <- 2 + exp(rnorm(1)) } model[[count]] <- tmp count <- count + 1 } } # Create the gamVineCopula object GVC <- gamVine(Matrix = Matrix, model = model, names = nnames) print(GVC) ## Not run: ## Simulate and fit the model sim <- gamVineSimulate(n, GVC) fitGVC <- gamVineSeqFit(sim, GVC, verbose = TRUE) fitGVC2 <- gamVineCopSelect(sim, Matrix, verbose = TRUE) ## Plot the results par(mfrow = c(3, 4)) plot(GVC, ylim = c(-2.5, 2.5)) plot(fitGVC, ylim = c(-2.5, 2.5)) plot(fitGVC2, ylim = c(-2.5, 2.5)) ## End(Not run)require(mgcv) set.seed(0) ## Simulation parameters # Sample size n <- 1e3 # Copula families familyset <- c(1:2, 301:304, 401:404) # Define a 4-dimensional R-vine tree structure matrix d <- 4 Matrix <- c(2, 3, 4, 1, 0, 3, 4, 1, 0, 0, 4, 1, 0, 0, 0, 1) Matrix <- matrix(Matrix, d, d) nnames <- paste("X", 1:d, sep = "") ## A function factory eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## Create the model # Define gam-vine model list count <- 1 model <- vector(mode = "list", length = d * (d - 1) / 2) sel <- seq(d, d^2 - d, by = d) # First tree for (i in 1:(d - 1)) { # Select a copula family family <- sample(familyset, 1) model[[count]]$family <- family # Use the canonical link and a randomly generated parameter if (is.element(family, c(1, 2))) { model[[count]]$par <- tanh(rnorm(1) / 2) if (family == 2) { model[[count]]$par2 <- 2 + exp(rnorm(1)) } } else { if (is.element(family, c(401:404))) { rr <- rnorm(1) model[[count]]$par <- sign(rr) * (1 + abs(rr)) } else { model[[count]]$par <- rnorm(1) } model[[count]]$par2 <- 0 } count <- count + 1 } # A dummy dataset data <- data.frame(u1 = runif(1e2), u2 = runif(1e2), matrix(runif(1e2 * d), 1e2, d)) # Trees 2 to (d-1) for (j in 2:(d - 1)) { for (i in 1:(d - j)) { # Select a copula family family <- sample(familyset, 1) # Select the conditiong set and create a model formula cond <- nnames[sort(Matrix[(d - j + 2):d, i])] tmpform <- paste("~", paste(paste("s(", cond, ", k=10, bs='cr')", sep = "" ), collapse = " + ")) l <- length(cond) temp <- sample(3, l, replace = TRUE) # Spline approximation of the true function m <- 1e2 x <- matrix(seq(0, 1, length.out = m), nrow = m, ncol = 1) if (l != 1) { tmp.fct <- paste("function(x){eta0+", paste(sapply(1:l, function(x) paste("calib.surf[[", temp[x], "]](x[", x, "])", sep = "" )), collapse = "+"), "}", sep = "" ) tmp.fct <- eval(parse(text = tmp.fct)) x <- eval(parse(text = paste0("expand.grid(", paste0(rep("x", l), collapse = ","), ")", collapse = "" ))) y <- apply(x, 1, tmp.fct) } else { tmp.fct <- function(x) eta0 + calib.surf[[temp]](x) colnames(x) <- cond y <- tmp.fct(x) } # Estimate the gam model form <- as.formula(paste0("y", tmpform)) dd <- data.frame(y, x) names(dd) <- c("y", cond) b <- gam(form, data = dd) # plot(x[,1],(y-fitted(b))/y) # Create a dummy gamBiCop object tmp <- gamBiCopFit(data = data, formula = form, family = 1, n.iters = 1)$res # Update the copula family and the model coefficients attr(tmp, "model")$coefficients <- coefficients(b) attr(tmp, "model")$smooth <- b$smooth attr(tmp, "family") <- family if (family == 2) { attr(tmp, "par2") <- 2 + exp(rnorm(1)) } model[[count]] <- tmp count <- count + 1 } } # Create the gamVineCopula object GVC <- gamVine(Matrix = Matrix, model = model, names = nnames) print(GVC) ## Not run: ## Simulate and fit the model sim <- gamVineSimulate(n, GVC) fitGVC <- gamVineSeqFit(sim, GVC, verbose = TRUE) fitGVC2 <- gamVineCopSelect(sim, Matrix, verbose = TRUE) ## Plot the results par(mfrow = c(3, 4)) plot(GVC, ylim = c(-2.5, 2.5)) plot(fitGVC, ylim = c(-2.5, 2.5)) plot(fitGVC2, ylim = c(-2.5, 2.5)) ## End(Not run)
Return the matrix of copula family (see
gamBiCop)
corresponding to the model list in the
gamVine object.
gamVineFamily(GVC)gamVineFamily(GVC)
GVC |
An object of the class
|
Matrix of copula families corresponding to the model list in the
gamVine object.
Change the R-vine matrix in the natural order, i.e. with d:1 on the diagonal
gamVineNormalize(GVC)gamVineNormalize(GVC)
GVC |
An object of the class
|
The normalized gamVine object.
This function returns the density of a conditional pair-copula constructions, where either the copula parameters or the Kendall's taus are modeled as a function of the covariates.
gamVinePDF(object, data)gamVinePDF(object, data)
object |
|
data |
(Same as in |
The conditional density.
gamVine, gamVineCopSelect,
gamVineStructureSelect, gamVine-class,
gamVineSimulate and gamBiCopFit.
require(mgcv) set.seed(0) ## Simulation parameters # Sample size n <- 1e3 # Copula families familyset <- c(1:2, 301:304, 401:404) # Define a 4-dimensional R-vine tree structure matrix d <- 4 Matrix <- c(2, 3, 4, 1, 0, 3, 4, 1, 0, 0, 4, 1, 0, 0, 0, 1) Matrix <- matrix(Matrix, d, d) nnames <- paste("X", 1:d, sep = "") ## A function factory eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## Create the model # Define gam-vine model list count <- 1 model <- vector(mode = "list", length = d * (d - 1) / 2) sel <- seq(d, d^2 - d, by = d) # First tree for (i in 1:(d - 1)) { # Select a copula family family <- sample(familyset, 1) model[[count]]$family <- family # Use the canonical link and a randomly generated parameter if (is.element(family, c(1, 2))) { model[[count]]$par <- tanh(rnorm(1) / 2) if (family == 2) { model[[count]]$par2 <- 2 + exp(rnorm(1)) } } else { if (is.element(family, c(401:404))) { rr <- rnorm(1) model[[count]]$par <- sign(rr) * (1 + abs(rr)) } else { model[[count]]$par <- rnorm(1) } model[[count]]$par2 <- 0 } count <- count + 1 } # A dummy dataset data <- data.frame(u1 = runif(1e2), u2 = runif(1e2), matrix(runif(1e2 * d), 1e2, d)) # Trees 2 to (d-1) for (j in 2:(d - 1)) { for (i in 1:(d - j)) { # Select a copula family family <- sample(familyset, 1) # Select the conditiong set and create a model formula cond <- nnames[sort(Matrix[(d - j + 2):d, i])] tmpform <- paste("~", paste(paste("s(", cond, ", k=10, bs='cr')", sep = "" ), collapse = " + ")) l <- length(cond) temp <- sample(3, l, replace = TRUE) # Spline approximation of the true function m <- 1e2 x <- matrix(seq(0, 1, length.out = m), nrow = m, ncol = 1) if (l != 1) { tmp.fct <- paste("function(x){eta0+", paste(sapply(1:l, function(x) paste("calib.surf[[", temp[x], "]](x[", x, "])", sep = "" )), collapse = "+"), "}", sep = "" ) tmp.fct <- eval(parse(text = tmp.fct)) x <- eval(parse(text = paste0("expand.grid(", paste0(rep("x", l), collapse = ","), ")", collapse = "" ))) y <- apply(x, 1, tmp.fct) } else { tmp.fct <- function(x) eta0 + calib.surf[[temp]](x) colnames(x) <- cond y <- tmp.fct(x) } # Estimate the gam model form <- as.formula(paste0("y", tmpform)) dd <- data.frame(y, x) names(dd) <- c("y", cond) b <- gam(form, data = dd) # plot(x[,1],(y-fitted(b))/y) # Create a dummy gamBiCop object tmp <- gamBiCopFit(data = data, formula = form, family = 1, n.iters = 1)$res # Update the copula family and the model coefficients attr(tmp, "model")$coefficients <- coefficients(b) attr(tmp, "model")$smooth <- b$smooth attr(tmp, "family") <- family if (family == 2) { attr(tmp, "par2") <- 2 + exp(rnorm(1)) } model[[count]] <- tmp count <- count + 1 } } # Create the gamVineCopula object GVC <- gamVine(Matrix = Matrix, model = model, names = nnames) print(GVC) ## Not run: ## Simulate and fit the model sim <- gamVineSimulate(n, GVC) fitGVC <- gamVineSeqFit(sim, GVC, verbose = TRUE) fitGVC2 <- gamVineCopSelect(sim, Matrix, verbose = TRUE) (gamVinePDF(GVC, sim[1:10, ])) ## Plot the results dev.off() par(mfrow = c(3, 4)) plot(GVC, ylim = c(-2.5, 2.5)) plot(fitGVC, ylim = c(-2.5, 2.5)) plot(fitGVC2, ylim = c(-2.5, 2.5)) ## End(Not run)require(mgcv) set.seed(0) ## Simulation parameters # Sample size n <- 1e3 # Copula families familyset <- c(1:2, 301:304, 401:404) # Define a 4-dimensional R-vine tree structure matrix d <- 4 Matrix <- c(2, 3, 4, 1, 0, 3, 4, 1, 0, 0, 4, 1, 0, 0, 0, 1) Matrix <- matrix(Matrix, d, d) nnames <- paste("X", 1:d, sep = "") ## A function factory eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## Create the model # Define gam-vine model list count <- 1 model <- vector(mode = "list", length = d * (d - 1) / 2) sel <- seq(d, d^2 - d, by = d) # First tree for (i in 1:(d - 1)) { # Select a copula family family <- sample(familyset, 1) model[[count]]$family <- family # Use the canonical link and a randomly generated parameter if (is.element(family, c(1, 2))) { model[[count]]$par <- tanh(rnorm(1) / 2) if (family == 2) { model[[count]]$par2 <- 2 + exp(rnorm(1)) } } else { if (is.element(family, c(401:404))) { rr <- rnorm(1) model[[count]]$par <- sign(rr) * (1 + abs(rr)) } else { model[[count]]$par <- rnorm(1) } model[[count]]$par2 <- 0 } count <- count + 1 } # A dummy dataset data <- data.frame(u1 = runif(1e2), u2 = runif(1e2), matrix(runif(1e2 * d), 1e2, d)) # Trees 2 to (d-1) for (j in 2:(d - 1)) { for (i in 1:(d - j)) { # Select a copula family family <- sample(familyset, 1) # Select the conditiong set and create a model formula cond <- nnames[sort(Matrix[(d - j + 2):d, i])] tmpform <- paste("~", paste(paste("s(", cond, ", k=10, bs='cr')", sep = "" ), collapse = " + ")) l <- length(cond) temp <- sample(3, l, replace = TRUE) # Spline approximation of the true function m <- 1e2 x <- matrix(seq(0, 1, length.out = m), nrow = m, ncol = 1) if (l != 1) { tmp.fct <- paste("function(x){eta0+", paste(sapply(1:l, function(x) paste("calib.surf[[", temp[x], "]](x[", x, "])", sep = "" )), collapse = "+"), "}", sep = "" ) tmp.fct <- eval(parse(text = tmp.fct)) x <- eval(parse(text = paste0("expand.grid(", paste0(rep("x", l), collapse = ","), ")", collapse = "" ))) y <- apply(x, 1, tmp.fct) } else { tmp.fct <- function(x) eta0 + calib.surf[[temp]](x) colnames(x) <- cond y <- tmp.fct(x) } # Estimate the gam model form <- as.formula(paste0("y", tmpform)) dd <- data.frame(y, x) names(dd) <- c("y", cond) b <- gam(form, data = dd) # plot(x[,1],(y-fitted(b))/y) # Create a dummy gamBiCop object tmp <- gamBiCopFit(data = data, formula = form, family = 1, n.iters = 1)$res # Update the copula family and the model coefficients attr(tmp, "model")$coefficients <- coefficients(b) attr(tmp, "model")$smooth <- b$smooth attr(tmp, "family") <- family if (family == 2) { attr(tmp, "par2") <- 2 + exp(rnorm(1)) } model[[count]] <- tmp count <- count + 1 } } # Create the gamVineCopula object GVC <- gamVine(Matrix = Matrix, model = model, names = nnames) print(GVC) ## Not run: ## Simulate and fit the model sim <- gamVineSimulate(n, GVC) fitGVC <- gamVineSeqFit(sim, GVC, verbose = TRUE) fitGVC2 <- gamVineCopSelect(sim, Matrix, verbose = TRUE) (gamVinePDF(GVC, sim[1:10, ])) ## Plot the results dev.off() par(mfrow = c(3, 4)) plot(GVC, ylim = c(-2.5, 2.5)) plot(fitGVC, ylim = c(-2.5, 2.5)) plot(fitGVC2, ylim = c(-2.5, 2.5)) ## End(Not run)
This function estimates the parameter(s) of a Generalized Additive model
(GAM) Vine model, where GAMs for individual edges are specified either for
the copula parameter or Kendall's tau.
It solves the maximum penalized likelihood estimation for the copula families
supported in this package by reformulating each Newton-Raphson iteration as
a generalized ridge regression, which is solved using
the mgcv package.
gamVineSeqFit( data, GVC, covariates = NA, method = "FS", tol.rel = 0.001, n.iters = 10, verbose = FALSE, ... )gamVineSeqFit( data, GVC, covariates = NA, method = "FS", tol.rel = 0.001, n.iters = 10, verbose = FALSE, ... )
data |
A matrix or data frame containing the data in [0,1]^d. |
GVC |
A |
covariates |
Vector of names for the covariates. |
method |
|
tol.rel |
Relative tolerance for |
n.iters |
Maximal number of iterations for
|
verbose |
|
... |
gamVineSeqFit returns a
gamVine object.
gamVineCopSelect and
gamVineStructureSelect
gamVineCopSelect,gamVineStructureSelect,
gamVine-class, gamVineSimulate and
gamBiCopFit.
require(mgcv) set.seed(0) ## Simulation parameters # Sample size n <- 1e3 # Copula families familyset <- c(1:2, 301:304, 401:404) # Define a 4-dimensional R-vine tree structure matrix d <- 4 Matrix <- c(2, 3, 4, 1, 0, 3, 4, 1, 0, 0, 4, 1, 0, 0, 0, 1) Matrix <- matrix(Matrix, d, d) nnames <- paste("X", 1:d, sep = "") ## A function factory eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## Create the model # Define gam-vine model list count <- 1 model <- vector(mode = "list", length = d * (d - 1) / 2) sel <- seq(d, d^2 - d, by = d) # First tree for (i in 1:(d - 1)) { # Select a copula family family <- sample(familyset, 1) model[[count]]$family <- family # Use the canonical link and a randomly generated parameter if (is.element(family, c(1, 2))) { model[[count]]$par <- tanh(rnorm(1) / 2) if (family == 2) { model[[count]]$par2 <- 2 + exp(rnorm(1)) } } else { if (is.element(family, c(401:404))) { rr <- rnorm(1) model[[count]]$par <- sign(rr) * (1 + abs(rr)) } else { model[[count]]$par <- rnorm(1) } model[[count]]$par2 <- 0 } count <- count + 1 } # A dummy dataset data <- data.frame(u1 = runif(1e2), u2 = runif(1e2), matrix(runif(1e2 * d), 1e2, d)) # Trees 2 to (d-1) for (j in 2:(d - 1)) { for (i in 1:(d - j)) { # Select a copula family family <- sample(familyset, 1) # Select the conditiong set and create a model formula cond <- nnames[sort(Matrix[(d - j + 2):d, i])] tmpform <- paste("~", paste(paste("s(", cond, ", k=10, bs='cr')", sep = "" ), collapse = " + ")) l <- length(cond) temp <- sample(3, l, replace = TRUE) # Spline approximation of the true function m <- 1e2 x <- matrix(seq(0, 1, length.out = m), nrow = m, ncol = 1) if (l != 1) { tmp.fct <- paste("function(x){eta0+", paste(sapply(1:l, function(x) paste("calib.surf[[", temp[x], "]](x[", x, "])", sep = "" )), collapse = "+"), "}", sep = "" ) tmp.fct <- eval(parse(text = tmp.fct)) x <- eval(parse(text = paste0("expand.grid(", paste0(rep("x", l), collapse = ","), ")", collapse = "" ))) y <- apply(x, 1, tmp.fct) } else { tmp.fct <- function(x) eta0 + calib.surf[[temp]](x) colnames(x) <- cond y <- tmp.fct(x) } # Estimate the gam model form <- as.formula(paste0("y", tmpform)) dd <- data.frame(y, x) names(dd) <- c("y", cond) b <- gam(form, data = dd) # plot(x[,1],(y-fitted(b))/y) # Create a dummy gamBiCop object tmp <- gamBiCopFit(data = data, formula = form, family = 1, n.iters = 1)$res # Update the copula family and the model coefficients attr(tmp, "model")$coefficients <- coefficients(b) attr(tmp, "model")$smooth <- b$smooth attr(tmp, "family") <- family if (family == 2) { attr(tmp, "par2") <- 2 + exp(rnorm(1)) } model[[count]] <- tmp count <- count + 1 } } # Create the gamVineCopula object GVC <- gamVine(Matrix = Matrix, model = model, names = nnames) print(GVC) ## Not run: ## Simulate and fit the model sim <- gamVineSimulate(n, GVC) fitGVC <- gamVineSeqFit(sim, GVC, verbose = TRUE) fitGVC2 <- gamVineCopSelect(sim, Matrix, verbose = TRUE) (gamVinePDF(GVC, sim[1:10, ])) ## Plot the results dev.off() par(mfrow = c(3, 4)) plot(GVC, ylim = c(-2.5, 2.5)) plot(fitGVC, ylim = c(-2.5, 2.5)) plot(fitGVC2, ylim = c(-2.5, 2.5)) ## End(Not run)require(mgcv) set.seed(0) ## Simulation parameters # Sample size n <- 1e3 # Copula families familyset <- c(1:2, 301:304, 401:404) # Define a 4-dimensional R-vine tree structure matrix d <- 4 Matrix <- c(2, 3, 4, 1, 0, 3, 4, 1, 0, 0, 4, 1, 0, 0, 0, 1) Matrix <- matrix(Matrix, d, d) nnames <- paste("X", 1:d, sep = "") ## A function factory eta0 <- 1 calib.surf <- list( calib.quad <- function(t, Ti = 0, Tf = 1, b = 8) { Tm <- (Tf - Ti) / 2 a <- -(b / 3) * (Tf^2 - 3 * Tf * Tm + 3 * Tm^2) return(a + b * (t - Tm)^2) }, calib.sin <- function(t, Ti = 0, Tf = 1, b = 1, f = 1) { a <- b * (1 - 2 * Tf * pi / (f * Tf * pi + cos(2 * f * pi * (Tf - Ti)) - cos(2 * f * pi * Ti))) return((a + b) / 2 + (b - a) * sin(2 * f * pi * (t - Ti)) / 2) }, calib.exp <- function(t, Ti = 0, Tf = 1, b = 2, s = Tf / 8) { Tm <- (Tf - Ti) / 2 a <- (b * s * sqrt(2 * pi) / Tf) * (pnorm(0, Tm, s) - pnorm(Tf, Tm, s)) return(a + b * exp(-(t - Tm)^2 / (2 * s^2))) } ) ## Create the model # Define gam-vine model list count <- 1 model <- vector(mode = "list", length = d * (d - 1) / 2) sel <- seq(d, d^2 - d, by = d) # First tree for (i in 1:(d - 1)) { # Select a copula family family <- sample(familyset, 1) model[[count]]$family <- family # Use the canonical link and a randomly generated parameter if (is.element(family, c(1, 2))) { model[[count]]$par <- tanh(rnorm(1) / 2) if (family == 2) { model[[count]]$par2 <- 2 + exp(rnorm(1)) } } else { if (is.element(family, c(401:404))) { rr <- rnorm(1) model[[count]]$par <- sign(rr) * (1 + abs(rr)) } else { model[[count]]$par <- rnorm(1) } model[[count]]$par2 <- 0 } count <- count + 1 } # A dummy dataset data <- data.frame(u1 = runif(1e2), u2 = runif(1e2), matrix(runif(1e2 * d), 1e2, d)) # Trees 2 to (d-1) for (j in 2:(d - 1)) { for (i in 1:(d - j)) { # Select a copula family family <- sample(familyset, 1) # Select the conditiong set and create a model formula cond <- nnames[sort(Matrix[(d - j + 2):d, i])] tmpform <- paste("~", paste(paste("s(", cond, ", k=10, bs='cr')", sep = "" ), collapse = " + ")) l <- length(cond) temp <- sample(3, l, replace = TRUE) # Spline approximation of the true function m <- 1e2 x <- matrix(seq(0, 1, length.out = m), nrow = m, ncol = 1) if (l != 1) { tmp.fct <- paste("function(x){eta0+", paste(sapply(1:l, function(x) paste("calib.surf[[", temp[x], "]](x[", x, "])", sep = "" )), collapse = "+"), "}", sep = "" ) tmp.fct <- eval(parse(text = tmp.fct)) x <- eval(parse(text = paste0("expand.grid(", paste0(rep("x", l), collapse = ","), ")", collapse = "" ))) y <- apply(x, 1, tmp.fct) } else { tmp.fct <- function(x) eta0 + calib.surf[[temp]](x) colnames(x) <- cond y <- tmp.fct(x) } # Estimate the gam model form <- as.formula(paste0("y", tmpform)) dd <- data.frame(y, x) names(dd) <- c("y", cond) b <- gam(form, data = dd) # plot(x[,1],(y-fitted(b))/y) # Create a dummy gamBiCop object tmp <- gamBiCopFit(data = data, formula = form, family = 1, n.iters = 1)$res # Update the copula family and the model coefficients attr(tmp, "model")$coefficients <- coefficients(b) attr(tmp, "model")$smooth <- b$smooth attr(tmp, "family") <- family if (family == 2) { attr(tmp, "par2") <- 2 + exp(rnorm(1)) } model[[count]] <- tmp count <- count + 1 } } # Create the gamVineCopula object GVC <- gamVine(Matrix = Matrix, model = model, names = nnames) print(GVC) ## Not run: ## Simulate and fit the model sim <- gamVineSimulate(n, GVC) fitGVC <- gamVineSeqFit(sim, GVC, verbose = TRUE) fitGVC2 <- gamVineCopSelect(sim, Matrix, verbose = TRUE) (gamVinePDF(GVC, sim[1:10, ])) ## Plot the results dev.off() par(mfrow = c(3, 4)) plot(GVC, ylim = c(-2.5, 2.5)) plot(fitGVC, ylim = c(-2.5, 2.5)) plot(fitGVC2, ylim = c(-2.5, 2.5)) ## End(Not run)
gamVine-class objectSimulation from a gamVine-class object
gamVineSimulate(n, GVC, U = NULL, newdata = NULL)gamVineSimulate(n, GVC, U = NULL, newdata = NULL)
n |
number of d-dimensional observations to simulate. |
GVC |
A |
U |
If not |
newdata |
If not |
A matrix of data simulated from the given
gamVine object.
require(VineCopula) ## Example adapted from RVineSim ## Define 5-dimensional R-vine tree structure matrix Matrix <- c( 5, 2, 3, 1, 4, 0, 2, 3, 4, 1, 0, 0, 3, 4, 1, 0, 0, 0, 4, 1, 0, 0, 0, 0, 1 ) Matrix <- matrix(Matrix, 5, 5) ## Define R-vine pair-copula family matrix family <- c( 0, 1, 3, 4, 4, 0, 0, 3, 4, 1, 0, 0, 0, 4, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0 ) family <- matrix(family, 5, 5) ## Define R-vine pair-copula parameter matrix par <- c( 0, 0.2, 0.9, 1.5, 3.9, 0, 0, 1.1, 1.6, 0.9, 0, 0, 0, 1.9, 0.5, 0, 0, 0, 0, 4.8, 0, 0, 0, 0, 0 ) par <- matrix(par, 5, 5) ## Define second R-vine pair-copula parameter matrix par2 <- matrix(0, 5, 5) ## Define RVineMatrix object RVM <- RVineMatrix( Matrix = Matrix, family = family, par = par, par2 = par2, names = c("V1", "V2", "V3", "V4", "V5") ) ## Convert to gamVine object GVC <- RVM2GVC(RVM) ## U[0,1] random variates to be transformed to the copula sample n <- 1e2 d <- 5 U <- matrix(runif(n * d), nrow = n) ## The output of gamVineSimulate correspond to that of RVineSim sampleRVM <- RVineSim(n, RVM, U) sampleGVC <- gamVineSimulate(n, GVC, U) all.equal(sampleRVM, sampleGVC) ## Fit the two models and compare the estimated parameter fitRVM <- RVM2GVC(RVineSeqEst(sampleRVM, RVM)) fitGVC <- gamVineSeqFit(sampleGVC, GVC) all.equal( simplify2array(attr(fitRVM, "model")), simplify2array(attr(fitGVC, "model")) )require(VineCopula) ## Example adapted from RVineSim ## Define 5-dimensional R-vine tree structure matrix Matrix <- c( 5, 2, 3, 1, 4, 0, 2, 3, 4, 1, 0, 0, 3, 4, 1, 0, 0, 0, 4, 1, 0, 0, 0, 0, 1 ) Matrix <- matrix(Matrix, 5, 5) ## Define R-vine pair-copula family matrix family <- c( 0, 1, 3, 4, 4, 0, 0, 3, 4, 1, 0, 0, 0, 4, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0 ) family <- matrix(family, 5, 5) ## Define R-vine pair-copula parameter matrix par <- c( 0, 0.2, 0.9, 1.5, 3.9, 0, 0, 1.1, 1.6, 0.9, 0, 0, 0, 1.9, 0.5, 0, 0, 0, 0, 4.8, 0, 0, 0, 0, 0 ) par <- matrix(par, 5, 5) ## Define second R-vine pair-copula parameter matrix par2 <- matrix(0, 5, 5) ## Define RVineMatrix object RVM <- RVineMatrix( Matrix = Matrix, family = family, par = par, par2 = par2, names = c("V1", "V2", "V3", "V4", "V5") ) ## Convert to gamVine object GVC <- RVM2GVC(RVM) ## U[0,1] random variates to be transformed to the copula sample n <- 1e2 d <- 5 U <- matrix(runif(n * d), nrow = n) ## The output of gamVineSimulate correspond to that of RVineSim sampleRVM <- RVineSim(n, RVM, U) sampleGVC <- gamVineSimulate(n, GVC, U) all.equal(sampleRVM, sampleGVC) ## Fit the two models and compare the estimated parameter fitRVM <- RVM2GVC(RVineSeqEst(sampleRVM, RVM)) fitGVC <- gamVineSeqFit(sampleGVC, GVC) all.equal( simplify2array(attr(fitRVM, "model")), simplify2array(attr(fitGVC, "model")) )
This function select the structure and estimates the parameter(s) of a
Generalized Additive model
(GAM) Vine model, where GAMs for individual edges are specified either for
the copula parameter or Kendall's tau.
It solves the maximum penalized likelihood estimation for the copula families
supported in this package by reformulating each Newton-Raphson iteration as
a generalized ridge regression, which is solved using
the mgcv package.
gamVineStructureSelect( udata, lin.covs = NULL, smooth.covs = NULL, simplified = TRUE, type = 0, familyset = NA, rotations = TRUE, familycrit = "AIC", treecrit = "tau", level = 0.05, trunclevel = NA, tau = TRUE, method = "FS", tol.rel = 0.001, n.iters = 10, parallel = FALSE, verbose = FALSE, select.once = TRUE )gamVineStructureSelect( udata, lin.covs = NULL, smooth.covs = NULL, simplified = TRUE, type = 0, familyset = NA, rotations = TRUE, familycrit = "AIC", treecrit = "tau", level = 0.05, trunclevel = NA, tau = TRUE, method = "FS", tol.rel = 0.001, n.iters = 10, parallel = FALSE, verbose = FALSE, select.once = TRUE )
udata |
A matrix or data frame containing the data in [0,1]^d. |
lin.covs |
A matrix or data frame containing the parametric (i.e.,
linear) covariates (default: |
smooth.covs |
A matrix or data frame containing the non-parametric
(i.e., smooth) covariates (default: |
simplified |
If |
type |
|
familyset |
An integer vector of pair-copula families to select from
(the independence copula MUST NOT be specified in this vector unless one
wants to fit an independence vine!).
Not listed copula families might be included to better handle
limit cases. If |
rotations |
If |
familycrit |
Character indicating the criterion for bivariate copula
selection. Possible choices: |
treecrit |
Character indicating how pairs are selected in each tree.
|
level |
Numerical; Passed to |
trunclevel |
Integer; level of truncation. |
tau |
|
method |
|
tol.rel |
Relative tolerance for |
n.iters |
Maximal number of iterations for
|
parallel |
|
verbose |
|
select.once |
if |
gamVineSeqFit returns a gamVine-class object.
gamVineSeqFit,gamVineCopSelect,
gamVine-class, gamVineSimulate and
gamBiCopSelect.
require(VineCopula) set.seed(0) ## An example with a 3-dimensional GAM-Vine # Sample size n <- 1e3 # Define a R-vine tree structure matrix d <- 3 Matrix <- c(2, 3, 1, 0, 3, 1, 0, 0, 1) Matrix <- matrix(Matrix, d, d) nnames <- paste("x", 1:d, sep = "") # Copula families for each edge fam <- c(301, 401, 1) # Parameters for the first tree (two unconditional copulas) par <- c(1, 2) # Pre-allocate the GAM-Vine model list count <- 1 model <- vector(mode = "list", length = d * (d - 1) / 2) # The first tree contains only the two unconditional copulas for (i in 1:(d - 1)) { model[[count]] <- list(family = fam[count], par = par[count], par2 = 0) count <- count + 1 } # The second tree contains a unique conditional copula # In this first example, we take a linear calibration function (10*x-5) # Set-up a dummy dataset tmp <- data.frame(u1 = runif(1e2), u2 = runif(1e2), x1 = runif(1e2)) # Set-up an arbitrary linear model for the calibration function model[[count]] <- gamBiCopFit(tmp, ~x1, fam[count])$res # Update the coefficients of the model attr(model[[count]], "model")$coefficients <- c(-5, 10) # Define gamVine object GVC <- gamVine(Matrix = Matrix, model = model, names = nnames) GVC ## Not run: # Simulate new data simData <- data.frame(gamVineSimulate(n, GVC)) colnames(simData) <- nnames # Fit data using sequential estimation assuming true model known summary(fitGVC <- gamVineSeqFit(simData, GVC)) # Fit data using structure selection and sequential estimation summary(fitGVC2 <- gamVineStructureSelect(simData, simplified = FALSE)) ## End(Not run)require(VineCopula) set.seed(0) ## An example with a 3-dimensional GAM-Vine # Sample size n <- 1e3 # Define a R-vine tree structure matrix d <- 3 Matrix <- c(2, 3, 1, 0, 3, 1, 0, 0, 1) Matrix <- matrix(Matrix, d, d) nnames <- paste("x", 1:d, sep = "") # Copula families for each edge fam <- c(301, 401, 1) # Parameters for the first tree (two unconditional copulas) par <- c(1, 2) # Pre-allocate the GAM-Vine model list count <- 1 model <- vector(mode = "list", length = d * (d - 1) / 2) # The first tree contains only the two unconditional copulas for (i in 1:(d - 1)) { model[[count]] <- list(family = fam[count], par = par[count], par2 = 0) count <- count + 1 } # The second tree contains a unique conditional copula # In this first example, we take a linear calibration function (10*x-5) # Set-up a dummy dataset tmp <- data.frame(u1 = runif(1e2), u2 = runif(1e2), x1 = runif(1e2)) # Set-up an arbitrary linear model for the calibration function model[[count]] <- gamBiCopFit(tmp, ~x1, fam[count])$res # Update the coefficients of the model attr(model[[count]], "model")$coefficients <- c(-5, 10) # Define gamVine object GVC <- gamVine(Matrix = Matrix, model = model, names = nnames) GVC ## Not run: # Simulate new data simData <- data.frame(gamVineSimulate(n, GVC)) colnames(simData) <- nnames # Fit data using sequential estimation assuming true model known summary(fitGVC <- gamVineSeqFit(simData, GVC)) # Fit data using structure selection and sequential estimation summary(fitGVC2 <- gamVineStructureSelect(simData, simplified = FALSE)) ## End(Not run)
Function to extract the log-likelihood from an object of the class
gamBiCop (note that the models are
usually fitted by penalized likelihood maximization).
This function is used by AIC and BIC.
## S4 method for signature 'gamBiCop' logLik(object, ...)## S4 method for signature 'gamBiCop' logLik(object, ...)
object |
An object of the class
|
... |
un-used in this class |
Standard logLik object: see logLik.
Extract the number of 'observations' from a model fit.
This is principally intended to be used in computing the BIC
(see AIC).
## S4 method for signature 'gamBiCop' nobs(object, ...)## S4 method for signature 'gamBiCop' nobs(object, ...)
object |
An object of the class
|
... |
un-used in this class |
A single number, normally an integer.
Plot from an object of the class
gamBiCop.
The function is based on (see plot.gam
from mgcv).
## S4 method for signature 'gamBiCop,ANY' plot(x, y, ...)## S4 method for signature 'gamBiCop,ANY' plot(x, y, ...)
x |
An object of the class
|
y |
Not used with this class. |
... |
additional arguments to be passed to |
This function simply generates plots.
Plot an object of the class
gamVine.
The function is based on (see plot.gam
from mgcv).
## S4 method for signature 'gamVine,ANY' plot(x, y, ...)## S4 method for signature 'gamVine,ANY' plot(x, y, ...)
x |
An object of the class
|
y |
Not used with this class. |
... |
additional arguments to be passed to |
This function simply generates plots.
Transform an object of the class RVineMatrix
into an object of the class gamVine.
RVM2GVC(RVM)RVM2GVC(RVM)
RVM |
An object of the class |
An object of the class
gamVine.
RVineMatrix and
gamVine.
Takes a gamBiCop object and produces
various useful summaries from it.
## S4 method for signature 'gamBiCop' summary(object, ...)## S4 method for signature 'gamBiCop' summary(object, ...)
object |
An object of the class
|
... |
unused in this class |
A useful summary (see summary.gam
from mgcv for more details).
summary.gam
from mgcv
Takes an object of the class
gamVine and produces various
useful summaries from it.
## S4 method for signature 'gamVine' summary(object, ...)## S4 method for signature 'gamVine' summary(object, ...)
object |
An object of the class
|
... |
unused in this class |
A useful summary (see summary.gam
from mgcv for more details).
summary.gam
from mgcv