BookmarkSubscribeRSS Feed
Choose Language Hide Translation Bar
phystudent
Community Trekker

Segmented regression

Does anyone know how to perform a segmented regression and calculate the breakpoint (where the 2 lines meet) on JMP?

0 Kudos
1 ACCEPTED SOLUTION

Accepted Solutions
ms
Super User ms
Super User

Re: Segmented regression

As Dodo suggests, piecewise regression can be done with the Nonlinear platform. Below is an example based on the broken-stick example above.

 

 

New Table( "piecewise",
  Add Rows( 20 ),
  New Column( "X",
  Continuous,
  Set Values( [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] )
  ),
  New Column( "Y",
  Numeric,
  Set Values( [15, 12, 27, 31, 26, 31, 42, 47, 56, 56, 47, 46, 36, 44, 38, 35, 34, 35, 25, 19] )
  ),
  New Column( "Ypred",
  Numeric,
  Formula( Parameter( {a = 20, b = 1, c = -10, d = 10}, a + b * :X + c * (:X - d) * (:X > d) ) )
  )
);
Nonlinear( Y( :Y ), X( :Ypred ), Newton, Finish );

 

4 REPLIES 4

Re: Segmented regression

If it's a simple broken stick relationship, you could do something like this:

 

 

// Create a broken stick relationship with some noise;

x = [ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
y = [15, 12, 27, 31, 26, 31, 42, 47, 56, 56, 47, 46, 36, 44, 38, 35, 34, 35, 25, 19];

expr_FX  = expr(a + b*x + c*(x-d):*(x>d));
expr_SSE = expr(sum((y-expr_FX)^2));

// Supply a set of starting values;
a = 20; b = 1; c = -10; d = 15;
print("Starting values:");
show(a, b, c, d);

sse = minimize(expr_SSE, {a, b, c, d}, << tolerance(1e-5));
print("Final estimates:");
show(a, b, c, d);
show(eval(expr_FX));

 

 

I've based the above on the Least Squares Example in the JMP 10 Manual, Chapter 8, substituting a broken stick relationship in the expression for the exponential model in the example.  The break point will be parameter d, as that's the x value at which the slope of the line changes.  Note that when you multiply the two matrices (x-d) and (x>d) together, you'll need the element-wise product :* as opposed to a simple multiplication.  You'll also probably need a relatively good starting value for the break point for the expression to converge.  In this example, all the output is written to the log.

 

Presumably this could also be set up in the nonlinear platform (Analyze | Modeling | Nonlinear), but I haven't tried that yet as I'm not very familiar with using formulae within data tables.  Does that help at all?

ms
Super User ms
Super User

Re: Segmented regression

As Dodo suggests, piecewise regression can be done with the Nonlinear platform. Below is an example based on the broken-stick example above.

 

 

New Table( "piecewise",
  Add Rows( 20 ),
  New Column( "X",
  Continuous,
  Set Values( [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] )
  ),
  New Column( "Y",
  Numeric,
  Set Values( [15, 12, 27, 31, 26, 31, 42, 47, 56, 56, 47, 46, 36, 44, 38, 35, 34, 35, 25, 19] )
  ),
  New Column( "Ypred",
  Numeric,
  Formula( Parameter( {a = 20, b = 1, c = -10, d = 10}, a + b * :X + c * (:X - d) * (:X > d) ) )
  )
);
Nonlinear( Y( :Y ), X( :Ypred ), Newton, Finish );

 

phystudent
Community Trekker

Re: Segmented regression

Thanks I will try this out!

PatrickGiuliano
Community Trekker

Re: Segmented regression

I tried this just recently, it makes more sense to me than the Nonlinear platform utility.  I'd be interested in understanding how the iteration scheme is converging on my solution?  I tried picking a reasonable value of d (the cutpoint) for my data, and it seemed to work better when I "locked" the value of d and re-clicked the "Go" button on the platform dialogue window that is generated from the Nonlinear platform launched using the: 

 

 Nonlinear( Y( :Y ), X( :Ypred ), Newton, Finish );

portion of the code.

 

Is there an easy way to change this short script to call a data table instead? (of manually entering in the values for X and Y)?

I'm sure this is a "JSL Novice Question" so I apologize in advance.....

 

I took this in a cloogey way and copy-pasted just the following into my saved datable with Columns, {X, Y, Ypred} and my populated data:

Parameter( {a = 5, b = 45, c = -100, d = 0.109}, a + b * :X + c * (:X - d) * (:X > d) );
 
 Nonlinear( Y( :Y ), X( :Ypred ), Newton, Finish );

and that's how I arrived at my result for my data!  Thanks again for this contribution to the community.

0 Kudos