@jthi ,
You were on the right track! Other expression manipulations were necessary to create the arguments to insert into their respective functions. In the mysim custom function, the arguments insert into modifying the distribution for the simulation, and generating the argument to insert into Simulate to Table have been explained in detail. This is a very exciting learning opportunity and opened my eyes to these types of advanced expressions.
If anyone wants to know more about expression manipulations, here's a link to documentation: https://www.jmp.com/support/help/en/17.0/#page/jmp/advanced-expressions-macros-and-lists.shtml#
Thank you to those who helped!
Names default to here(1);
dt = open( "$SAMPLE_DATA/Body Fat.jmp" );
mysim = function( {list, iteration, stddev, step},
// filter list of effects down to main effects. These are the effects whose name matches a column name
// take advantage of the speed of associative arrays to get the intersection set.
list << Intersect(Associative Array(dt<<Get Column Names("String")));
unique_factors = list << Get Keys; // get list of values remaining in list after intersection.
num_sim_factors = N Items( unique_factors );
// get reference to profiler in fit model
prof = Report(mymodel_sls)["Prediction Profiler"] << Get Scriptable Object;
/*** Build the expression to turn on the Simulator with random normal distributions for factors ***/
sim_factor = Expr(Factors()); // Base expression to add arguments to later.
// Loop through list of column names and add distribution specification as arguments to the Factors expression
for( i = 1, i <= num_sim_factors, i++,
Insert Into(sim_factor,
EvalExpr(Expr(AsName(unique_factors[i])) << Random( Normal(
Expr(col mean( Column(dt, unique_factors[i]) )), // evaluates to the column mean
Expr(stddev * col std dev(Column(dt, unique_factors[i] ))) // evaluates to a multiple of the column std dev
))); // result of EvalExpr() is an expression that gets inserted as an argument into the sim_factor expression
);
);
// use the sim_factor expression as an argument to the Simulator message sent to the profiler
// to turn on the simulator with appropriate distributions for the factors.
Eval(EvalExpr(prof << Simulator( 1, Expr(NameExpr( sim_factor )) )));
sim = prof << Get Simulator; // get a reference to the simulator object now that is it turned on
/************************************************************************************************/
/*** Build the expression to simulate to table with desired ranges, steps, and iterations ***/
toTableExpr = Expr(Simulate to Table()); // create empty expression for simulate to table
InsertInto(toTableExpr, EvalExpr(N Runs(Expr(iteration)))); // add the N Runs argument
// to see the expression at this point, you can use NameExpr(), and it will write it to the log
NameExpr(toTableExpr);
// Creates an argument for each factor
for( i = 1, i <= num_sim_factors, i++,
Insert Into(toTableExpr, // insert another argument into the expression
EvalExpr(Expr(AsName(unique_factors[i])) << Sequence Location(
Expr(Col Minimum(Column(dt, unique_factors[i]))), // evaluates to the col min of the current column
Expr(Col Maximum(Column(dt, unique_factors[i]))), // evaluates to the col max of the current column
Expr(step) // evaluates to the value of the variable step
)) // result of EvalExpr() is an expression with numbers inserted as arguments to Sequence Location()
);
);
// at this point, toTableExpr contains an expression that can be sent to the sim object as a message
SimDT = Eval(EvalExpr(sim << Expr(NameExpr(toTableExpr)))); // simulate to table with set sequence and N Runs.
/********************************************************************************************/
// The Simulate to Table message returns a reference to the simulation table. Meanwhile, the function returns
// the result of the last evaluation (without specifying otherwise). Since that is the table, we can set a
// variable equal to the function call in the main script and we have a reference to the simulation table
// created inside this function.
);
/////////////////////////// Cols to use - user adjustable
predict = {:"Neck circumference (cm)"n, :"Chest circumference (cm)"n,
:"Abdomen circumference (cm)"n, :"Hip circumference (cm)"n,
:"Thigh circumference (cm)"n, :"Knee circumference (cm)"n,
:"Ankle circumference (cm)"n, :"Biceps (extended) circumference (cm)"n,
:"Forearm circumference (cm)"n, :"Wrist circumference (cm)"n};
response = {:"Age (years)"n, :"Weight (lbs)"n, :"Height (inches)"n};
/////////////////////////// User input
num_response = N Items( response );
num_predict = N Items( predict );
// How many simulations to run?
sim_no = 10;
// How many standard deviations for each predictor in the simulation?
stddev = 3;
// Steps in simulation
steps = 2;
/////////////////////////// Changing col attribute
// In a later step, Simulate, the mean should be 0 due to this
for( i = 1, i <= num_response, i++,
response[i] << Set Property( "Coding", { col minimum( response[i] ), col maximum( response[i] ) } );
);
/////////////////////////// Modeling
/* Fit Model - Stepwise, w/ K-fold validation --> SLS --> Simulate */
for( k = 1, k <= num_response, k++,
// Names models for calling later
mymodel_sw = "FM_SW_" || char( k );
// Iterating through responses - JMP 17
mymodel_sw = Fit Model( Y( response[k] ),
Effects( Factorial to degree( eval( predict ) ), Response Surface( eval( predict ) ) ),
Personality("Stepwise"),
Run( "K-Fold Crossvalidation"n(5) )
);
// Runs modeling
mymodel_sw << Go;
// Finishes predictor selection before proceeding
mymodel_sw << Finish;
// Makes model
mymodel_sls = mymodel_sw << Make Model;
// Runs SLS model
mymodel_sls = mymodel_sls << Run; // this creates another object. assign your variable to that object
mymodel_sls << Profiler(1); // make sure profiler is on.
// Gets associative array of effect names.
// use this in the function to easily filter down to the main effect names
param_sls1 = Associative Array(mymodel_sls << Get Effect Names);
// Calls on custom function <--- This is second step
resultDT = mysim( param_sls1, sim_no, stddev, steps ); // assign variable to reference returned table
// Names Simulate to table dataset by response variable in for loop
resultDT << Set name( char( response[k] ) || "_report" );
);
ss
Learning every day!