5

I am trying to input matrix data into the brm() function to run a signal regression. brm is from the brms package, which provides an interface to fit Bayesian models using Stan. Signal regression is when you model one covariate using another within the bigger model, and you use the by parameter like this: model <- brm(response ~ s(matrix1, by = matrix2) + ..., data = Data). The problem is, I cannot input my matrices using the 'data' parameter because it only allows one data.frame object to be inputted.

Here are my code and the errors I obtained from trying to get around that constraint...

First off, my reproducible code leading up to the model-building:

library(brms)
#100 rows, 4 columns. Each cell contains a number between 1 and 10
Data <- data.frame(runif(100,1,10),runif(100,1,10),runif(100,1,10),runif(100,1,10))
#Assign names to the columns
names(Data) <- c("d0_10","d0_100","d0_1000","d0_10000")
Data$Density <- as.matrix(Data)%*%c(-1,10,5,1)
#the coefficients we are modelling
d <- c(-1,10,5,1) 
#Made a matrix with 4 columns with values 10, 100, 1000, 10000 which are evaluation points. Rows are repeats of the same column numbers
Bins <- 10^matrix(rep(1:4,times = dim(Data)[1]),ncol = 4,byrow =T)
Bins

As mentioned above, since 'data' only allows one data.frame object to be inputted, I've tried other ways of inputting my matrix data. These methods include:

1) making the matrix within the brm() function using as.matrix()

signalregression.brms <- brm(Density ~ s(Bins,by=as.matrix(Data[,c(c("d0_10","d0_100","d0_1000","d0_10000"))])),data = Data)
#Error in is(sexpr, "try-error") : 
  argument "sexpr" is missing, with no default

2) making the matrix outside the formula, storing it in a variable, then calling that variable inside the brm() function

Donuts <- as.matrix(Data[,c(c("d0_10","d0_100","d0_1000","d0_10000"))])
signalregression.brms <- brm(Density ~ s(Bins,by=Donuts),data = Data)
#Error: The following variables can neither be found in 'data' nor in 'data2':
'Bins', 'Donuts'

3) inputting a list containing the matrix using the 'data2' parameter

signalregression.brms <- brm(Density ~ s(Bins,by=donuts),data = Data,data2=list(Bins = 10^matrix(rep(1:4,times = dim(Data)[1]),ncol = 4,byrow =T),donuts=as.matrix(Data[,c(c("d0_10","d0_100","d0_1000","d0_10000"))])))
#Error in names(dat) <- object$term : 
  'names' attribute [1] must be the same length as the vector [0]

None of the above worked; each had their own errors and it was difficult troubleshooting them because I couldn't find answers or examples online that were of a similar nature in the context of brms.

I was able to use the above techniques just fine for gam(), in the mgcv package - you don't have to define a data.frame using 'data', you can call on variables defined outside of the gam() formula, and you can make matrices inside the gam() function itself. See below:

library(mgcv)
signalregression2 <- gam(Data$Density ~ s(Bins,by = as.matrix(Data[,c("d0_10","d0_100","d0_1000","d0_10000")]),k=3))
#Works!

It seems like brms is less flexible... :(

My question: does anyone have any suggestions on how to make my brm() function run?

Thank you very much!

Xia Zhu
  • 53
  • 4
  • `s(Bins,by=as.matrix(Data[,c(c("d0_10","d0_100","d0_1000","d0_10000"))]))` Is the output of this code correct and how it should be? – Ronak Shah Jun 22 '21 at 05:24
  • Hi! This smooth code works inside gam but not inside brms. My goal is to make it work inside the brm function. – Xia Zhu Jun 23 '21 at 14:39

1 Answers1

2

My understanding of signal regression is limited enough that I'm not convinced this is correct, but I think it's at least a step in the right direction. The problem seems to be that brm() expects everything in its formula to be a column in data. So we can get the model to compile by ensuring all the things we want are present in data:

library(tidyverse)
signalregression.brms = brm(Density ~
                              s(cbind(d0_10_bin, d0_100_bin, d0_1000_bin, d0_10000_bin),
                                by = cbind(d0_10, d0_100, d0_1000, d0_10000),
                                k = 3),
                            data = Data %>%
                              mutate(d0_10_bin = 10,
                                     d0_100_bin = 100,
                                     d0_1000_bin = 1000,
                                     d0_10000_bin = 10000))

Writing out each column by hand is a little annoying; I'm sure there are more general solutions.

For reference, here are my installed package versions:

map_chr(unname(unlist(pacman::p_depends(brms)[c("Depends", "Imports")])), ~ paste(., ": ", pacman::p_version(.), sep = ""))
 [1] "Rcpp: 1.0.6"           "methods: 4.0.3"        "rstan: 2.21.2"         "ggplot2: 3.3.3"       
 [5] "loo: 2.4.1"            "Matrix: 1.2.18"        "mgcv: 1.8.33"          "rstantools: 2.1.1"    
 [9] "bayesplot: 1.8.0"      "shinystan: 2.5.0"      "projpred: 2.0.2"       "bridgesampling: 1.1.2"
[13] "glue: 1.4.2"           "future: 1.21.0"        "matrixStats: 0.58.0"   "nleqslv: 3.3.2"       
[17] "nlme: 3.1.149"         "coda: 0.19.4"          "abind: 1.4.5"          "stats: 4.0.3"         
[21] "utils: 4.0.3"          "parallel: 4.0.3"       "grDevices: 4.0.3"      "backports: 1.2.1"
A. S. K.
  • 2,504
  • 13
  • 22
  • Thank you for your response! I tried the code but I got the same error as case #1 in my question: ```Error in is(sexpr, "try-error") : argument "sexpr" is missing, with no default. ```I suppose neither `as.matrix` nor `cbind` work inside brm formula... – Xia Zhu Jun 26 '21 at 22:37
  • Hmm, interesting - I got that error using the code posted in your question, but not with this code. What version of `brms` do you have? – A. S. K. Jun 27 '21 at 21:33
  • I have version 2.15.0 of `brms`, how about you? Also my RStudio is version 1.4.1717, in case that makes a difference! – Xia Zhu Jun 28 '21 at 15:17
  • Same here. Could it be one of `brms`'s dependencies? I've added a list to the answer. – A. S. K. Jun 28 '21 at 16:01
  • The package names are identical but the versions for some of them are different: (yours vs mine) "nlme: 3.1.149" vs "nlme: 3.1.152", "utils: 4.0.3" vs "utils: 4.0.5", "methods: 4.0.3" vs "methods: 4.0.5", "Matrix: 1.2.18" vs "Matrix: 1.3.2", "stats: 4.0.3" vs "stats: 4.0.5". Could these discrepancies change the `brm` functioning? – Xia Zhu Jun 28 '21 at 16:25
  • Maybe, but unfortunately I think we're now beyond my troubleshooting ability. [This post](https://discourse.mc-stan.org/t/argument-sexpr-is-missing-with-no-default/17710) suggests that including all the variables in the dataframe supplied to `data` ought to fix things; why it's not working with `cbind` on your end is beyond me! – A. S. K. Jun 28 '21 at 21:36
  • 1
    Hi! Thank you very much for your help! I realized I added an extra comma after the `k = 3` in my code and that was the reason why it wasn't working. But now my tidyverse code works! Really appreciate your answer, this is going to help anyone trying to do signal regression using brms :) – Xia Zhu Jun 29 '21 at 13:23