# [R] piecewise linear approximation

Rolf Turner r.turner at auckland.ac.nz
Thu Aug 30 03:04:43 CEST 2007

```On 30/08/2007, at 12:45 PM, Naxerova, Kamila wrote:

> Dear list,
>
> I have a series of data points which I want to approximate with
> exactly two
> linear functions. I would like to choose the intervals so that the
> total
> deviation from my fitted lines is minimal. How do I best do this?
>
> Thanks!
> Kamila

If you want to minimize the total ***squared*** deviations, then the
code that
I enclose below should do the trick for you.  If you really want to
minimize
the total (presumably absolute) deviation, then you'll have to adapt the
code a bit.

The argument ``b'' to the bsr() function is a vector of candidate
values for
the ``join point'', e.g. b <- seq(lo,hi,length=100), where lo and hi are
suitably chosen lower and upper bounds on the location of the join
point.

cheers,

Rolf Turner

bsr <- function(x,y,b) {
#
# Broken stick regression.
#
if(length(b)==1) {
x1 <- ifelse(x<=b,0,x-b)
temp <- lm(y~x+x1)
ss <- sum(resid(temp)^2)
rslt <- list(fit=temp,ss=ss,b=b)
class(rslt) <- "bsr"
return(rslt)
}
temp <- list()
for(v in b) {
x1 <- ifelse(x<=v,0,x-v)
fff <- lm(y~x+x1)
temp[[paste(v)]] <- sum(resid(fff)^2)
}
ss <- unname(unlist(temp))
v <- b[which.min(ss)]
x1 <- ifelse(x<=v,0,x-v)
rslt <- list(fit=lm(y~x+x1),ss=unname(unlist(temp)),
b=b,ss.min=min(ss),b.min=v)
class(rslt) <- "bsr"
rslt
}

===+===+===+===+===+===+===+===+===+===+===+===+===+===+===+===+===
+===+===

#
# Plot method for broken stick regressions.
#
fit <- x
if(cont) {
if(is.null(rr)) {
x <- fit\$fit\$model\$x
rr <- range(x)
}
xx <- seq(rr[1],rr[2],length=npts)
b  <- fit\$b.min
if(is.null(b)) b <- fit\$b
x1 <- ifelse(xx<=b,0,xx-b)
yh <- predict(fit\$fit,newdata=data.frame(x=xx,x1=x1))
} else {
xx <- fit\$fit\$model[,2]
yh <- predict(fit\$fit)
}