Hi,
In addition to useful Ben's suggestion, you have a, possibly simpler,
alternative.
If you are willing to assume to know the power of you piecewise
polynomial (beta parameter according to code of Ben) you can use the
package segmented. Using the data generated by Ben in his previous
email, you get
olm<-lm(y~0+I(x^(-.5))) #note that 0 as the true model has not interc
os1<-segmented(olm,seg.Z=~x,psi=40)
Results are comparable with the ones returned by the nls() (even as
regard the St.Err of the breakpoint), although segmented returns a
somewhat smaller residual sum of squares :-)
***segmented() vs. nls(): some possibles differences***
1)In segmented, you are assuming to know the power of polynomial. In
practice you can try several different values such as {-1,-.5,1,2,3},
say, and to assess the fit.. However the St.Err from the other estimates
might be underestimated..
2)In segmented, you need to specify starting value only for the breakpoint.
3)In segmented, you can easy generalize the model: multiple breakpoints
and/or additional "linear" covariates and/or non-continuous response
and/or non-identity link functions (e.g. gamma with log-link)...
Hope this helps you,
vito
Ben Bolker ha scritto:
Joe Waddell <joecwaddell <at> gmail.com> writes:
Hi,
I am a biologist (relatively new to R) analyzing data which we predict
to fit a power function. I was wondering if anyone knew a way to model
piecewise functions in R, where across a range of values (0-x) the data
is modeled as a power function, and across another range (x-inf) it is a
linear function. This would be predicted by one of our hypotheses, and
we would like to find the AICs and weights for a piecewise function as
described, compared with a power function across the entire range.
I have looked into the polySpline function, however it appears to use
only polynomials, instead of the nls models I have been using. Thanks
in advance for any help you might be able to offer.
You should be able to do it in nls as follows ...
There are some potentially subtle issues if you get into
the details of likelihood profile confidence intervals
for the breakpoint (since the likelihood profile is flat
between/discontinuous across the locations of data points),
but hopefully that won't bite you in your applications.
## function to generate piecewise power-law/linear "data"
f <- function(x,brk,alpha,beta,b,sd) {
mu <- ifelse(x<brk,alpha*x^beta,(alpha*brk^beta)-b*(x-brk))
rnorm(length(x),mean=mu,sd=sd)
}
## generate "data"
set.seed(1001)
x <- runif(1000,max=100)
y <- f(x,brk=50,alpha=100,beta=-0.5,b=1,sd=5)
## take a quick look, vs. theoretical curve
plot(y~x)
curve(f(x,50,100,-0.5,1,0),col=2,add=TRUE,n=1000,lwd=2)
## fit, using the "I()" command to do the piecewise part
dat <- data.frame(x,y)
fit1 <- nls(y~I(x<brk)*alpha*x^beta+I(x>brk)*((alpha*brk^beta)-b*(x-brk)),
start=list(brk=60,alpha=110,beta=-0.75,b=2),data=dat)
## plot the fit
xvec <- seq(0,100,length=200)
lines(xvec,predict(fit1,newdata=data.frame(x=xvec)),col=4,lwd=2)
## testing ...
with(as.list(coef(fit1)),
lines(xvec,f(xvec,brk,alpha,beta,b,sd=0),col=5,lwd=2))
Ben Bolker
______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
--
====================================
Vito M.R. Muggeo
Dip.to Sc Statist e Matem `Vianelli'
Università di Palermo
viale delle Scienze, edificio 13
90128 Palermo - ITALY
tel: 091 6626240
fax: 091 485726/485612
http://dssm.unipa.it/vmuggeo
______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.