Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fit a GAM model to several pairs of (x,y) variables

Tags:

r

I am trying to fit a GAM model to a dataset consisting of two pairs of (x,y) values i.e. (x1,y1) and (x2,y2) by first fitting the 1st pair and then moving to the second. When I call the gam function inside the ‘for’ loop, it gives an error “Not enough (non-NA) data to do anything meaningful”. I suspect this is something to do with the way I construct the x1, y1, x2 and y2 labels of the columns because outside the ‘for’ loop the gam function works.

Thank you!

library(mgcv)
#> Loading required package: nlme
#> This is mgcv 1.8-26. For overview type 'help("mgcv-package")'.
library(ggplot2)
library(tidyverse)

# create dataframe
x1 = seq(0, 50, by = 0.5)
y1 = dnorm(x1, mean = 22, sd = 5)
x2 = seq(0, 50, by = 0.5)
y2 = dnorm(x2, mean = 28, sd = 7)
df = cbind.data.frame(x1, y1, x2, y2)

# plot(c(x1,x2), c(y1,y2))

count = ncol(df)/2
for (i in 1:count) {
  x<-noquote(paste("x", i, sep = ""))
  y<-noquote(paste("y", i, sep = ""))
  print(x)  # test
  gam(y ~ s(x), data = df, method = "REML")   # this call doesn't work
}

gam(y1 ~ s(x1), data = df, method = "REML")   # this call works
like image 933
odar Avatar asked Nov 16 '25 10:11

odar


1 Answers

I have managed to figure out what the problem is. It turned out that my construction of xi and yi vars is causing the problem because then the y ~ s(x) is not of type “formula”. I had to construct the equation outside the gam function call, convert it to type “formula” and then use it in the gam call.

library(mgcv)
library(ggplot2)
library(tidyverse)

# create test dataframe
x1 = seq(0, 50, by = 0.5)
y1 = dnorm(x1, mean = 25, sd = 5)
x2 = seq(0, 50, by = 0.5)
y2 = dnorm(x2, mean = 29, sd = 7)
df = cbind.data.frame(x1, y1, x2, y2)

plot(c(df$x1,df$x2), c(df$y1,df$y2))

(count = ncol(df)/2)
for (i in 1:count) {
  # construct the formula to go into the "gam" function and convert it to type "formula" with the "as.formula" function
  part1 <- noquote(paste0("y", i))
  part2 <- paste0("~ s(")
  frag1 <- paste(part1, part2)
  part3 <- noquote(paste0("x", i))
  frag2 <- paste0(frag1, part3)
  frag3 <- paste0(frag2, ")")
  fmla <- as.formula(frag3)
  
  # fit the data
  gam_mod <- gam(formula = fmla, data = df, method = "REML")
  
  print(gam_mod)
}
like image 99
odar Avatar answered Nov 19 '25 05:11

odar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!