cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Choose Language Hide Translation Bar
SpannerHead
Level III

Iteratively create columns containing formulae.

I would like to iterate through the columns that have spec limits and perform analyses against those.

 


	New Column("WM Minus Target", Numeric, "Continuous", Format("Best", 10), Formula(:WN - (:WN << get property("Spec Limits"))["Target"]), Set Selected);

The script located here is close to what I want.

 

Solved: When a spec is on, how do I write a script when I want to write a fail name? - JMP User Comm...

 

Just wondering how to get the more involved formula?

 

Thanks

 

SpannerHead

2 ACCEPTED SOLUTIONS

Accepted Solutions

Re: Iteratively create columns containing formulae.

Here's one way. It might be more elegant with an associative array instead of 2 lists, but using 2 lists is easier for me to wrap my head around:

Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Semiconductor Capability.jmp" );

lstCols = {};
lstTargets = {};

//get cols with targets
For Each( {i}, 1 :: N Col( dt ),
	t = .;
	Try( t = (Column( i ) << Get Property( "Spec Limits" ))["Target"], );
	If( !Is Missing( t ),
		Insert Into( lstCols, i );
		Insert Into( lstTargets, t);
	);
);

//make formulas
For Each( {i, j}, lstCols,
	//i = 5; j = 1;
	dt << New Column( char(Column Name( i )) || " Minus Target",
		Numeric,
		"Continuous",
		Format( "Best", 10 ),
		Formula( as column(Column( i )) - lstTargets[j] )
	)
);

/*JMP STATISTICAL DISCOVERY LLC (“JMP”) PERMITS THE USE OF THIS COMPUTER SOFTWARE CODE (“CODE”) ON AN AS-IS BASIS AND AUTHORIZES YOU TO USE THE CODE SUBJECT TO THE TERMS LISTED HEREIN.  BY USING THE CODE, YOU AGREE TO THESE TERMS.  YOUR USE OF THE CODE IS AT YOUR OWN RISK.  JMP MAKES NO REPRESENTATION OR WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRIGEMENT, AND TITLE, WITH RESPECT TO THE CODE.
You may use the Code solely as part of a software product you currently have licensed from JMP, JMP’s parent company SAS Institute Inc. (“SAS”), or one of JMP’s or SAS’s subsidiaries or authorized agents (the “Software”), and not for any other purpose.  The Code is designed to add functionality to the Software but has not necessarily been tested.  Accordingly, JMP makes no representation or warranty that the Code will operate error-free.  JMP is under no obligation to maintain, support, or continue to distribute the Code.
Neither JMP nor its licensors shall be liable to you or any third-party for any general, special, direct, indirect, consequential, incidental, or other damages whatsoever arising out of or related to your use or inability to use the Code, even if JMP has been advised of the possibility of such damages.  Except as otherwise provided above, the Code is governed by the same agreement that governs the Software.  If you do not have an existing agreement with JMP or SAS governing the Software, you may not use the Code.
JMP and all other JMP Statistical Discovery LLC product or service names are registered trademarks or trademarks of JMP Statistical Discovery LLC in the USA and other countries.  ® indicates USA registration.  Other brand and product names are registered trademarks or trademarks of their respective companies.
*/

 

View solution in original post

txnelson
Super User

Re: Iteratively create columns containing formulae.

And here is another way

Names Default To Here( 1 );
dt = 
// Open Data Table: semiconductor capability.jmp
// → Data Table( "semiconductor capability" )
Open( "$SAMPLE_DATA/semiconductor capability.jmp" );

colNames = dt << get column names( continuous, string );

For each( {col}, colNames,
	Eval(
		Eval Expr(
			theTarget = (Column( Eval( col ) ) << get property( "Spec Limits" ))["Target"];
			New Column( Expr( col ) || " Minus Target",
				Numeric,
				"Continuous",
				Format( "Best", 10 ),
				Formula( As Column( Eval( col ) ) - Expr( theTarget ) )
			);
		)
	);
);
Jim

View solution in original post

7 REPLIES 7

Re: Iteratively create columns containing formulae.

Here's one way. It might be more elegant with an associative array instead of 2 lists, but using 2 lists is easier for me to wrap my head around:

Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Semiconductor Capability.jmp" );

lstCols = {};
lstTargets = {};

//get cols with targets
For Each( {i}, 1 :: N Col( dt ),
	t = .;
	Try( t = (Column( i ) << Get Property( "Spec Limits" ))["Target"], );
	If( !Is Missing( t ),
		Insert Into( lstCols, i );
		Insert Into( lstTargets, t);
	);
);

//make formulas
For Each( {i, j}, lstCols,
	//i = 5; j = 1;
	dt << New Column( char(Column Name( i )) || " Minus Target",
		Numeric,
		"Continuous",
		Format( "Best", 10 ),
		Formula( as column(Column( i )) - lstTargets[j] )
	)
);

/*JMP STATISTICAL DISCOVERY LLC (“JMP”) PERMITS THE USE OF THIS COMPUTER SOFTWARE CODE (“CODE”) ON AN AS-IS BASIS AND AUTHORIZES YOU TO USE THE CODE SUBJECT TO THE TERMS LISTED HEREIN.  BY USING THE CODE, YOU AGREE TO THESE TERMS.  YOUR USE OF THE CODE IS AT YOUR OWN RISK.  JMP MAKES NO REPRESENTATION OR WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRIGEMENT, AND TITLE, WITH RESPECT TO THE CODE.
You may use the Code solely as part of a software product you currently have licensed from JMP, JMP’s parent company SAS Institute Inc. (“SAS”), or one of JMP’s or SAS’s subsidiaries or authorized agents (the “Software”), and not for any other purpose.  The Code is designed to add functionality to the Software but has not necessarily been tested.  Accordingly, JMP makes no representation or warranty that the Code will operate error-free.  JMP is under no obligation to maintain, support, or continue to distribute the Code.
Neither JMP nor its licensors shall be liable to you or any third-party for any general, special, direct, indirect, consequential, incidental, or other damages whatsoever arising out of or related to your use or inability to use the Code, even if JMP has been advised of the possibility of such damages.  Except as otherwise provided above, the Code is governed by the same agreement that governs the Software.  If you do not have an existing agreement with JMP or SAS governing the Software, you may not use the Code.
JMP and all other JMP Statistical Discovery LLC product or service names are registered trademarks or trademarks of JMP Statistical Discovery LLC in the USA and other countries.  ® indicates USA registration.  Other brand and product names are registered trademarks or trademarks of their respective companies.
*/

 

txnelson
Super User

Re: Iteratively create columns containing formulae.

And here is another way

Names Default To Here( 1 );
dt = 
// Open Data Table: semiconductor capability.jmp
// → Data Table( "semiconductor capability" )
Open( "$SAMPLE_DATA/semiconductor capability.jmp" );

colNames = dt << get column names( continuous, string );

For each( {col}, colNames,
	Eval(
		Eval Expr(
			theTarget = (Column( Eval( col ) ) << get property( "Spec Limits" ))["Target"];
			New Column( Expr( col ) || " Minus Target",
				Numeric,
				"Continuous",
				Format( "Best", 10 ),
				Formula( As Column( Eval( col ) ) - Expr( theTarget ) )
			);
		)
	);
);
Jim
SpannerHead
Level III

Re: Iteratively create columns containing formulae.

Looks interesting, gives me an error though.  Name Unresolved: theTarget in access or evaluation of 'theTarget', theTarget/*###*/

SpannerHead
Level III

Re: Iteratively create columns containing formulae.

The code works but when I look at the formula in the resulting column it looks like this.

As Column( Column( i ) ) - lstTargets[j]
txnelson
Super User

Re: Iteratively create columns containing formulae.

Not using Eval(Evalexpr()) does not allow for the full expansion of the formula code prior to execution.  Try my modified code below

Names Default To Here( 1 );
dt = 
// Open Data Table: semiconductor capability.jmp
// → Data Table( "semiconductor capability" )
Open( "$SAMPLE_DATA/semiconductor capability.jmp" );

colNames = dt << get column names( continuous, string );

For Each( {xcol}, colNames,
	col = xcol;
	theTarget = (Column( Eval( col ) ) << get property( "Spec Limits" ))["Target"];
	Eval(
		Eval Expr(
			New Column( col || " Minus Target",
				Numeric,
				"Continuous",
				Format( "Best", 10 ),
				Formula( As Column( Eval( col ) ) - Expr( theTarget ) )
			)
		)
	);
);
Jim

Re: Iteratively create columns containing formulae.

Jim's Eval() solution should be similar to how to get the formula to show up properly in my example as well.

jthi
Super User

Re: Iteratively create columns containing formulae.

Depending on your analysis, you could add new column for each measurement or stack your table first and create single new column.

Adding new columns for each parameter

Names Default To Here(1);

dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
cont_cols = dt << Get Column Names("Continuous", "String");

cols_created = {};
For Each({cont_col}, cont_cols,
	specs = Column(dt, cont_col) << Get Property("Spec Limits");
	If(Is Empty(specs), // skip columns without specs
		Continue();
	);
	cur_target = Try(specs["Target"], .); // If target isn't set -> use 0 (could for example use USL - LSL?)
	
	new_col = Eval(Substitute( // generally I use Eval(EvalExpr()) but in this case this makes expression more clear
		Expr(dt << New Column(cont_col || " Minus Target", Numeric, Continuos, Formula(
			_curcol_ - _targetval_
		))),
		Expr(_curcol_), Name Expr(AsColumn(dt, cont_col)),
		Expr(_targetval_), cur_target
	));	
	// new_col << Suppress Eval(1);
	Insert Into(cols_created, new_col << get name);
);

and you end up with columns like this (target won't be updated IF you change the column property)

jthi_0-1717153065908.png

Stacking

Names Default To Here(1);

dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
cont_cols = dt << Get Column Names("Continuous", "String");

ml = dt << Manage Limits(Process Variables(Eval(cont_cols))); // in this case this will open very annoying "help" window due to inconsistencies
dt_limits = ml << Save to Tall Limits Table;
ml << close window;

dt_stack = dt << Stack(
	columns(Eval(cont_cols)),
	Source Label Column("Measurement"),
	Stacked Data Column("Data"),
	Output Table("Data Stacked")
);

// If you don't care about LSL/USL they could be dropped from update
dt_stack << Update(
	With(dt_limits),
	Match Columns(:Measurement = :Variable),
	Replace Columns in Main Table(None)
);

dt_stack << New Column("Data Minus Target", Numeric, Continuous, Formula(
	:Data - :Target
));

Both data formats have their pros and cons which depends on what you are doing.

 

Edit:

This should get the values from column property BUT it won't re-evaluate (I wouldn't really use this if you can avoid it)

Names Default To Here(1);

dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
cont_cols = dt << Get Column Names("Continuous", "String");

cols_created = {};
For Each({cont_col}, cont_cols,
	specs = Column(dt, cont_col) << Get Property("Spec Limits");
	If(Is Empty(specs), // skip columns without specs
		Continue();
	);
	
	new_col = Eval(Substitute( // generally I use Eval(EvalExpr()) but in this case this makes expression more clear
		Expr(dt << New Column(cont_col || " Minus Target", Numeric, Continuos, Formula(
			_curcol_ - (_curcol_ << Get Property("Spec Limits"))["Target"]
		))),
		Expr(_curcol_), Name Expr(AsColumn(dt, cont_col))
	));	
	//new_col << Suppress Eval(1);
	Insert Into(cols_created, new_col << get name);
);

 

-Jarmo