The catch in piecewise linear regression is just making sure that the line segments intersect. One systematic approach is to define successive intercepts as the endpoint of the previous line segment.
Here we have 3 segments defined as
$$E(y|x<c_1) = a_1 + b_1*x$$
$$E(y|c_1\leq x < c_2) = a_2 + b_2*(x-c_1)$$
$$E(y|x \geq c_2) = a_3 + b_3*(x-c_2)$$
Here is some made-up sample data:
data={{0, 422.808}, {5, 420.478}, {10, 419.885}, {15, 409.099}, {20, 401.991}, {25, 392.784}, {30, 393.007}, {35, 389.866}, {40, 387.422}, {45, 379.185}, {50, 372.092}, {55, 371.027}, {60, 366.818}, {65, 357.419}, {70, 354.197}, {75, 360.306}, {80, 344.244}, {85, 335.323}, {90, 341.295}, {95, 332.923}, {100, 324.843}, {105, 317.478}, {110, 327.442}, {115, 323.628}, {120, 318.41}, {125, 308.144}, {130, 301.034}, {135, 290.368}, {140, 297.193}, {145, 280.523}, {150, 280.346}, {155, 280.226}, {160, 275.515}, {165, 256.107}, {170, 265.278}, {175, 256.207}, {180, 258.653}, {185, 250.39}, {190, 248.119}, {195, 243.037}, {200, 229.993}, {205, 233.597}, {210, 225.621}, {215, 225.956}, {220, 225.194}, {225, 202.891}, {230, 205.367}, {235, 195.868}, {240, 198.521}, {245, 190.676}, {250, 190.554}, {255, 186.289}, {260, 179.3}, {265, 169.817}, {270, 176.787}, {275, 167.459}, {280, 159.373}, {285, 148.818}, {290, 151.855}, {295, 153.478}, {300, 134.617}, {305, 131.247}, {310, 124.339}, {315, 117.13}, {320, 112.433}, {325, 118.728}, {330, 120.256}, {335, 121.561}, {340, 121.885}, {345, 120.332}, {350, 119.723}, {355, 121.307}, {360, 118.366}, {365, 126.8}, {370, 112.267}, {375, 129.264}, {380, 120.966}, {385, 118.512}, {390, 128.474}, {395, 111.953}, {400, 121.195}, {405, 109.736}, {410, 122.929}, {415, 124.296}, {420, 114.717}, {425, 113.587}, {430, 127.551}, {435, 118.699}, {440, 113.722}, {445, 121.305}, {450, 119.947}, {455, 116.325}, {460, 112.804}, {465, 121.835}, {470, 113.748}, {475, 113.579}, {480, 124.282}, {485, 118.15}, {490, 117.994}, {495, 117.481}, {500, 121.803}, {505, 122.779}, {510, 117.996}, {515, 120.409}, {520, 111.087}, {525, 122.412}, {530, 117.491}, {535, 117.528}, {540, 114.733}, {545, 116.949}, {550, 120.648}, {555, 123.045}, {560, 114.907}, {565, 119.423}, {570, 126.76}, {575, 129.451}, {580, 117.285}, {585, 123.121}, {590, 118.529}, {595, 113.142}, {600, 114.442}, {605, 118.918}, {610, 125.887}, {615, 116.258}, {620, 111.013}, {625, 114.41}, {630, 96.3528}, {635, 104.718}, {640, 106.042}, {645, 96.0105}, {650, 88.3762}, {655, 87.1887}, {660, 82.0769}, {665, 79.3052}, {670, 76.4389}, {675, 76.9792}, {680, 70.0337}, {685, 71.3829}, {690, 67.4005}, {695, 50.7625}, {700, 43.9277}, {705, 50.1198}, {710, 44.768}, {715, 42.2054}, {720, 45.803}, {725, 38.1361}, {730, 20.7952}, {735, 26.0742}, {740, 25.5816}, {745, 18.6975}, {750, 13.4672}};
Choose intercepts a2
and a3
as the prediction at each cut-point c1
and c2
.
(This is so the line segments intersect at the cut-points.)
a2 = a1 + b1 c1
a3 = a2 + b2 c2
(* Piecewise function *)
f = (a1 + b1 x) Boole[x < c1] + (a2 + b2 (x - c1)) Boole[c1 <= x < c2] +
(a3 + b3 (x - c2)) Boole[x >= c2]
nlm = NonlinearModelFit[data,
f, {{a1, 400}, {b1, -1}, {b2, 0}, {b3, -1}, {c1, 300}, {c2, 600}}, x]
Show[ListPlot[data], Plot[nlm[x], {x, 0, 750}, PlotStyle -> Red]]