Indexing into a matrix (or a list) with another matrix (or list) is a powerful technique for making scripts fast and small, but there is one edge case to worry about which we are fixing for JMP 13. Perhaps I should put "fixing" in quotation marks because any change is a potential disruption, which is why I want to explain it here in advance of JMP 13.
Here's an example of using a matrix as an index into a data column.
Open("$SAMPLE_DATA/Big Class.jmp");
tall rows = Loc(:height << Get Values() >= 67); // [25, 27, 30, 37, 39, 40]
:height[tall rows]; // [68, 69, 67, 68, 68, 70]
N Rows(:height[tall rows]); // 6
If you're not familiar with this style of programming, the second line is the key. ":height << Get Values()" returns the values of the height column as a matrix. The comparison ">= 67" returns a matrix of 0s and 1s corresponding to where the expression is false (0) or true (1). The Loc() function returns the locations of the 1s within the previous matrix.
In this case we get [25, 27, 30, 37, 39, 40] as the row numbers where the height column is greater than or equal to 67. That's pretty handy by itself, but the real power comes from being able to use that matrix as the index into a column or other matrix as in the third and fourth lines.
The alternative to this technique would be to write a For() loop to iterate through every row explicitly. Of course, JMP is still looping through the rows in either case, but it's much faster if done internally rather than in JSL. And the JSL is more compact without the explicit loop.
We can do the same thing with a matrix variable instead of a data column reference:
m = :height << Get Values();
tall rows = Loc(m >= 67); // [25, 27, 30, 37, 39, 40]
m[tall rows]; // [68, 69, 67, 68, 68, 70]
N Rows(m[tall rows]); // 6
All great so far. Let's look at the same examples with a different height cutoff (70 instead of 67):
tall rows = Loc(:height << Get Values() >= 70); // [40]
:height[tall rows]; // [70]
N Rows(:height[tall rows]); // 1
m = :height << Get Values();
tall rows = Loc(m >= 70); // [40]
m[tall rows]; // 70
N Rows(m[tall rows]); // error
What went wrong? Notice that data[tall rows] returned 70 instead of [70]. In many cases, a 1x1 matrix and a number are treated the same way, but not always. The N Rows() function is one example where it makes a difference. The indexing is too aggressively "simplifying" the 1x1 matrix into a number.
One work-around is to call Is Matrix() before using N Rows(). Another is to concatenate an empty matrix to the result, which will create a matrix whether the source is a number or a matrix:
m = m |/ [];
ln JMP 13, the 1x1 matrix is maintained so that the result of the index operation will be a matrix whenever the index itself is a matrix. The same applies to list indexing and already applied to data column indexing.
We expect the disruption to be rare since the trigger is not common and a 1x1 matrix and a number are often treated the same anyway. Nonetheless, the JMP 13 debugger will have the ability to identify places in your scripts that might be affected by the change.
If you have any feedback or concerns, let us know here or contact danielvalente to see if you're eligible for the JMP 13 Early Adopter program to try out the change on your own code.