cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
  • Learn how to build custom Python data connectors and further customize JMP’s Data Connector Framework with the Python Data Connector Demo, available now in the JMP Marketplace!
  • See how to create experiments to support product design and ID useful product features. Register for June 12 webinar, 2pm US Eastern Time.

Discussions

Solve problems, and share tips and tricks with other JMP users.
Choose Language Hide Translation Bar
hogi
Level XIII

Expression Indexing: How to climb the Expression Tree?

This post was born as a wishlist entry - but it turns out that the wish is already partially possible (see @jthi's answer below).
So I moved it here to make the results more visible.

The original wish - which asks for a functionality which goes beyond what is already possible - can be found here:
Expression Indexing: read and write access 

Please have a look and decide if it could help you as well ...

___________________________________________


In many programming languages, one can index lists and matrices. This is also possible in Jmp:

 

list= {"A", "B", "C"};
mat=[1,2,3];
list[3]
mat[2]

 

With Jmp 13, another level of indexing got possible: Data table subscripting 
Nowadays the User can easily index entries in the data table with read and write access.

 

There is a third kind of indexing: Display Tree Indexing
For a given Report, you can walk down the Display Tree to identify a specific object:

 

dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
gb = dt << Graph Builder(
	Size( 437, 413 ),
	Graph Spacing( 4 ),
	Variables( X( :height ), Y( :weight ), Overlay( :sex ) ),
	Elements( Points( X, Y, Legend( 1 ) ), Smoother( X, Y, Legend( 2 ) ) )
)
Report(gb)["Graph Builder"][AxisBox(1)]

 

Maybe there are more places in Jmp where indexing helps the user with his daily work ...

 

For Expressions it's much more complicated to walk down the tree:

To get the Y variable :weight from 

myExpr=Expr(gb = dt << Graph Builder(
	Size( 437, 413 ),
	Graph Spacing( 4 ),
	Variables( X( :height ), Y( :weight ), Overlay( :sex ) ),
	Elements( Points( X, Y, Legend( 1 ) ), Smoother( X, Y, Legend( 2 ) ) )
));

one has to use

Arg(Arg(Arg(Arg(Arg(myExpr,2),2),3),2),1)  // :weight

very fragile !!!!

 

A workaround: convert the Variables Expression into a list and use List-indexing:

myExpr=Expr(Variables( X( :height ), Y( :weight ), Overlay( :sex ) ))
Substitute(Name Expr(myExpr),Expr(Variables()),Expr(List()))["Y"];

but there are several disadvantages:

  1. just works for a single level - flat hierarchy
  2. just the first named argument is found, further named arguments with the same identifier are ignored:
    myExpr=Expr(Variables( X( :height ), Y( :weight ),Y(:height ), Overlay( :sex ) )); 
    Substitute(Name Expr(myExpr),Expr(Variables()),Expr(List()))["Y"]; // returns :weight, ignores Y(:height)
  3.  just returns the first argument, further arguments get lost
    myExpr = Expr(Distribution(columns(:height, :weight)));
    Substitute(Name Expr(myExpr),Expr(Distribution()),Expr(List()))["columns"];
    //returns :height -> :weight gets lost

 

Is there a possibility, analogous to Display Tree Indexing, to climbing an Expression Tree?

 

instead of 

dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
myExpr=Expr(gb = dt << Graph Builder(
	Size( 437, 413 ),
	Graph Spacing( 4 ),
	Variables( X( :height ), Y( :weight ), Y(:height), Overlay( :sex ) ),
	Elements( Points( X, Y, Legend( 1 ) ), Smoother( X, Y, Legend( 2 ) ) )
));
//instead of:
Arg(Arg(Arg(Arg(Arg(myExpr,2),2),3),3),1)

I want to use

myExpr[2][2["Variables"]["Y"(2)][1]
1 ACCEPTED SOLUTION

Accepted Solutions
jthi
Super User

Re: Expression Indexing: How to climb the Expression Tree?

There are some options on how you can do this already (but expression subscripting could be useful). Like I did mention in the wish list item (Expression Indexing: Help me climbing the Expression Tree - JMP User Community), JMP does have Extract Expr() which uses Wild() and Wild List()

Names Default To Here(1);

myExpr = Expr(
	gb = dt << Graph Builder(
		Size(437, 413),
		Graph Spacing(4),
		Variables(X(:height), Y(:weight), Overlay(:sex)),
		Elements(Points(X, Y, Legend(1)), Smoother(X, Y, Legend(2)))
	)
);

yexpr = Extract Expr(myExpr, Y(Wild()));
variables_expr = Extract Expr(myExpr, Variables(Wild List()));
Names Default To Here(1);

myExpr = Expr(
	gb = dt << Graph Builder(
		Size(437, 413),
		Graph Spacing(4),
		Variables(X(:height), Y(:weight), Y(:height), Overlay(:sex)),
		Elements(Points(X, Y, Legend(1)), Smoother(X, Y, Legend(2)))
	)
);

variables_expr = Extract Expr(myExpr, Variables(Wild List()));
idx = 0;
For(i = 1, i <= N Arg(variables_expr), i++,
	firstlevel = Arg(variables_expr, i); // could use Extract Expr
	If(Head(firstlevel) == Expr(Y) & idx == 2,
		secondlevel = Arg(firstlevel, 1);
	);
);
show(secondlevel);

There are also other things you can do (but not really sure if you should)

Names Default To Here(1);

myExpr = Expr(
	Variables(X(:height), Y(:weight), Y(:height), Overlay(:sex))
);

listconversion = Substitute(Name Expr(myExpr), Expr(Variables()), Expr(List())); 

yexprs = {};
While(yexpr = Contains(listconversion, Extract Expr(listconversion, Y(Wild()))),
	Insert Into(yexprs, Remove From(listconversion, yexpr));
);
show(yexprs);
yexprs[2];

There could be other weird stuff you could do with lists...

 

Advanced Expressions, Macros, and Lists (jmp.com) can be a good read

-Jarmo

View solution in original post

2 REPLIES 2
jthi
Super User

Re: Expression Indexing: How to climb the Expression Tree?

There are some options on how you can do this already (but expression subscripting could be useful). Like I did mention in the wish list item (Expression Indexing: Help me climbing the Expression Tree - JMP User Community), JMP does have Extract Expr() which uses Wild() and Wild List()

Names Default To Here(1);

myExpr = Expr(
	gb = dt << Graph Builder(
		Size(437, 413),
		Graph Spacing(4),
		Variables(X(:height), Y(:weight), Overlay(:sex)),
		Elements(Points(X, Y, Legend(1)), Smoother(X, Y, Legend(2)))
	)
);

yexpr = Extract Expr(myExpr, Y(Wild()));
variables_expr = Extract Expr(myExpr, Variables(Wild List()));
Names Default To Here(1);

myExpr = Expr(
	gb = dt << Graph Builder(
		Size(437, 413),
		Graph Spacing(4),
		Variables(X(:height), Y(:weight), Y(:height), Overlay(:sex)),
		Elements(Points(X, Y, Legend(1)), Smoother(X, Y, Legend(2)))
	)
);

variables_expr = Extract Expr(myExpr, Variables(Wild List()));
idx = 0;
For(i = 1, i <= N Arg(variables_expr), i++,
	firstlevel = Arg(variables_expr, i); // could use Extract Expr
	If(Head(firstlevel) == Expr(Y) & idx == 2,
		secondlevel = Arg(firstlevel, 1);
	);
);
show(secondlevel);

There are also other things you can do (but not really sure if you should)

Names Default To Here(1);

myExpr = Expr(
	Variables(X(:height), Y(:weight), Y(:height), Overlay(:sex))
);

listconversion = Substitute(Name Expr(myExpr), Expr(Variables()), Expr(List())); 

yexprs = {};
While(yexpr = Contains(listconversion, Extract Expr(listconversion, Y(Wild()))),
	Insert Into(yexprs, Remove From(listconversion, yexpr));
);
show(yexprs);
yexprs[2];

There could be other weird stuff you could do with lists...

 

Advanced Expressions, Macros, and Lists (jmp.com) can be a good read

-Jarmo
hogi
Level XIII

Re: Expression Indexing: How to climb the Expression Tree?

Thanks, @jthi Extract Expr() is very helpful to get to the correct level of the tree.
It helped me a lot last year : )

 

I just noticed that the processing of arguments within one level can be done much easier:

For Each, Transform Each and Filter Each can be used with expressions. Cool!

hogi_0-1735977771997.png

 

Main Script = Expr(dt << Graph Builder(
	Size( 437, 413 ),
	Graph Spacing( 4 ),
	Variables( X( :height ), Y( :weight ), Y (:sex), Overlay( :sex ) ),
	Elements( Points( X, Y, Legend( 1 ) ), Smoother( X, Y, Legend( 2 ) ) )
));

snippet = Extract Expr(Main Script, Variables(Wild List()))

For each({variable}, Name Expr(snippet), Show(Head(variable), Arg(variable)))

selection = Filter Each ({code}, Name Expr(snippet), Head(code)==Expr(Y()));
Show(selection)

changed= Transform Each ({code}, Name Expr(snippet), If (Head(code)==Expr(X()),  Expr(my changed code),Name Expr(code)))
Show(changed);

 

Recommended Articles