cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Check out the JMP® Marketplace featured Capability Explorer add-in
Choose Language Hide Translation Bar
phystudent
Level II

Segmented regression

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

1 ACCEPTED SOLUTION

Accepted Solutions
ms
Super User (Alumni) ms
Super User (Alumni)

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 );

 

View solution in original post

5 REPLIES 5

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 (Alumni) ms
Super User (Alumni)

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
Level II

Re: Segmented regression

Thanks I will try this out!

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.

Re: Segmented regression

For those who have not seen this, here is a potentially useful blog written by my colleague @JerryFish  on how to construct and manipulate piecewise fitting in JMP (using the Nonlinear platform): Piecewise Nonlinear Solutions Part 3: Using JMP's Formula Editor to solve for unknown parameters.

I am including this here since it dovetails nicely with this discussion.