R/midas_nlpr_methods.R

Defines functions R2.np plot_lstr plot_midas_coef.midas_nlpr coef.midas_nlpr predict.midas_nlpr print.summary.midas_nlpr deviance.midas_nlpr summary.midas_nlpr print.midas_nlpr fitted.midas_nlpr

Documented in coef.midas_nlpr deviance.midas_nlpr fitted.midas_nlpr plot_lstr plot_midas_coef.midas_nlpr predict.midas_nlpr

##' Fitted values for non-linear parametric MIDAS regression model
##'
##' Returns the fitted values of a fitted non-linear parametric MIDAS regression object
##' @param object a \code{\link{midas_r}} object
##' @param ... currently nothing
##' @return the vector of fitted values
##' @author Virmantas Kvedaras, Vaidotas Zemlys
##' @rdname fitted.midas_nlpr
##' @export
##' @method fitted midas_nlpr
fitted.midas_nlpr <- function(object, ...) {
    as.numeric(object$rhs(coef(object)))
}

##' @export
##' @method print midas_nlpr
print.midas_nlpr <- function(x, digits=max(3,getOption("digits")-3),...) {
    #Code adapted from dynln:::print.dynlm code
    model_string <-  "\nNon-linear parametric MIDAS regression model with \""
    cat(paste(model_string, class(x$lhs)[1], 
              "\" data:\n", sep = ""))
    cat(paste("Start = ", x$lhs_start, 
              ", End = ", x$lhs_end, 
              "\n", sep = ""))
    cat(" model:", deparse(formula(x)),"\n")
    print(coef(x),digits = digits, ...)
    cat("\n")
    cat("Function", x$argmap_opt$Ofunction, "was used for fitting\n")
    invisible(x)
}


##' @export
##' @importFrom stats deviance pt pnorm residuals printCoefmat
##' @method summary midas_nlpr
summary.midas_nlpr <- function(object, df=NULL, ...) {
    r <- as.vector(residuals(object))
    param <- coef(object)
    pnames <- names(param)
    n <- length(r)
    p <- length(param)
    rdf <- n - p
    
    resvar <- deviance(object)/rdf
    
    dg <- jacobian(object$rhs, param)
    V <- resvar * ginv(crossprod(dg)/nrow(dg))/n
    
    colnames(V) <- pnames
    rownames(V) <- pnames
   
    se <- sqrt(diag(V)) 
       
    f <- as.vector(object$fitted.values)
    mss <- if (attr(object$terms, "intercept")) 
        sum((f - mean(f))^2)
    else sum(f^2)
    rss <- sum(r^2)
    
    n <- length(r)
    p <- length(coef(object))
    rdf <- n-p
    df.int <- if (attr(object$terms, "intercept")) 1L
    else 0L
    
    r_squared <- R2.np(object$model[,1], f)
    
    tval <- param/se
    
    #Code stolen from coeftest function
    if(is.null(df)) {
        df <- rdf
    }
    if (is.finite(df) && df > 0) {
        pval <- 2 * pt(abs(tval), df = df, lower.tail = FALSE)
        cnames <- c("Estimate", "Std. Error", "t value", "Pr(>|t|)")
        mthd <- "t"
    }
    else {
        pval <- 2 * pnorm(abs(tval), lower.tail = FALSE)
        cnames <- c("Estimate", "Std. Error", "z value", "Pr(>|z|)")
        mthd <- "z"
    }
    
    param <- cbind(param,se,tval,pval)
    dimnames(param) <- list(pnames, c("Estimate", "Std. Error", 
                                      "t value", "Pr(>|t|)"))
    ans <- list(formula=formula(object$terms), residuals=r, sigma=sqrt(resvar),
                df=c(p,rdf), cov.unscaled = V/resvar, call=object$call,
                coefficients=param,midas_coefficients=coef(object, midas = TRUE),
                r_squared = r_squared, lhs_start = object$lhs_start, lhs_end = object$lhs_end, class_lhs = class(object$lhs))
    class(ans) <- "summary.midas_nlpr"
    ans
}

##' Non-linear parametric MIDAS regression model deviance
##'
##' Returns the deviance of a fitted MIDAS regression object
##' @param object a \code{\link{midas_r}} object
##' @param ... currently nothing
##' @return The sum of squared residuals
##' @author Virmantas Kvedaras, Vaidotas Zemlys
##' @rdname deviance.midas_nlpr
##' @method deviance midas_nlpr
##' @export
deviance.midas_nlpr <- function(object,...) {
    sum(residuals(object)^2,na.rm=TRUE)
}

##' @export
##' @method print summary.midas_nlpr
print.summary.midas_nlpr <- function(x, digits=max(3, getOption("digits") - 3 ), signif.stars = getOption("show.signif.stars"), ...) {
    cat(paste("\nNon linear parametric MIDAS regression model with \"", x$class_lhs[1], 
              "\" data:\n", sep = ""))
    cat(paste("Start = ", x$lhs_start, 
              ", End = ", x$lhs_end, 
              "\n", sep = ""))
    cat("\n Formula", deparse(formula(x)),"\n")
    df <- x$df
    rdf <- df[2L]
    cat("\n Parameters:\n")
    printCoefmat(x$coefficients,digits=digits,signif.stars=signif.stars,...)
    cat("\n Residual standard error:", format(signif(x$sigma,digits)), "on", rdf , "degrees of freedom\n")
    #   cat(" Multiple R-squared: ", formatC(x$r_squared, digits = digits))
    #   cat(",\tAdjusted R-squared: ", formatC(x$adj_r_squared, digits = digits),"\n")
    invisible(x)
}

##' Predicted values based on \code{midas_nlpr} object.
##'
##' \code{predict.midas_nlpr} produces predicted values, obtained by evaluating regression function in the frame \code{newdata}. This means that the appropriate model matrix is constructed using only the data in \code{newdata}. This makes this function not very convenient for forecasting purposes. If you want to supply the new data for forecasting horizon only use the function \link{forecast.midas_r}. Also this function produces only static predictions, if you want dynamic forecasts use the \link{forecast.midas_r}.
##' 
##' @title Predict method for non-linear parametric MIDAS regression fit
##' @param object \code{\link{midas_nlpr}} object
##' @param newdata a named list containing data for mixed frequencies. If omitted, the in-sample values are used.
##' @param na.action function determining what should be done with missing values in \code{newdata}. The most likely cause of missing values is the insufficient data for the lagged variables. The default is to omit such missing values.
##' @param ... additional arguments, not used
##' @return a vector of predicted values
##' @author Virmantas Kvedaras, Vaidotas Zemlys
##' @method predict midas_nlpr
##' @rdname predict.midas_nlpr
##' @export
predict.midas_nlpr <- function(object, newdata, na.action = na.omit, ... ) {
    Zenv <- new.env(parent=parent.frame())
    
    if(missing(newdata))
        return(as.vector(fitted(object)))
    else {
        ee <- data_to_env(newdata)    
        ZZ <- object$Zenv    
        parent.env(ee) <- ZZ
    }
    
    assign("ee",ee,Zenv)
    cll <- match.call()
    mf <- match.call(expand.dots = FALSE)
    m <- match(c("object", "newdata"), names(mf), 0L)
    mf <- mf[c(1L, m)]
    mf[[1L]] <- as.name("model.frame")
    Terms <- delete.response(terms(object))
    mf[[2L]] <- Terms    
    mf[[3L]] <- as.name("ee")   
    mf[[4L]] <- na.action
    names(mf)[c(2,3,4)] <- c("formula","data","na.action")
    
    mf <- eval(mf,Zenv)
    mt <- attr(mf, "terms")
    
    X <- model.matrix(mt, mf) 
    
    rhs <- object$rhs
    
    environment(rhs)$X <- X
    xind1 <- environment(rhs)$xind1
    environment(rhs)$X1 <- X[, xind1]
    
    as.vector(rhs(coef(object)))
}

##' Extracts various coefficients of MIDAS regression
##'
##' MIDAS regression has two sets of cofficients. The first set is the coefficients associated with the parameters
##' of weight functions associated with MIDAS regression terms. These are the coefficients of the NLS problem associated with MIDAS regression.
##' The second is the coefficients of the linear model, i.e  the values of weight
##' functions of terms, or so called MIDAS coefficients. By default the function returns the first set of the coefficients.
##' 
##' @title Extract coefficients of MIDAS regression
##' @param object \code{midas_nlpr} object
##' @param type one of plain, midas, or nlpr. Returns appropriate coefficients.
##' @param term_names a character vector with term names. Default is \code{NULL}, which means that coefficients of all the terms are returned
##' @param ... not used currently
##' @return a vector with coefficients
##' @author Vaidotas Zemlys
##' @method coef midas_nlpr
##' @rdname coef.midas_nlpr
##' @export
coef.midas_nlpr <- function(object, type = c("plain", "midas", "nlpr"), term_names = NULL, ...) {
    type <- match.arg(type)
    if (is.null(term_names) & type != "plain") stop("Please provide a term name to get midas or nlpr type coefficients")
    if (is.null(term_names)) {
        return(object$coefficients)
    } else {
        if (length(setdiff(term_names,names(object$term_info))) > 0) stop("Some of the term names are not present in estimated MIDAS regression")
        if (type == "plain") {
            res <- lapply(object$term_info[term_names], function(x) {
                if (is.null(x[["nlpr"]])) object$coefficients[x$coef_index]
                else object$coefficients[x$coef_index][x$param_map$r]
            })
        }  
        if (type == "midas") {
            res <- lapply(object$term_info[term_names], function(x) {
                 if (is.null(x[["nlpr"]]))  x$weight(object$coefficients[x$coef_index])
                 else x$weight(object$coefficients[x$coef_index][x$param_map$r])
            })
        }
        if (type == "nlpr") {
            cf <- coef(object, type = "plain", term_name = NULL)
            res <- lapply(object$term_info[term_names], function(x) {
                if (is.null(x[["nlpr"]]))  stop("The term ", x$term_name, " is not a non-linear parametric term")
                else cf[x$coef_index][x$param_map$nlpr]
            })
        }
        
        
        names(res) <- NULL
        if (length(res) == 1) return(res[[1]])
        else return(unlist(res))
            
    }
}

##' @include midas_r_methods.R
setMethod("extract", signature = className("midas_nlpr", "midasr"), definition = extract.midas_r)


##' Plots MIDAS coefficients of a MIDAS regression for a selected term.
##'
##' Plots MIDAS coefficients of a selected MIDAS regression term together with corresponding MIDAS coefficients and their confidence intervals
##' of unrestricted MIDAS regression
##' @title Plot MIDAS coefficients
##' @param x \code{midas_r} object
##' @param term_name the term name for which the coefficients are plotted. Default is \code{NULL}, which selects the first MIDAS term
##' @param title the title string of the graph. The default is \code{NULL} for the default title.
##' @param compare the parameters for weight function to compare with the model, default is NULL
##' @param normalize logical, if FALSE use the weight from the model, if TRUE, set the normalization coefficient of the weight function to 1.
##' @param ... not used
##' @return a data frame with restricted MIDAS coefficients, unrestricted MIDAS coefficients and lower and upper confidence interval limits. The data
##' frame is returned invisibly.
##' @author Virmantas Kvedaras, Vaidotas Zemlys
##' @importFrom graphics plot points
##' @importFrom numDeriv jacobian
##' @importFrom stats na.omit
##' @method plot_midas_coef midas_nlpr
##' @rdname plot_midas_coef.midas_nlpr
##' @export
plot_midas_coef.midas_nlpr <- function(x, term_name = NULL, title = NULL, compare = NULL, normalize = FALSE, ...) {
    if(is.null(term_name)) {
        wt <- do.call("rbind",lapply(x$term_info,function(l)c(l$term_name,l$weight_name)))
        wt <- data.frame(wt, stringsAsFactors = FALSE)
        colnames(wt) <- c("term_name","weight_name")
        wt <- wt[wt$weight_name != "", ]
        if (nrow(wt) == 0) stop("No terms with MIDAS weights in midas_r object")
        if (nrow(wt) > 1) warning("Multiple terms with MIDAS weights, choosing the first one. Please specify the desired term name via 'term_name' argument.")
        term_name <- wt$term_name[1]
    }
    ti <- x$term_info[[term_name]]
   
    mcoef <- coef(x, type = "midas", term_name = term_name)
    pcoef <- coef(x, type = "plain", term_name = term_name)
    
    sx <- summary(x)
    V <- sx$cov.unscaled * sx$sigma^2
    ti <- x$term_info[[term_name]]
    if (is.null(ti$nlpr)) {
        Vind <- ti$coef_index
    } else {
        Vind <- ti$coef_index[ti$param_map$r]
    }
    
    wfun <- ti$weight
    if (normalize) {
        nc <- find_normalisation_coefficient(wfun, pcoef)
        if (length(nc) == 0) stop("Weight restriction seems to not have normalization")
        pcoef0 <- pcoef
        mcoef <- mcoef/pcoef[nc]
        pcoef <- pcoef[-nc]
        Vind <- Vind[-nc]
        wfun <- function(p) {
            pp <- rep(NA, length(p) + 1)
            pp[nc] <- 1
            pp[-nc] <- p
            ti$weight(pp) 
        }
    }
    
    grad_r <- jacobian(wfun, pcoef)
    V_s <- V[Vind, Vind]
    se_r <- sqrt(diag(grad_r %*% V_s %*% t(grad_r)))
    pd <- data.frame(restricted = mcoef, compare = NA, lower = mcoef - 1.96*se_r, upper = mcoef + 1.96*se_r, lag_struct = ti$lag_structure)
    
    if (!is.null(compare)) {
        pd$compare <- wfun(compare)
    }
    
    ylim <- range(na.omit(c(pd[,1], pd[,2], pd[,3], pd[,4])))
    plot(pd$lag_struct, pd$restricted, col = "blue", ylab = "MIDAS coefficients", xlab = "High frequency lag", ylim = ylim)
    
    points(pd$lag_struct, pd$compare, col = "black") 
    points(pd$lag_struct, pd$lower, type = "l", col = "grey", lty = 2)
    points(pd$lag_struct, pd$upper, type = "l", col = "grey", lty = 2)
    
    if (is.null(title)) {
        title(main = paste0("MIDAS coefficients for term ",term_name,": ",ti$weight_name))
    } else title(main = title) 
    
    invisible(pd)
}

##' Plots logistic function for LSTR MIDAS regression
##'
##' Plots logistic function for LSTR MIDSAS regression
##' of unrestricted MIDAS regression
##' @title Plot MIDAS coefficients
##' @param x \code{midas_r} object
##' @param term_name the term name for which the coefficients are plotted. Default is \code{NULL}, which selects the first MIDAS term
##' @param title the title string of the graph. The default is \code{NULL} for the default title.
##' @param compare the parameters for weight function to compare with the model, default is NULL
##' @param ... not used
##' @return a data frame with restricted MIDAS coefficients, unrestricted MIDAS coefficients and lower and upper confidence interval limits. The data
##' frame is returned invisibly.
##' @author Virmantas Kvedaras, Vaidotas Zemlys
##' @importFrom graphics plot points
##' @importFrom numDeriv jacobian
##' @importFrom stats na.omit
##' @export
plot_lstr <- function(x, term_name, title = NULL,  compare = NULL, ... ) {
    ti <- x$term_info[[term_name]]
    
    if (is.null(ti) && is.null(ti$nlpr)) stop("Please provide the name of the term which is nlpr term")
    
    sx <- summary(x)
    cf <- coef(x)
    r_map <- ti$coef_index[ti$param_map$r]
    n_map <- ti$coef_index[ti$param_map$nlpr[-2:-1]]
    Vind <- c(r_map,n_map)  
  
    tfun <- function(p) {
        ri <- 1:length(r_map)
        pr <- p[ri]
        pn <- p[-ri]
        as.vector(lstr_G(x$model[, ti$midas_coef_index + 1], ti$weight(pr), pn, ti$sd_x))
    }
    
    sx <- summary(x)
    V <- sx$cov.unscaled * sx$sigma^2
    
    
    grad_r <- jacobian(tfun, cf[Vind])
    
    V_s <- V[Vind, Vind]
    se_r <- sqrt(diag(grad_r %*% V_s %*% t(grad_r)))
    
    xi <- as.vector(x$model[, ti$midas_coef_index + 1] %*% ti$weight(cf[ti$coef_index][ti$param_map$r]))
    
    ixi <- order(xi)
    
    nt <- tfun(cf[Vind])
    
    xi_o <- xi[ixi]
    nt_o <- nt[ixi]
    se_ro <- se_r[ixi]
    
    pd <- data.frame(xi = xi_o, term = nt_o, compare = NA, lower = nt_o - 1.96*se_ro, upper = nt_o + 1.96*se_ro, xi2 = NA)
   
    if (!is.null(compare)) {
        op <- rep(NA, length(Vind))
        op[1:length(r_map)] <- compare$r
        op[-(1:length(r_map))] <- compare$lstr
        xi2 <- as.vector(x$model[, ti$midas_coef_index + 1] %*% ti$weight(op[1:length(r_map)]))
        ixi2 <- order(xi2)
        pd$compare <- tfun(op)[ixi2]
        
        pd$xi2 <-  xi2[ixi2]
    }
    
    ylim <- range(na.omit(c(pd$term,pd$compare, pd$lower, pd$upper)))
    
    plot(pd$xi, pd$term, col = "blue", ylab = "Logistic function", xlab = "MIDAS aggregate", ylim = ylim, type = "l")
    
    points(pd$xi2, pd$compare, col = "black", type = "l") 
    points(pd$xi, pd$lower, type = "l", col = "grey", lty = 2)
    points(pd$xi, pd$upper, type = "l", col = "grey", lty = 2)
    
    if (is.null(title)) {
        title(main = paste0("Logistic function of term ",term_name," with weight: ",ti$weight_name))
    } else title(main = title) 
    
    invisible(pd)
    
}

R2.np <- function(y, fit) {
    yc <- y - mean(y)
    fitc <- fit - mean(y)
    (sum(yc*fitc)^2)/(sum(yc^2)*sum(fitc^2))
}

Try the midasr package in your browser

Any scripts or data that you put into this service are public.

midasr documentation built on Feb. 23, 2021, 5:11 p.m.