cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
JMP is taking Discovery online, April 16 and 18. Register today and join us for interactive sessions featuring popular presentation topics, networking, and discussions with the experts.
Choose Language Hide Translation Bar
Craige_Hales
Super User
What is the JSL Matrix?

 

 

Animated gif of random green letters with random red J, M, and P charactersAnimated gif of random green letters with random red J, M, and P characters

JMP has a powerfull set of matrix primitives in the JSL scripting language. Here's an introduction to creating and using 1D and 2D matrices in JSL.

A JSL matrix constant for a 3 row by 2 column matrix looks like this; notice the spaces between elements on a row and the commas between rows.

constant = [ 
1 2,
3 4,
5 6	
];

When you run that code it will display like this in the log window (and you can write it on one line too):

[1 2, 3 4, 5 6]

The square brackets define a constant that is created when the JSL is parsed. You can't use other JSL variables between the square brackets because the parser runs before the variables exist (more on that in a moment). Two more examples using 1D matrices:

RowVector = [1 2];
ColVector = [3,4];

JSL has several functions for creating matrices. I usually use J( nRows, nCols, init ), with 0 for the 3rd init value.

squareOnes = J(5);
[1 1 1 1 1,
1 1 1 1 1,
1 1 1 1 1,
1 1 1 1 1,
1 1 1 1 1]

diagOnes = identity(5);
[1 0 0 0 0,
0 1 0 0 0,
0 0 1 0 0,
0 0 0 1 0,
0 0 0 0 1]

colsAndRows = J(3,2,random integer(1,6));
[2 6, 2 5, 5 2]

You can also build matrices by concatenating values together, horizontally or vertically. The same concatenation operators will concatenate matrices that have compatible sizes (not shown here).

a=1;b=2;c=3;d=4;e=5; // now we can use variables as follows

row1 = a::e; // row
[1 2 3 4 5]

col1 = (a::e)`; // column - transpose operator
[1, 2, 3, 4, 5]

row2 = a||22||c||44||e; // row - concatenate horizontal
[1 22 3 44 5]

col2 = a|/222|/c|/444|/e; // column - concatenate vertical
[1, 222, 3, 444, 5]

Than tiny little ` character is at the top left of a US keyboard and is the matrix transpose operator. The :: operator makes a matrix of integers. You can multiply by a scalar and add a scalar to get the result matrix you need.

(0::9)*.1+100
[100 100.1 100.2 100.3 100.4 100.5 100.6 100.7 100.8 100.9]

Matrices are subscripted in the ususal way. Matrix subscripts start at 1 in JSL, not 0 as in some languages.

M = [
 11 12 13 14 15,
 21 22 23 24 25,
 31 32 33 34 45	
];

write(M);
[	11 12 13 14 15, 
	21 22 23 24 25, 
	31 32 33 34 45]

write(M[2,3])
23

And they can be sliced and diced in powerful ways:

write(M[2::3, 1::2]); // return a 2x2 sub-matrix
[21 22, 31 32]

write(M[1,0]); // 0 means the entire dimension
[11 12 13 14 15]

write(M[0,2::3]); // various combinations
[12 13, 22 23, 32 33]

There is a matrix function in JSL called shape that is sometimes useful for reshaping a row or column vector into a 2D matrix. There are two multiply operators for matrices, one for matrix algebra multiplies ( m1 * m2 ) and another for element-by-element multiplication:

[1 2, 3 4] :* [2 3, 4 5]
[2 6, 12 20]

Remember that :* operator if you get really unexpected results multiplying two images together!

You can assign values to matrix elements or slices too:

mat = J(2,3,.); // 2 rows, three columns, all missing
mat[1,1] = 7; // the top left corner
mat[0,2::3] = [5 9, 13 15]; // all rows, columns 2 and 3
write(mat); // notice the missing value that never got set
[7 5 9, . 13 15]

Finally, here's the code for the animated gif that has almost nothing to do with the topic. It uses matrices in surprising ways to manipulate images and characters and probably isn't the example you want to start with.

matgif = "$desktop/mat.gif";
gb = Graph Box(framesize(500,300));
gb << setBackgroundColor( "black" );
gb << setGraphicsScript(
	Text Color( "green" );
	For( x = -10, x <= 110, x += Random Integer( 2, 4 ),
		For( y = -10, y <= 110, y += Random Integer( 3, 7 ),
			c = random integer(31,1000);
			textcolor("green");
			if( random integer(1,10000)<60,
				textcolor("red");
				c = blobtomatrix(chartoblob(substr("JMP", random integer(1,3),1)),"uint",1,"big")
			);
			Text( {x, y}, blobtochar(matrixtoblob(c::c,"uint",2,"big"),encoding="utf-16be") )
		);
	);
);
New Window( "x", gb );
duration=80;//ms
animation = gb[framebox(1)]<<getpicture;
animation<<setFrameDuration(duration);//ms
for( ipic=1,ipic<=7,ipic++,
    gb << inval; gb<<updatewindow;
	p = gb[framebox(1)]<<getpicture;
	animation<<addFrame;
	animation<<setFrameDuration(duration);//ms
	animation<<setPixels(p<<getpixels);
);
animation<<saveImage(matgif,"gif");
open(matgif);
filesize(matgif);

 

Last Modified: Dec 8, 2016 3:10 PM
Comments
MathStatChem
Level VI

thanks for the instruction.  The code on how to create an animated GIF was really helpful, too!  I had been trying to figure that out recently.  

Craige_Hales
Super User

welcome, and thanks!

Craige_Hales
Super User

also: Using Loc with a 2D Matrix is a bit more advanced side discussion. The loc( ) function finds the location of matrix elements that match a condition. Loc( ) returns a vector of indexes that needs a little work for a 2D matrix.

David_Burnham
Super User (Alumni)

Sometimes we just want to perform a regression without the overhead of generating all the Fit Model results, and matrices are a great way of doing it.  I wrote a post on this topic a while back:

 

http://www.pega-analytics.co.uk/blog/linear-regression-matrix-form/

 

At the time, I didn't realise you can do it using the function LeastSquaresSolve() !

 

 

Craige_Hales
Super User

https://community.jmp.com/t5/Discussions/Near-neighbors-mean-calculation/m-p/345727#M59633 has an example of indexing a matrix, M3, with another matrix, indexer2x2, to get a sub-matrix of M3. This example is designed to get a contiguous rectangular region and return it as a 2D matrix, but the indexer could get any set of elements, in any order, and the shape() function is optional if you want the 1D matrix of items:

M3 = [. . . . . . . . .,
. . . . . . . . .,
. . . . . . . . .,
. . . 1 2 3 . . .,
. . . 4 5 6 . . .,
. . . 7 8 9 . . .,
. . . . . . . . .,
. . . . . . . . .,
. . . . . . . . .];

indexer2x2 = [1 2 10 11]; // top left 2x2 sub-matrix

For( x = 2, x <= 5, x += 1,
	For( y = 2, y <= 5, y += 1,
		Write( "\!n ", x, " ", y, " ", Shape( M3[indexer2x2 + x + y * 9], 2 ) );
	
	)
);

2 2 [. ., . 1]
2 3 [. 1, . 4]
2 4 [. 4, . 7]
2 5 [. 7, . .]
3 2 [. ., 1 2]
3 3 [1 2, 4 5]
3 4 [4 5, 7 8]
3 5 [7 8, . .]
4 2 [. ., 2 3]
4 3 [2 3, 5 6]
4 4 [5 6, 8 9]
4 5 [8 9, . .]
5 2 [. ., 3 .]
5 3 [3 ., 6 .]
5 4 [6 ., 9 .]
5 5 [9 ., . .]