Hello Jarmo,
Stack > Update > Split is a great idea!!!
I have been able to implement it successfully, but my code is a bit dirty (a lot of For() loops, intermediate steps,...).
Instead of:
- Concatenate the table multiple times
- Then populating a column from a list of repeated metrics
I would like to become better in optimizing my code.
Is there a way to populate dt5 in a more cleaner/optimized way? (use native JMP commands maybe?)
I would love your suggestions on this
But anyway, thanks a lot for helping me on this
-Voiz
Names Default To Here( 1 );
clear symbols();
Deletesymbols();
//Create table with random distribution (table 1)
dt = New Table( "tabletest",
Add Rows( 5000 ),
New Column( "Product", Character, "Nominal", formula("Product " ||char( Random Integer( 1, 4 )))),
New Column( "Metric1", Numeric, "Continuous", formula( Random Normal( 10, 1 ) ) ),
New Column( "Metric2", Numeric, "Continuous", formula( Random Gamma( 10, 1 ) ) ),
New Column( "Metric3", Numeric, "Continuous", formula( Random Gamma( 10, 2 ) ) ),
);
Column( dt, "Metric1" ) << set property( "spec limits", {LSL( 5 ), USL( 25 ), Show Limits( 0 )} );
Column( dt, "Metric2" ) << set property( "spec limits", {LSL( 0 ), USL( 40 ), Show Limits( 0 )} );
Column( dt, "Metric3" ) << set property( "spec limits", {LSL( 5 ), USL( 40 ), Show Limits( 0 )} );
dt << save( "$Desktop\tabletest.jmp" );
//Get a list from all unique Product
SplitBy = "Product";
summarize(ColumnSplitBy=by(Column (SplitBy)));
show(ColumnSplitBy);
For( i = N Items( ColumnSplitBy ), i > 0, i--,
If( ColumnSplitBy[i] == "",
Remove From( ColumnSplitBy, i, 1 );
)
);
//Get Column name
MetricCols = dt << Get Column Names( numeric, continuous, "string" );
show(MetricCols);
//Get all unique combo of 2 Products
ColumnSplitByCombo = aslist( nchoosekMatrix(nitems(ColumnSplitBy), 2));
show (ColumnSplitByCombo);
//Create a combinaed datatable with stats (Table 2)
ow = dt << Oneway(
Y(Eval(MetricCols)),
X(Eval(SplitBy)),
Means and Std Dev(1),
SendToReport(
Dispatch(
{"Means and Std Deviations"},
"Std Dev Lower 95%",
NumberColBox,
{Visibility("Visible")}
),
Dispatch(
{"Means and Std Deviations"},
"Std Dev Upper 95%",
NumberColBox,
{Visibility("Visible")}
)
),
Invisible
);
tb = Report(ow[1])[Outline Box("Means and Std Deviations"), Table Box(1)];
dt2 = tb << Make Combined Data Table;
tb << close window;
//Create new table for the result, each row has a unique pair of Levels
dt3 = astable( nchoosekMatrix(nitems(ColumnSplitBy), 2), << column names({"x", "y"}) );
dt3 << new column ("first", character, << set values ( ColumnSplitBy[dt3:x << get values]));
dt3 << new column ("second", character, << set values ( ColumnSplitBy[dt3:y << get values]));
dt3 << delete columns (1::2);
//Create a nested list with each pair of levels
Listdt3 = aslist( nchoosekMatrix(nitems(ColumnSplitBy), 2));
show (Listdt3);
// I tried to use associate array() to match the level and name but couldn't make it work
// Loop over Metrics and perform these for each of them
// Concatenate results into single table
dt3 = As Table(NChooseK Matrix(N Items(ColumnSplitBy), 2), <<column names({"x", "y"}));
dt3 << New Column("first", character, <<set values(ColumnSplitBy[dt3:x << get values]));
dt3 << New Column("second", character, <<set values(ColumnSplitBy[dt3:y << get values]));
dt3 << new column("R", Numeric, Ordinal, Formula(Row()));
dt4 = dt3 << Stack(
columns(:first, :second),
Source Label Column("Label"),
Stacked Data Column("Data"),
"Non-stacked columns"n(Keep(:R)),
);
close(dt3, no save);
// create final table
dt5 = New Table("final",
New Column( "R", Character, "Nominal"),
New Column( "Label", Character, "Nominal"),
New Column( "Data", Character, "Nominal")
);
// create the Metric list to populate into dt5 metric column <-- not very clean
MetricListFinal = {};
For (k=1, k<=N items(MetricCols), k++,
For(j=1, j<=N rows(dt4), j++,
Insert into(MetricListFinal, MetricCols[k]);
));
show(MetricListFinal);
// concatenate the stacked list of unique pairs of level <-- not very clean
For(i=1, i<=N items(MetricCols), i++,
dt5 << concatenate(data table(dt4), append to first table(1));
);
// populate the column with the list of metrics <-- not very clean
dt5 << New Column( "Metric", Character, "Nominal", values(MetricListFinal));
// update table from Combined stats table
dt5 << Update(
With(dt2),
Match Columns(:Data = :Level, :Metric = :Y )
);
// split table by level
dt5 << Split(
Split By( :Label ),
Split(
:Metric, :Data, :Number, :Mean, :Std Dev, :Std Err Mean, :Lower 95%,
:Upper 95%, :Std Dev Lower 95%, :Std Dev Upper 95%
),
Output Table( "untitled 19.jmp" ),
Remaining Columns( Drop All ),
Sort by Column Property
);