cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Choose Language Hide Translation Bar
BHarris
Level VI

Difference of lines

Suppose I have two lines, distance vs. time for two different moving objects.  The time measurements for object 1 and object 2 are at arbitrary times, i.e., the measured times for object 1 aren't the same times as provided for object 2.

 

Is there a way in Graph Builder to plot the *difference* between those curves vs. time?

2 ACCEPTED SOLUTIONS

Accepted Solutions
Craige_Hales
Super User

Re: Difference of lines

I think what you want is called a piece-wise linear interpolation. I'm not sure what platform might produce a formula for that, but you can do something similar like this. Do your own testing if you use this!

dt = Open( "$desktop/ab.jmp" ); // table with unaligned times for a and b measurements
dt << sort( by( time ), replacetable( 1 ) ); // make sure time is ascending
aRows = dt << getrowswhere( SourceTable == "a" ); // get all the a
bRows = dt << getrowswhere( SourceTable == "b" ); // and b row indexes
aTimes = dt:time[aRows]; // get all the a and b times and positions in
aPositions = dt:position[aRows]; // matrices for the interpolate function
bTimes = dt:time[bRows];
bPositions = dt:position[bRows];

apos = Function( {time}, // tiny wrappers for interpolate
	Interpolate( time, aTimes, aPositions )
);
bpos = Function( {time},
	Interpolate( time, bTimes, bPositions )
);

dtnew = New Table( "new_ab", // new table is similar to old table
	New Column( "Source Table", Character( 1 ), "Nominal" ),
	New Column( "time", Numeric, "Continuous", Format( "Best", 12 ) ),
	New Column( "position", Numeric, "Continuous", Format( "Best", 12 ) )
);

bigdif = 0; // track the largest difference so it can have a ref line
bigtime = .;
// make a new table covering the range of the data
For( i = min(min(aTimes),min(bTimes))-10, i <= max(max(aTimes),max(bTimes))+10, i += 1,
	dtnew << addrows( 1 ); // interpolate a at time i
	dtnew:SourceTable = "a";
	dtnew:time = i;
	dtnew:position = apos( i );
	dtnew << addrows( 1 ); // interpolate b at time i
	dtnew:SourceTable = "b";
	dtnew:time = i;
	dtnew:position = bpos( i );
	dtnew << addrows( 1 ); // difference at time i
	dtnew:SourceTable = "diff";
	dtnew:time = i;
	dtnew:position = apos( i ) - bpos( i );
	If( Abs( dtnew:position ) > bigdif, // capture biggest diff
		bigdif = Abs( dtnew:position );
		bigtime = i;
	);
);

dtnew << Graph Builder(
	Size( 518, 448 ),
	Show Control Panel( 0 ),
	Variables( X( :time ), Y( :position ), Overlay( :Source Table ) ),
	Elements( Points( X, Y, Legend( 21 ) ), Smoother( X, Y, Legend( 22 ), Lambda( 0.000001 ) ) ),
	SendToReport(
		Dispatch( {}, "time", ScaleBox, {Add Ref Line( bigtime, "Solid", "Black", "big=" || Char( bigtime ), 1 )} ),
		Dispatch( {}, "Graph Builder", FrameBox, {Marker Size( 2 )} )
	)
);

Input data like this

Capture1.PNG

And the interpolated data like this

Capture2.PNG

Producing a graph like this:

The green curve is blue - red; the ref line is at the first biggest difference.The green curve is blue - red; the ref line is at the first biggest difference.

If this was a race, a won in 71 seconds and b lost in 99 seconds. a was furthest ahead at 43 seconds (well, maybe. You can't be too sure about b's position at time 43 in the original data.)

You can't get that from a simple linear fit on the original data:

Original data with linear fit.Original data with linear fit.

Craige

View solution in original post

XanGregg
Staff

Re: Difference of lines

Here's a low scripting alternative using the Save Formula command available in the red triangle menu for a Smoother or Line of Fit element.

XanGregg_0-1631541150941.png

 

Starting with Craige's ab.jmp table using Overlay to get two lines/curves, use Save Formula to get a new column with a formula that looks like:

 

If( :Source Table == "a", Spline Eval( ... ), :Source Table == "b", Spline Eval( ... ), . ))

 

Go into the Formula Editor for the new column and change the formula to subtract the two Spline expressions:

 

Spline Eval( ... ) - Spline Eval( ... )

 

And use that as the Y in GB.

XanGregg_1-1631541420331.png

 

View solution in original post

12 REPLIES 12

Re: Difference of lines

The only way that you can compare to curves observed at different times is to model each one and compare the models at selected times. The model could be as simple as a linear interpolation as complex as any model type in JMP. Do you have JMP Pro? If so, you can treat the data as 'functions' and use the Functional Data Explorer.

 

I won't go into detail until I hear from you that the general approach makes sense.

BHarris
Level VI

Re: Difference of lines

No, we just have the basic JMP v16.

Craige_Hales
Super User

Re: Difference of lines

If you had a pair of data tables, one per object, with columns for time and distance, you could save the formulas that would predict positions at between times. Subtracting the formulas at a Time would give an answer. I think Mark's question is if you think a linear/quadratic/other model from Fit Model would give a good-enough estimate of a object position, between measurements.

 

Craige

Re: Difference of lines

Exactly. The complexity of the curve or shape will dictate the complexity of the model that is necessary. Can you show a picture of a plot of the data? Perhaps there is a theoretical model for such data?

 

We cannot help you further because the next step is the modeling, but we have to know which model in order to help you.

BHarris
Level VI

Re: Difference of lines


@Mark_Bailey wrote:

Exactly. The complexity of the curve or shape will dictate the complexity of the model that is necessary. Can you show a picture of a plot of the data? Perhaps there is a theoretical model for such data?

 

We cannot help you further because the next step is the modeling, but we have to know which model in order to help you.


@Mark_Bailey , @Craige_Hales  -- Yes, a linear fit between points would be fine.  I realize the difference will be somewhat bouncy due to the linear interpolation, but that's fine, we're just looking at rough magnitudes.

txnelson
Super User

Re: Difference of lines

@Mark_Bailey If the two lines are linear, then a Fit Model of Height predicted by Weight, for the 2 sex groups end up having an term estimate of -2.079223.  Wouldn't that be the difference between the lines when simplified to a linear regression?

 

txnelson_0-1631312435224.png

 

Jim
Craige_Hales
Super User

Re: Difference of lines

I think what you want is called a piece-wise linear interpolation. I'm not sure what platform might produce a formula for that, but you can do something similar like this. Do your own testing if you use this!

dt = Open( "$desktop/ab.jmp" ); // table with unaligned times for a and b measurements
dt << sort( by( time ), replacetable( 1 ) ); // make sure time is ascending
aRows = dt << getrowswhere( SourceTable == "a" ); // get all the a
bRows = dt << getrowswhere( SourceTable == "b" ); // and b row indexes
aTimes = dt:time[aRows]; // get all the a and b times and positions in
aPositions = dt:position[aRows]; // matrices for the interpolate function
bTimes = dt:time[bRows];
bPositions = dt:position[bRows];

apos = Function( {time}, // tiny wrappers for interpolate
	Interpolate( time, aTimes, aPositions )
);
bpos = Function( {time},
	Interpolate( time, bTimes, bPositions )
);

dtnew = New Table( "new_ab", // new table is similar to old table
	New Column( "Source Table", Character( 1 ), "Nominal" ),
	New Column( "time", Numeric, "Continuous", Format( "Best", 12 ) ),
	New Column( "position", Numeric, "Continuous", Format( "Best", 12 ) )
);

bigdif = 0; // track the largest difference so it can have a ref line
bigtime = .;
// make a new table covering the range of the data
For( i = min(min(aTimes),min(bTimes))-10, i <= max(max(aTimes),max(bTimes))+10, i += 1,
	dtnew << addrows( 1 ); // interpolate a at time i
	dtnew:SourceTable = "a";
	dtnew:time = i;
	dtnew:position = apos( i );
	dtnew << addrows( 1 ); // interpolate b at time i
	dtnew:SourceTable = "b";
	dtnew:time = i;
	dtnew:position = bpos( i );
	dtnew << addrows( 1 ); // difference at time i
	dtnew:SourceTable = "diff";
	dtnew:time = i;
	dtnew:position = apos( i ) - bpos( i );
	If( Abs( dtnew:position ) > bigdif, // capture biggest diff
		bigdif = Abs( dtnew:position );
		bigtime = i;
	);
);

dtnew << Graph Builder(
	Size( 518, 448 ),
	Show Control Panel( 0 ),
	Variables( X( :time ), Y( :position ), Overlay( :Source Table ) ),
	Elements( Points( X, Y, Legend( 21 ) ), Smoother( X, Y, Legend( 22 ), Lambda( 0.000001 ) ) ),
	SendToReport(
		Dispatch( {}, "time", ScaleBox, {Add Ref Line( bigtime, "Solid", "Black", "big=" || Char( bigtime ), 1 )} ),
		Dispatch( {}, "Graph Builder", FrameBox, {Marker Size( 2 )} )
	)
);

Input data like this

Capture1.PNG

And the interpolated data like this

Capture2.PNG

Producing a graph like this:

The green curve is blue - red; the ref line is at the first biggest difference.The green curve is blue - red; the ref line is at the first biggest difference.

If this was a race, a won in 71 seconds and b lost in 99 seconds. a was furthest ahead at 43 seconds (well, maybe. You can't be too sure about b's position at time 43 in the original data.)

You can't get that from a simple linear fit on the original data:

Original data with linear fit.Original data with linear fit.

Craige
BHarris
Level VI

Re: Difference of lines

Wow, impressive solution!  And very well documented, thank you!!

 

The only thing better would be if JMP just did this on its own without the intermediate scripting step, but aside from shift-clicking two lines in Graph Builder and asking for a difference line (which is conceptually messy from a mental-model-of-what-it's-doing standpoint), I can't really imagine how that would work.

 

Thanks, Craige!

 

(ps.  Are you really retired?  Doing JMP support for fun?)

Craige_Hales
Super User

Re: Difference of lines

Yes, retired, and I learn a lot answering questions.

@XanGreggfor the graph builder suggestion.

Craige