Yesterday I found the following thread, which caused me to investigate parse().
https://community.jmp.com/t5/Discussions/evaluating-a-string-using-a-column-formula/m-p/38028
The thought process is as follows:
- When using expr(), JMP expects functions as an argument, not other arguments. More on this later.
- If arguments can be saved to a variable as a string, and then placed into either another argument, or function, this will help code what's needed
Here's an example.
names default to here(1);
clear log();
clear symbols();
dt = open( "$SAMPLE_DATA/Big Class.jmp" );
dt << Graph Builder(
Size( 517, 447 ),
Show Control Panel( 0 ),
Fit to Window,
Set α Level( 0.05 ),
Variables( X( :weight ), Y( :height ), Color( :sex ) ),
Elements( Points( X, Y, Legend( 3 ) ) ),
SendToReport(
Dispatch(
{},
"height",
ScaleBox,
{Add Ref Line( 67.5, "Solid", "Black", "Tall", 1 )}
)
)
);
The script opens Big Class.jmp and then generates a visualization with a reference line. When I want to pull data from other sources for the visualization, I could modify the script above to the following.
Names default to here(1);
clear log();
dt = open( "$SAMPLE_DATA/Big Class.jmp" );
// Example "other" source
ex = New Table( "Example",
Add Rows(2),
New Column( "Growth Label", Character, Nominal, Set Values( { "Tall", "Short" } ) ),
New Column( "Height tag", Numeric, Continuous, Set Values( { 67.5, 60 } ) ),
);
dt << Graph Builder(
Size( 517, 447 ),
Show Control Panel( 0 ),
Fit to Window,
Set α Level( 0.05 ),
Variables( X( :weight ), Y( :height ), Color( :sex ) ),
Elements( Points( X, Y, Legend( 3 ) ) ),
SendToReport(
Dispatch(
{},
"height",
ScaleBox,
{Add Ref Line( ex:Height tag[1], "Solid", "Black", ex:Growth Label[1], 1 )} // 2x references to data table( "Example" ) as "ex"
)
)
);
The difference in the above script is that some of the reference line information is now pulling from the example table that was created. What if I wanted to add the visualization in the script above as a data table script? Assuming that we don't want to always be referencing another table for the values, how can we replace the references with the values they represent? The answer is expression manipulations and, seemingly, parse().
To read more about expression manipulations, read this resource: https://www.jmp.com/support/help/en/17.0/#page/jmp/advanced-expressions-macros-and-lists.shtml#
If we were to add the visualization as a table script to Big Class, our script window would have code like this.
// Visualization - No references to other data sources
dt << New script( "Vis 1",
Graph Builder(
Size( 517, 447 ),
Show Control Panel( 0 ),
Fit to Window,
Set α Level( 0.05 ),
Variables( X( :weight ), Y( :height ), Color( :sex ) ),
Elements( Points( X, Y, Legend( 3 ) ) ),
SendToReport(
Dispatch(
{},
"height",
ScaleBox,
{Add Ref Line( 67.5, "Solid", "Black", "Tall", 1 )}
)
)
);
);
// Visualization - With references to other data sources
// This will not work, as the data table reference "ex" is undefined
// We could replace ex with data table( "example" ), but that table would need to be open in the background
dt << New script( "Vis 2",
Graph Builder(
Size( 517, 447 ),
Show Control Panel( 0 ),
Fit to Window,
Set α Level( 0.05 ),
Variables( X( :weight ), Y( :height ), Color( :sex ) ),
Elements( Points( X, Y, Legend( 3 ) ) ),
SendToReport(
Dispatch(
{},
"height",
ScaleBox,
{Add Ref Line( ex:Height tag[1], "Solid", "Black", ex:Growth Label[1], 1 )}
)
)
);
);
This is the fruit of my investigation and experimentation so far, with a focus on parse(). It doesn't work yet, but it's a step in the right direction!
names default to here(1);
clear log();
clear symbols();
// Opening & creating data tables for use
dt = open( "$SAMPLE_DATA/Big Class.jmp" );
ex = New Table( "Example",
Add Rows(2),
New Column( "Growth Label", Character, Nominal, Set Values( { "Tall", "Short" } ) ),
New Column( "Height tag", Numeric, Continuous, Set Values( { 67.5, 60 } ) ),
);
// Variables
graphing = expr( Graph Builder() );
size = "Size( 517, 447 )";
control_panel = "Show Control Panel( 0 )";
fit = "Fit to Window";
a_lvl = "Set α Level( 0.05 )";
vars = "Variables( X( :weight ), Y( :height ), Color( :sex ) )";
eles = "Elements( Points( X, Y, Legend( 3 ) ) )";
str = "SendToReport()";
disp = parse( "Dispatch()" );
curly = "{}";
label = "ex:Growth label[1]";
label2 = "height";
scle = "ScaleBox";
x_axis = "x()";
test_label = "ex:Height tag[1]";
mylabel = "ex:Growth label[1]";
ref_line = parse( "Add Ref Line()" );
insert into( graphing, parse( size ) );
insert into( graphing, parse( control_panel ) );
insert into( graphing, parse( fit ) );
insert into( graphing, parse( a_lvl ) );
insert into( graphing, parse( vars ) );
insert into( graphing, parse( eles ) );
show( graphing ); // Result:graphing = Graph Builder(Size(517, 447), Show Control Panel(0), Fit to Window, Set α Level(0.05), Variables(X(:weight), Y(:height), Color(:sex)), Elements(Points(X, Y, Legend(3))));
// add ref line
insert into( ref_line, eval( parse( test_label ) ) );
insert into( ref_line, "Solid" );
insert into( ref_line, "Black" );
insert into( ref_line, eval( parse( mylabel ) ) );
show( ref_line ); // Result: ref_line = Add Ref Line(67.5, "Solid", "Black", "Tall");
insert into( disp, parse( curley ) );
insert into( disp, eval( parse( mylabel ) ) );
insert into( disp, char( label2 ) );
insert into( disp, parse( scle ) );
insert into( disp, parse( curly ) ); // Note this line! More work needs to be done here
show( disp ); // Result: disp = Dispatch({}, "Tall", "height", ScaleBox, {});
The script above is very busy, and after figuring out the rest of this, I'll look for ways to optimize by shrinking the number of variables necessary, as this is quite a list.
Near the bottom of the script, more information on the note: ref_line needs to be inserted into curly BEFORE curly is inserted into disp. It would be easy to think that you could do this:
insert( curley, ref_line );
But, because the contents of ref_line is contained within an argument, not a function, JMP will error out. Once a way is figured out around this, everything else should be easy. My next guess is to try something like this:
// Note: char( ref_line ) will cause JMP to error, because it's an argument
new_parse = expr( parse() );
insert into( new_parse, char( ref_line) );
// Then somehow
eval( insert into( curley, eval expr( eval( new_parse ) ) ) );
After learning how to insert a non-character type argument into another argument, the rest of the Graph Builder() function will be simple to build. The final piece will be to insert everything as an expression, into dt << New Script( "Visualization", <expression here> );, and then use eval expr() and another eval() (?) to make JMP successfully execute the code and insert the visualization into dt.
Learning every day!