Search code examples
rcurve-fittingpolynomialsnonlinear-functionscoefficients

How to adjust coefficients for nonlinear curve fit using non-standard polynomial function in R


I am attempting to perform a polynomial regression on a set of data, whose plot looks like this

Plot 1

However, every time I perform this regression, I get a low R squared value even though the points seem tightly packed around a line. My guess for why this is happening is that r is using equation to fit the curve

First equation

(although I am not certain that the poly function actually uses this equation, that is just a guess), and this doesn't seem capable of generating a curve like that in the plot. To resolve this problem, I have written a new equation which seems to fit the data pretty well.

New Equation

After playing with the numbers for a bit, I generated the red curve on the plot 1 with values of beta_0 = 22, beta_one = 195, and beta_two = .001. I then run a regression on this equation and get a much more reasonable R squared value. The code for this plot and the regression are as follows:

plot(full_simulation_data$T_n_rt_tds~full_simulation_data$d_rt_tds, pch = 20, cex = .5, ylim = c(0,1000), xlim = c(.75,1))

curve((22+((x^195)/.001*x)), add = TRUE, col = "red")

summary(lm(full_simulation_data$T_n_rt_tds~I(22+((full_simulation_data$d_rt_tds^195)/(.001*full_simulation_data$d_rt_tds)))))

My question is twofold. One, is there a way that I can get R to automatically adjust these coefficients so that I don't have to fit the line by eyeballing it? Two, is there a way that the normal polynomial function can be fit to the data so that I don't have to invent new equations to fit the data?


Solution

  • Yes, R has the function nls to fit custom functions:

    #create fake data
    b0<-22
    b1<-195
    b2<-0.001
    x<-sort(runif(1000, 0, 1))
    y<-b0+x^b1/(b2*x)+ rnorm(1000, 2, 2)
    
    #fit model
    model<-nls(y~ beta0+x^beta1/(beta2*x), start=list(beta0=10, beta1=100, beta2=0.001))
    
    print(summary(model))
    #plot results
    plot(x, y)
    lines(x, predict(model, data.frame(x)), col="red")
    

    In the nls function, I have your function defined and provided a list of starting values for the parameters and allow R to solve. nls is a very powerful function and I suggest taking some time to read the documentation.