Search code examples
rmgcv

How do I generate spline bases from a character vector of response variables?


I am working on a problem where I need to fit many additive models of the form y ~ s(x), where the response y is constant whereas the predictor x varies between each model. I am using mgcv::smoothCon() to set up the bases, and lm() to fit the models. The reason why I do this, rather than calling gam() directly, is that I need the unpenalized fits. My problem is that smoothCon() requires it object argument to be unquoted, e.g., s(x), and I wonder how I can generated such unquoted arguments from a character vector of variable names.

A minimal example can be illustrated using the mtcars dataset. The following snippet shows what I am able to do at the moment:

library(mgcv)
# Variables for which I want to create a smooth term s(x)
responses <- c("mpg", "disp")
# At the moment, this is the only solution which I am able to make work
bs <- list(
  smoothCon(s(mpg), data = mtcars),
  smoothCon(s(disp), data = mtcars)
)

It would be nicer to be able to generate bs using some functional programming approach. I imagine something like this, where foo() is my missing link:

lapply(paste0("s(", responses, ")"), function(x) smoothCon(foo(x), 
data = mtcars))

I have tried noquote() and as.symbol(), but both fail.

responses <- c("mpg", "disp")
lapply(paste0("s(", responses, ")"), 
              function(x) smoothCon(noquote(x), data = mtcars))
#> Error: $ operator is invalid for atomic vectors

lapply(paste0("s(", responses, ")"), 
              function(x) smoothCon(as.symbol(x), data = mtcars))
#> Error: object of type 'symbol' is not subsettable

Solution

  • We can do this by converting to language class, evaluate and then apply the smoothCon

    library(tidyverse)
    out <- paste0("s(", responses, ")") %>%
              map(~ rlang::parse_expr(.x) %>% 
                       eval %>%
                      smoothCon(., data = mtcars))
    identical(out, bs)
    #[1] TRUE