Skip to content
Function Works
tidypredict_fit(), tidypredict_sql(), parse_model()
tidypredict_to_column() ✔*
tidypredict_test() ✔*
tidypredict_interval(), tidypredict_sql_interval()
parsnip

* Only for regression models with a single outcome.

mixOmics fits partial least squares models with pls() and spls(), and the discriminant analysis variants with plsda() and splsda(). All four collapse down to one set of regression coefficients per outcome, so the generated expression is a plain linear combination of the predictors.

For a single-outcome regression model, tidypredict_fit() returns one expression. For a model with multiple outcome columns it returns a named list of expressions, one per outcome. For the discriminant variants it returns a named list of class-probability expressions (the softmax of the predicted dummy outcomes, matching what plsmod predicts). Since those two cases return a list, tidypredict_to_column() and tidypredict_test() only work for single-outcome regression models.

The number of components (ncomp) is baked into the coefficients, and the sparse variants simply give the predictors that were not selected a coefficient of zero.

tidypredict_ functions

x <- as.matrix(mtcars[c("cyl", "disp", "hp", "drat")])
model <- mixOmics::pls(x, mtcars$mpg, ncomp = 2)
  • Create the R formula

    tidypredict_fit(model)
    #> 24.2937361352851 + (cyl * -0.889931447343478) + (disp * -0.0130565637350741) + 
    #>     (hp * -0.0228109587521556) + (drat * 2.1303277985918)
  • Add the prediction to the original table

    library(dplyr)
    
    mtcars %>%
      tidypredict_to_column(model) %>%
      glimpse()
    #> Rows: 32
    #> Columns: 12
    #> $ mpg  <dbl> 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 19…
    #> $ cyl  <dbl> 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4,
    #> $ disp <dbl> 160.0, 160.0, 108.0, 258.0, 360.0, 225.0, 360.0, 146.7, 
    #> $ hp   <dbl> 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180,
    #> $ drat <dbl> 3.90, 3.90, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.…
    #> $ wt   <dbl> 2.620, 2.875, 2.320, 3.215, 3.440, 3.460, 3.570, 3.190, 
    #> $ qsec <dbl> 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20.00, 
    #> $ vs   <dbl> 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
    #> $ am   <dbl> 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
    #> $ gear <dbl> 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4,
    #> $ carb <dbl> 4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2,
    #> $ fit  <dbl> 22.66417, 22.66417, 25.40424, 19.63776, 15.19254, 19.500…
  • Confirm that the results match the model’s predict() results

    tidypredict_test(model, mtcars)
    #> tidypredict test results
    #> Difference threshold: 1e-12
    #> 
    #>  All results are within the difference threshold

Discriminant analysis

plsda() and splsda() return one probability expression per class:

da_model <- mixOmics::splsda(as.matrix(iris[1:4]), iris$Species, ncomp = 2)

fit <- tidypredict_fit(da_model)
names(fit)
#> [1] "setosa"     "versicolor" "virginica"
fit[["setosa"]]
#> exp(0.391460011724113 + (Sepal.Length * -0.118750531861652) + 
#>     (Sepal.Width * 0.378311039737146) + (Petal.Length * -0.084556881358667) + 
#>     (Petal.Width * -0.16933234787912))/(exp(0.391460011724113 + 
#>     (Sepal.Length * -0.118750531861652) + (Sepal.Width * 0.378311039737146) + 
#>     (Petal.Length * -0.084556881358667) + (Petal.Width * -0.16933234787912)) + 
#>     exp(1.96606184899222 + (Sepal.Length * -0.0303959537594359) + 
#>         (Sepal.Width * -0.492023767406961) + (Petal.Length * 
#>         0.0179469395936271) + (Petal.Width * -0.0152407670638333)) + 
#>     exp(-1.35752186071634 + (Sepal.Length * 0.149146485621088) + 
#>         (Sepal.Width * 0.113712727669814) + (Petal.Length * 0.06660994176504) + 
#>         (Petal.Width * 0.184573114942953)))

parsnip

parsnip fitted models are also supported by tidypredict. The mixOmics engine of pls() works for both regression and classification:

library(parsnip)
library(plsmod)

p_model <- pls(num_comp = 2) %>%
  set_engine("mixOmics") %>%
  set_mode("regression") %>%
  fit(mpg ~ disp + hp + drat, data = mtcars)

tidypredict_fit(p_model)
#> 18.9698741155116 + (disp * -0.0183282632913477) + (hp * -0.0323705835435153) + 
#>     (drat * 2.80763705068415)

mixOmics models are fit from a numeric matrix, so a model fit directly can only refer to the matrix columns it was given. Categorical predictors therefore work through the parsnip interface, which keeps the formula around and lets the dummy columns be written in terms of the original factors:

cars <- transform(mtcars, gear = factor(gear))

c_model <- pls(num_comp = 2) %>%
  set_engine("mixOmics") %>%
  set_mode("regression") %>%
  fit(mpg ~ disp + hp + gear, data = cars)

tidypredict_fit(c_model)
#> 28.3990491890354 + (disp * -0.0212765260717577) + (hp * -0.0321040699674561) + 
#>     (ifelse(gear == "4", 1, 0) * 1.89118556186025) + (ifelse(gear == 
#>     "5", 1, 0) * 3.84388465523581)

Parse model spec

Here is an example of the model spec:

pm <- parse_model(model)
str(pm, 2)
#> List of 2
#>  $ general:List of 5
#>   ..$ model  : chr "mixo_pls"
#>   ..$ version: num 2
#>   ..$ type   : chr "regression"
#>   ..$ is_glm : num 0
#>   ..$ ncomp  : num 2
#>  $ terms  :List of 5
#>   ..$ :List of 4
#>   ..$ :List of 4
#>   ..$ :List of 4
#>   ..$ :List of 4
#>   ..$ :List of 4
#>  - attr(*, "class")= chr [1:3] "parsed_model" "pm_regression" "list"