cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
  • JMP 19 is here! See the new features at jmp.com/new.
  • Register to attend Discovery Summit 2025 Online: Early Users Edition, Sept. 24-25.
Choose Language Hide Translation Bar
PaleoHunter
Level I

Calculations between rows based on conditions

Hey, I'm new to JMP scripting, but somewhat used to python language. I'm trying to achieve the following with my dummy test table below:

 

1) Cycle through all rows (both before and after the row) and do calculations only on those rows where Cuvette == 11, remaining rows where Cuvette != 11 the "Output" can be set to NA or whatever. 

2) The calcuation itself is between two separate rows. In rows with Cuvette == 11, the 850 nm cell of the row has to be divided with the 250 nm cell from the row that meets two conditions:
                   a) Cuvette == 12
                   b) The Pass value has to match up between the rows, e.g. Pass value for cuvette 11 == Pass value for Cuvette 12    

 

Pass 850 nm 250 nm Cuvette Output
1 100 200 11 100/500 = 0,2
2 400 500 11 400/400 = 1
3 300 100 11 300 / 900 = 0.33
1 700 500 12 NA
2 200 400 12 NA
3 400 900 12 NA
1 400 800 13 NA
2 500 700 13 NA
3 300 700 13 NA



3 REPLIES 3
jthi
Super User

Re: Calculations between rows based on conditions

To do this in JMP like fashion, you generally would split your data and then perform the calculation (JMP is Not a Spreadsheet), then join it back or continue with the split data.

 

But you can use also JSL or Formula to do this calculation, but first consider the splitting option.

-Jarmo
jthi
Super User

Re: Calculations between rows based on conditions

Here is one matrix option, but using JMP features is generally easier to understand

Names Default To Here(1);

dt = Current Data Table();

cuvette_start = 11;
cuvette_end = 12;

cuvettes = dt[0, "Cuvette"];

// Data is sorted -> we can just take values and make comparison
start_idx = Loc(cuvettes, cuvette_start);
end_idx = Loc(cuvettes, cuvette_end);

// differences
output = J(1, N Rows(dt), .);
output[start_idx] = dt[start_idx, "850 nm"]  dt[end_idx, "250 nm"];
dt << new column("R", Numeric, Continuous, Values(output));

If you can rely on the order heavily, you can use formula like this

If(:Cuvette == 11,
	:"850 nm"n / :"250 nm"n[Col Min(If(:Cuvette == 12, Row(), .)) + Row() - 1];
);

The type of final formula will heavily depend on your real use case (is data sorted "properly", are you looking for more than one value comparison and so on).

-Jarmo
txnelson
Super User

Re: Calculations between rows based on conditions

Welcome to the Community.

Here is an example of how I would approach your problem

txnelson_0-1743592985021.png

Names Default To Here( 1 );
dt = Current Data Table();

// Separate out the Cuvette==12 rows into a separate data table
// and then join the Pass==Pass rows to the Cuvette==11 rows
// Then calculate the Output column

// Select the Cuvette==12 rows
dt << Select Where( :Cuvette == 12 );

// Create a new subsetted data table with those rows
dt12 = dt << Subset( Selected Rows( 1 ), columns( :Pass, :"250 nm"n ) );

// Change 250 nm column name so when joined back to original table
// it will have a unique column name
dt12:"250 nm"n << Set Name( "Divisor" );

// For alignment reasons, add a new column called Cuvette and set
// it equal to 11
dt12 << New Column( "Cuvette", Set Each Value( 11 ) );

// Join the tables using the Update Platform
dt << Update(
	With( dt12 ),
	Match Columns( :Pass = :Pass, :Cuvette = :Cuvette )
);

// Create the new Output column
dt << New Column( "Output", Set Each Value( :"850 nm"n / :Divisor ) );

// Remove Divisor column since it is no longer needed
dt << delete columns( Divisor );

// Close the subsetted data table since it is no longer needed
Close( dt12, nosave );

// Remove the Selected RowStates from the data table
dt << clear rowstates;

 Below is a more direct approach, but a far more inefficient method, which yields the same results.  On a large data table this method will be quite slow

Names Default To Here( 1 );
dt = Current Data Table();

dt << New Column( "Output",
	Formula(
		foundRow = [];
		If( :Cuvette == 11,
			curPass = :Pass;
			foundRow = Current Data Table() <<
			get rows where( :Cuvette == 12 & :Pass == curPass );
			If( N Items( foundRow ) > 0,
				:"850 nm"n / :"250 nm"n[foundRow[1]]
			);
		);
	)
);
Jim

Recommended Articles