cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Check out the JMP® Marketplace featured Capability Explorer add-in
Choose Language Hide Translation Bar
neelsrejan
Level III

How to add a graphics script dynamically to a variability chart with multiple frame boxes

Hi all, 

 

So I have a variability chart that is split by a "BY" grouping, I asked this question in https://community.jmp.com/t5/Discussions/How-to-add-Dynamic-horizontal-line-by-shared-y-axis-among/m... in which I understand how the graphics script added the respective lines based on the values from the data tables. I was trying to adapt this method to the variability chart with more frameboxes and am unable to figure out how to do it. My guess as of now is to put each By in a for loop and add the graphics to the respective framebox iteratively but am confused as how to do that as I am not sure how to access a framebox iteratively. Any help would be appreciated. Thanks!

 

Please use the rpt from below and potentially add a for loop so that 

//Potential for loop?

rpt = dt << Variability Chart( Y( :Head IC), X( :Make, :Model ), Analysis Type( "Choose best analysis (EMS REML Bayesian)" ), Show Range Bars( 0 ), Show Cell Means( 0 ), Std Dev Chart( 0 ), Points Jittered( 1 ), BY(:Name("D/P")) );
//Subset data table by "By" condition to add the correct lines based on the condition.
tree = rpt << Report; Eval( Eval Expr( tree[FrameBox( 1 )] << Add Graphics Script( Local( {values = Expr( category average ), numbers = Expr( category number ), i, items, sum = 0}, items = numbers << Get Keys; Pen Size( 2 ); Pen Color( "Blue" ); Summation( i = 1, N Items( items ), Line( Eval List( {sum, values[items[i]]} ), Eval List( {sum += numbers[items[i]], values[items[i]]} ) ); 0 ) ) ) ) )
1 ACCEPTED SOLUTION

Accepted Solutions
ErraticAttack
Level VI

Re: How to add a graphics script dynamically to a variability chart with multiple frame boxes

You can loop over the return result from the original Variability Chart( By( ... ) ) command:

names default to here(1);
dt = 
// Open Data Table: Big Class.jmp
// → Data Table( "Big Class" )
Open( "$SAMPLE_DATA/Cars.jmp" );

rpt = dt << Variability Chart(
	Y( :Head IC),
	X( :Make, :Model ),
	Analysis Type( "Choose best analysis (EMS REML Bayesian)" ),
	Show Range Bars( 0 ),
	Show Cell Means( 0 ),
	Std Dev Chart( 0 ),
	Points Jittered( 1 ),
	By( :NAME("D/P"), :Protection ),
);

//find groupings:

subt = dt << Summary( Group( :"D/P"n, :Protection ), Link to Original Data Table( 0 ) );
dps = subt:"D/P"n << Get Values;
protections = subt:protection << Get Values;
Close( subt, No Save );

For( t = 1, t <= N Items( dps ), t++,
	Eval( eval Expr(
	rows = dt << Get Rows Where( :NAME("D/P") == Expr( dps[t] ) & :Protection == Expr( protections[t] ) );
	) );
	subt = dt << Subset( Rows( rows ), Columns( :Make, :Model, :Wt ), Not Linked, Private );
	sumt = subt << Summary( Group( :Make, Model ), Mean( :Wt ), Statistics Column Name Format( "Column" ), Link to Original Data Table( 0 ), Private );
	Close( subt, No Save );
	subt = sumt << Summary( Group( :Make ), Mean( :Wt ), Statistics Column Name Format( "Column" ), Link to Original Data Table( 0 ), Private );
	Close( sumt, No Save );

	category number = [=>];
	category average = [=>];
	For Each Row( subt,
		category number[:Make] = :N Rows; // each least-significant category in a VariabilityPlot is exactly X=1 width on the hidden x-axis, starting at zero
		category average[:Make] = :Wt
	);
	Close( subt, No Save );

	tree = rpt[t] << Report;
	Eval( Eval Expr(
	tree[FrameBox( 1 )] << Add Graphics Script(
		Local( {values = Expr( category average ), numbers = Expr( category number ), i, items, sum = 0},
			items = numbers << Get Keys;
			Pen Size( 2 );
			Pen Color( "Blue" );
			Summation( i = 1, N Items( items ),
				Line( Eval List( {sum, values[items[i]]} ), Eval List( {sum += numbers[items[i]], values[items[i]]} ) );
				0
			)
		)
	)
	) )
);
Jordan

View solution in original post

8 REPLIES 8
vince_faller
Super User (Alumni)

Re: How to add a graphics script dynamically to a variability chart with multiple frame boxes

I'm not sure what exactly you're trying but would something like this work?  

Names default to here( 1 );
dt = open("$SAMPLE_DATA\Big Class.jmp");
var_chart = dt << Variability Chart( Y( :height ), X( :sex ), By( :age ), stddevchart(0) );
summarize(dt, ages = by(:age));
var_rpt = var_chart << Report(); // this should just give a list of outlineboxes

for(i=1, i<=nitems(var_rpt), i++, 
	olb = var_rpt[i];
	framebox = olb[FrameBox(1)];
	framebox << Add Graphics Script(
		Transparency( 0.5 );
		Pen Color( "blue" );
		Line([0,100], [62.5, 62.5]);
	);
);
Vince Faller - Predictum
neelsrejan
Level III

Re: How to add a graphics script dynamically to a variability chart with multiple frame boxes

Hi Vince,

 

Thanks for the response, I see that you have 62.5 hard coded, but do you know how you would adapt that to be dynamic to be the value in :wt?

 

 

Re: How to add a graphics script dynamically to a variability chart with multiple frame boxes

I generally do not use variables in graphics scripts unless they are generated entirely internally to the frame box. Here is an example of my approach.

 

Names Default To Here( 1 );

// open example
dt = Open( "$SAMPLE_DATA\Big Class.jmp" );

// launch variability chart
var_chart = dt << Variability Chart( Y( :height ), X( :sex ), By( :age ), stddevchart( 0 ) );

// get summary in same order as By groups
Summarize( dt, age = by( :age ), avg = Mean( :height ) );
var_rpt = var_chart << Report;

// iterate over list and add script using H Line() with literal argument
For( i = 1, i <= N Items( age ), i++,
	Eval(
		Substitute(
			Expr(
				var_rpt[i][FrameBox(1)] << Add Graphics Script(
					Pen Color( "Red" ); H Line( aaa );
				);
			),
			Expr( aaa ), avg[i]
		)
	)
);
neelsrejan
Level III

Re: How to add a graphics script dynamically to a variability chart with multiple frame boxes

Hi Mark, thanks for your reply! I was wondering what the passed value of "aaa" is in H Line() and Expr(), I don't see it assigned anywhere so I'm curious as what that does? Thank you!

Re: How to add a graphics script dynamically to a variability chart with multiple frame boxes

The first expression is just a template. The expression 'aaa' is a placeholder for substitution. It is never evaluated. The Substitute() looks for Expr( aaa ) and substitutes the value.

neelsrejan
Level III

Re: How to add a graphics script dynamically to a variability chart with multiple frame boxes

I see, thanks for the explanation. Just out of curiosity, does jmp not evaluate values inside a function first. I have had trouble with this in the past but haven't been able to figure out what to search to understand the behavior having come from a python background. In my head H Line should just get avg[i] rather than have to substitute the value in but I get an error.

"invalid subscript (must be number or list of numbers) in access or evaluation of 'avg[ /*###*/i]' , avg[/*###*/i]"

For( i = 1, i <= N Items( age ), i++,
	Eval(
		Expr(
			var_rpt[i][FrameBox(1)] << Add Graphics Script(
				Pen Color( "Red" ); H Line( avg[i] );
			);
			),
		)
	);

I appreciate the help and any explanation, thanks!

Re: How to add a graphics script dynamically to a variability chart with multiple frame boxes

Expressions are a powerful feature in the JMP Scripting Language. I recommend reading the documentation to become more familiar with how they work and how they might be used.

 

Here is the correct way to use your last approach:

 

Names Default To Here( 1 );

// open example
dt = Open( "$SAMPLE_DATA\Big Class.jmp" );

// launch variability chart
var_chart = dt << Variability Chart( Y( :height ), X( :sex ), By( :age ), stddevchart( 0 ) );

// get summary in same order as By groups
Summarize( dt, age = by( :age ), avg = Mean( :height ) );
var_rpt = var_chart << Report;

// iterate over the list and add script using H Line() with the literal argument
For( i = 1, i <= N Items( age ), i++,
	Eval(
		Eval Expr(
			var_rpt[i][FrameBox(1)] << Add Graphics Script(
				Pen Color( "Red" ); H Line( Expr( avg[i] ) );
			);
		);
	)
);

 

ErraticAttack
Level VI

Re: How to add a graphics script dynamically to a variability chart with multiple frame boxes

You can loop over the return result from the original Variability Chart( By( ... ) ) command:

names default to here(1);
dt = 
// Open Data Table: Big Class.jmp
// → Data Table( "Big Class" )
Open( "$SAMPLE_DATA/Cars.jmp" );

rpt = dt << Variability Chart(
	Y( :Head IC),
	X( :Make, :Model ),
	Analysis Type( "Choose best analysis (EMS REML Bayesian)" ),
	Show Range Bars( 0 ),
	Show Cell Means( 0 ),
	Std Dev Chart( 0 ),
	Points Jittered( 1 ),
	By( :NAME("D/P"), :Protection ),
);

//find groupings:

subt = dt << Summary( Group( :"D/P"n, :Protection ), Link to Original Data Table( 0 ) );
dps = subt:"D/P"n << Get Values;
protections = subt:protection << Get Values;
Close( subt, No Save );

For( t = 1, t <= N Items( dps ), t++,
	Eval( eval Expr(
	rows = dt << Get Rows Where( :NAME("D/P") == Expr( dps[t] ) & :Protection == Expr( protections[t] ) );
	) );
	subt = dt << Subset( Rows( rows ), Columns( :Make, :Model, :Wt ), Not Linked, Private );
	sumt = subt << Summary( Group( :Make, Model ), Mean( :Wt ), Statistics Column Name Format( "Column" ), Link to Original Data Table( 0 ), Private );
	Close( subt, No Save );
	subt = sumt << Summary( Group( :Make ), Mean( :Wt ), Statistics Column Name Format( "Column" ), Link to Original Data Table( 0 ), Private );
	Close( sumt, No Save );

	category number = [=>];
	category average = [=>];
	For Each Row( subt,
		category number[:Make] = :N Rows; // each least-significant category in a VariabilityPlot is exactly X=1 width on the hidden x-axis, starting at zero
		category average[:Make] = :Wt
	);
	Close( subt, No Save );

	tree = rpt[t] << Report;
	Eval( Eval Expr(
	tree[FrameBox( 1 )] << Add Graphics Script(
		Local( {values = Expr( category average ), numbers = Expr( category number ), i, items, sum = 0},
			items = numbers << Get Keys;
			Pen Size( 2 );
			Pen Color( "Blue" );
			Summation( i = 1, N Items( items ),
				Line( Eval List( {sum, values[items[i]]} ), Eval List( {sum += numbers[items[i]], values[items[i]]} ) );
				0
			)
		)
	)
	) )
);
Jordan