Search code examples
rmatrix-multiplicationnon-linear-regression

"Error in ... %*% ... : non-conformable arguments" using own function in regression


I have a function Q(x|delta): R^n --> R for which I would like to fit a nonlinear quantile regression. The function Q(.) uses some matrix operations and it would be very complicated to do not use it. The problem is that it seems that the nlrq (nonlinear quantile regression) and the nls (non linear regression) do not work when there is matrix operations in the function used in the formula argument.

To illustrate, consider the simpler function F(x1,x2|a,b,c) which I can use in the formula argument for the nlrq and the nls functions when I do not use matrix operations, but which do not work in the formula argument when it was written with matrix operations.

    library('quantreg')

    ## Generating the data
    x1<- rnorm(200)
    x2<- rnorm(200)
    y<- 1+3*sin(x1)+2*cos(x2) +rnorm(200)
    Dat<- data.frame(y,x1,x2)

    ## The function F1 without matrix operation
    F1<- function(x_1, x_2, a, b,c){a+b*sin(x_1)+c*cos(x_2)}

    ## The function F2 with matrix operation
    F2<- function(x_1, x_2, a, b,c){t(c(1,sin(x_1),cos(x_2)))%*%c(a,b,c)}

    ## Both functions work perfectly
    F1(x_1=3, x_2=2, a=1, b=3,c=2)
    F2(x_1=3, x_2=2, a=1, b=3,c=2)

    ## But only F1 can be estimated by nls and nlrq
    nls_1<-nls(y ~ F1(x_1 = x1, x_2 = x2, a = 1, b, c),
               data = Dat, start = list(b = 3, c = 2))

    nlrq_1<-nlrq(y ~ F1(x_1 = x1, x_2 = x2, a = 1, b, c),
                 data = Dat, start = list(b = 3, c = 2), tau = 0.9)

    ## When F2 is used in the formula argument an error happens
    nls_2<-nls(y ~ F2(x_1 = x1, x_2 = x2, a = 1, b, c),
               data = Dat, start = list(b = 3, c = 2))

    nlrq_2<-nlrq(y ~ F2(x_1 = x1, x_2 = x2, a = 1, b, c),
                 data = Dat, start = list(b = 3, c = 2), tau = 0.9)

The error is Error in t(c(1, sin(x_1), cos(x_2))) %*% c(a, b, c) : non-conformable arguments. I believe that if someone manages to estimate F2 using matrix operations through nls and nlrq, I would be able to use the same solution in my other function.

The size of Dat is 200x3.

Thank you very much.


Solution

  • Your function F2() doesn't work for vector arguments x_1x_2, ... because c(...) is constructing only a long vector (not a matrix).
    See:

    F1(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2)
    F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2)
    

    result:

    #> F1(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2)
    #[1]  0.5910664 -3.1840601
    #> F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2)
    #error in t(c(1, sin(x_1), cos(x_2))) %*% c(a, b, c) :  ...
    

    The function nls() and nlrq() are sending vectors (i.e. columns from your dataframe Dat) to your functions F2() (resp. F1()).

    Here are some vectorized definitions of F2():

    # other definitions for F2()
    F2 <- function(x_1, x_2, a, b,c) cbind(1,sin(x_1),cos(x_2)) %*% c(a,b,c)
    F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2)
    
    F2 <- function(x_1, x_2, a, b,c) t(rbind(1,sin(x_1),cos(x_2))) %*% c(a,b,c)
    F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2)
    
    F2 <- function(x_1, x_2, a, b,c) colSums(rbind(1,sin(x_1),cos(x_2)) * c(a,b,c))
    F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2)
    
    F2 <- function(x_1, x_2, a, b,c) crossprod(rbind(1,sin(x_1),cos(x_2)), c(a,b,c))
    F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2)
    
    F2 <- function(x_1, x_2, a, b,c) tcrossprod(c(a,b,c), cbind(1,sin(x_1),cos(x_2)))
    F2(x_1=c(3,5), x_2=c(2,4), a=1, b=3,c=2)