How to dynamically assign X or Y variables in Graph Builder using JSL based on conditions?
Hi JMP Community,
I'm trying to build a dynamic Graph Builder report in JSL where the list of X variables is determined by certain conditions (e.g., flags like includeSite, includeWW, etc.). The goal is to flexibly add or remove columns from the X-axis based on runtime logic.
I’ve tried several approaches, including using:
X( :ColumnName )
X( Column("ColumnName") )
Expr( X(...) )
Substitute(...) and Eval(...)
However, I consistently run into errors like:
Name Unresolved: X in access or evaluation of 'X'
Bad Argument( Column(...) )
What I'm looking for is a reliable and correct way to:
-
Dynamically define a list of X-axis variables
-
Pass them to Graph Builder
-
Avoid hardcoding the number of X variables or having to repeat the builder logic
Here’s a simplified version of my goal:
xVars = {};
If( includeSite, Insert Into( xVars, :Site ) );
If( includeWW, Insert Into( xVars, :WW ) );
// add remaining fixed columns...
Graph Builder(
Variables(
// <- How can I inject xVars here properly?
Y( :Measurement )
),
Elements(
Points( Y( :Measurement ) )
)
);
I want to avoid generating multiple separate graph blocks depending on each condition. Is there a supported or recommended way to dynamically build up the X() list for Graph Builder?
Thanks in advance!
Automation and ScriptingBasic Data Analysis and ModelingQuality and Process EngineeringRe: How to dynamically assign X or Y variables in Graph Builder using JSL based on conditions?You could try first by using << Add Variable
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
gb = Graph Builder(Variables(X(:age), Y(:weight)), Elements(Points(X, Y), Smoother(X, Y)));
Wait(0.5);
gb << Add Variable({:height, Role("Y")});
If that doesn't work you might have to build X as expression and then evaluate it to graph builder
Re: How to dynamically assign X or Y variables in Graph Builder using JSL based on conditions?Using built-in functions - like @jthi suggests - is a great way to handle such topics.
If you want to follow the original idea of Writing JSL code dynamically by defining and combining blocks of JSL code (="expressions"), please have a look at @Jasean 's blog post ☝.
With
Expr( X(...) )
you are close, Substitute and Eval are other parts of the framework.
Maybe the most important function: Name Expr(). It can be used to access the expression which is stored in a variable (=name) without evaluating it, e.g. via
y= Expr(X( "ColumnName") );
Name Expr(y);
you will get X( "ColumnName") instead of

Other resources on expression handling:
Expression Handling in JMP: Tips and Trapdoors - JMP User Community
Scripters Club, Session 9: Advanced JSL
Expression Handling Functions: Part I - Unraveling the Expr(), NameExpr(), Eval(), ... Conundrum
Re: How to dynamically assign X or Y variables in Graph Builder using JSL based on conditions?So, with the help of Expr(), Eval(), Substitute(), AND Name Expr(),
Names Default to Here(1);
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
xVars = Expr(X);
Insert Into( xVars, Expr(:age) );
Eval(Substitute(Expr(Graph Builder(
Variables(
__xVars__,
Y( :height )
)
)
), Expr(__xVars__) , Name Expr(xVars)));Re: How to dynamically assign X or Y variables in Graph Builder using JSL based on conditions?Instead of Substitute(), I prefer using Eval Expr() - which works like
"search for Expr() and evaluate the content before you evaluate the whole thing":
Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
xVars = Expr( X );
Insert Into( xVars, Expr( :age ) );
Eval(
Eval Expr(
Graph Builder(
Variables( Expr( Name Expr( xVars ) ), Y( :height ) )
)
)
);
So, JMP has to find:

and evaluate it. Please note the Name Expr(). As discussed in the previous post, this ensures that JMP only looks up the content of xVars and does not evaluate it. After retrieving it and inserting the block into the main block, the whole thing gets evaluated via the enclosing

An nice trick to check what's going on: omit the enclosing Eval() and look at the log.
Then JMP will print the "pre-cooked" expression in the log - without evaluating it. This allows the user to look at the final expression an scan for errors:

If everything is as expected, simply add the Eval() to evaluate the expression.