Export fitted regression splines (constructed by 'bs' or 'ns') as piecewise polynomials

前端 未结 1 1840
栀梦
栀梦 2020-12-06 08:14

Take for instance the following one-knot, degree two, spline:

library(splines)
library(ISLR)
fit.spline <- lm(wage~bs(age, knots=c(42), degree=2), data=Wa         


        
相关标签:
1条回答
  • 2020-12-06 08:32

    I was constantly asked to wrap up the idea in my original answer into a user-friendly function, able to reparametrize a fitted linear or generalized linear model with a bs or ns term. Eventually I rolled out a small R package SplinesUtils at https://github.com/ZheyuanLi/SplinesUtils (with a PDF version package manual). You can install it via

    ## make you have `devtools` package avaiable
    devtools::install_github("ZheyuanLi/SplinesUtils")
    

    The function to be used here is RegBsplineAsPiecePoly.

    library(SplinesUtils)
    
    library(splines)
    library(ISLR)
    fit.spline <- lm(wage ~ bs(age, knots=c(42), degree=2), data = Wage)
    
    ans1 <- RegBsplineAsPiecePoly(fit.spline, "bs(age, knots = c(42), degree = 2)")
    ans1
    #2 piecewise polynomials of degree 2 are constructed!
    #Use 'summary' to export all of them.
    #The first 2 are printed below.
    #8.2e-15 + 4.96 * (x - 18) + 0.0991 * (x - 18) ^ 2
    #61.9 + 0.2 * (x - 42) + 0.0224 * (x - 42) ^ 2
    
    ## coefficients as a matrix
    ans1$PiecePoly$coef
    #              [,1]        [,2]
    #[1,]  8.204641e-15 61.91542748
    #[2,]  4.959286e+00  0.20033307
    #[3,] -9.914485e-02 -0.02240887
    
    ## knots
    ans1$knots
    #[1] 18 42 80
    

    The function defaults to parametrize piecewise polynomials in shifted form (see ?PiecePoly). You can set shift = FALSE for a non-shifted version.

    ans2 <- RegBsplineAsPiecePoly(fit.spline, "bs(age, knots = c(42), degree = 2)",
                                  shift = FALSE)
    ans2
    #2 piecewise polynomials of degree 2 are constructed!
    #Use 'summary' to export all of them.
    #The first 2 are printed below.
    #-121 + 8.53 * x + 0.0991 * x ^ 2
    #14 + 2.08 * x + 0.0224 * x ^ 2
    
    ## coefficients as a matrix
    ans2$PiecePoly$coef
    #              [,1]        [,2]
    #[1,] -121.39007747 13.97219046
    #[2,]    8.52850050  2.08267822
    #[3,]   -0.09914485 -0.02240887
    

    You can predict the splines with predict.

    xg <- 18:80
    yg1 <- predict(ans1, xg)  ## use shifted form
    yg2 <- predict(ans2, xg)  ## use non-shifted form
    all.equal(yg1, yg2)
    #[1] TRUE
    

    But since there is an intercept in the model, the predicted values would differ from model prediction by the intercept.

    yh <- predict(fit.spline, data.frame(age = xg))
    intercept <- coef(fit.spline)[[1]]
    all.equal(yh, yg1 + intercept, check.attributes = FALSE)
    #[1] TRUE
    

    The package has summary, print, plot, predict and solve methods for a "PiecePoly" class. Explore the package for more.

    0 讨论(0)
提交回复
热议问题