Ri: Impilamento in colonne indicizzate JSL per gruppo (dati dei sensori e risorse)Forse qualcosa del genere:
Names Default To Here( 1 );
//dt=open("input_example.jmp");
//Stack data table
Data Table( "input_example.jmp" ) << Stack(
columns( Column Group( "A sensors" ), Column Group( "B sensors" ) ),
Source Label Column( "Label" ),
Stacked Data Column( "Data" ),
Output Table( "Stacked Data" )
);
//Text to columns
Data Table( "Stacked Data" ) << Text to Columns(
columns( :Label ),
Delimiters( " " )
);
//Delete column: Label 2
Data Table( "Stacked Data" ) << Delete Columns( :Label 2 );
//Change column name: Label 1 → Asset
Data Table( "Stacked Data" ):Label 1 << Set Name( "Asset" );
//Change column name: Label 3 → Sensor
Data Table( "Stacked Data" ):Label 3 << Set Name( "Sensor" );
//New column: Column 6
Data Table( "Stacked Data" ) << New Column( "Stddev of Sensor by Asset by Index",
Numeric,
"Continuous",
Format( "Best", 12 )
);
//Change column formula: Stddev of Sensor by Asset by Index
Data Table( "Stacked Data" ):Stddev of Sensor by Asset by Index <<
Set Formula( Col Std Dev( :Data, :Asset, :Index ) );
//Report snapshot: Stacked Data - Graph Builder
Data Table( "Stacked Data" ) << Graph Builder(
Size( 517, 450 ),
Show Control Panel( 0 ),
Variables(
X( :Index ),
Y( :Stddev of Sensor by Asset by Index ),
Overlay( :Asset )
),
Elements( Line( X, Y, Legend( 7 ) ), Points( X, Y, Legend( 8 ) ) )
);
Ho usato Worflow Builder in JMP 17 per "scrivere" questo script.
La chiave sta usando gli argomenti "by" nella formula.

Questo mi consente di impilare completamente i dati per avere la gerarchia completa con i dati tutti in una colonna.
Quindi ottengo lo stddev dell'intera colonna di dati per asset e per indice. Questo mi permette di fare questo grafico:

Ri: Impilamento in colonne indicizzate JSL per gruppo (dati dei sensori e risorse)Questo è un buon approccio. Tuttavia, una tabella completamente impilata presenta il problema di essere limitata a quelle formule che hanno un argomento "per".
Ad esempio, se volessi fare una formula che è: (sensore 1 - sensore 2) / sensore 3, sarà necessaria la tabella by-stacked.
Ri: Impilamento in colonne indicizzate JSL per gruppo (dati dei sensori e risorse)Risposta rimossa per evitare la confusione del futuro lettore
Ri: Impilamento in colonne indicizzate JSL per gruppo (dati dei sensori e risorse)Un'opzione è quella di seguire il percorso JSL puro se si dispone della tabella della gerarchia. Il codice potrebbe essere in grado di spiegarsi da solo:
Names Default To Here(1);
dt_hier = Open("$DOWNLOADS/hierarchy_example.jmp");
dt_input = Open("$DOWNLOADS/input_example.jmp");
// some assumptions:
// both parents will have same amount of columns
new_col = dt_hier << New Column("Data Cols", Character, Nominal, << Set Each Value(
Regex(:Child column, "sensor \d")
));
data_cols = Associative Array(new_col) << get keys;
dt_hier << Delete Column(new_col);
dt_collector = New Table("data",
New Column("Index", Numeric, Ordinal),
New Column("Group", Character, Nominal)
);
For Each({data_col}, data_cols,
dt_collector << New Column(data_col, Numeric, Continuous)
);
Summarize(dt_hier, parents = by(:Parent));
For Each({parent}, parents,
parent_rows = Loc(dt_hier[0, "Parent"], parent);
parent_cols = dt_hier[parent_rows, "Child column"];
parent_data = dt_input[0, parent_cols];
non_missing_idx = Loc(parent_data);
row_count = N Items(non_missing_idx) / n cols(parent_data);
parent_data_clean = Shape(parent_data[non_missing_idx], row_count);
first_row = N Rows(dt_collector) + 1;
last_row = first_row + row_count - 1;
dt_collector << Add Rows(row_count);
dt_collector[Index(first_row, last_row), "Index"] = Index(1, row_count)`;
dt_collector[Index(first_row, last_row), "Group"] = Repeat({parent}, row_count);
dt_collector[Index(first_row, last_row), data_cols] = parent_data_clean
);

Alcune ipotesi fatte qui e nessuna corretta gestione degli errori
Ri: Impilamento in colonne indicizzate JSL per gruppo (dati dei sensori e risorse)La gerarchia può essere già presente nella tabella come metadati (proprietà colonna).
Ho aggiornato l'esempio in modo da avere genitore (gruppo), alias genitore, figlio e alias figlio incorporati nella tabella.
Penso che l'approccio più intuitivo sarà quello di impilare la tabella per risorsa (sottoinsieme), dividere i dati per etichetta e quindi concatenare le tabelle insieme.
Ri: Impilamento in colonne indicizzate JSL per gruppo (dati dei sensori e risorse)Ho anche semplificato i requisiti (niente più valori vuoti) e ho trovato una soluzione (stack, split, concat) che deve essere eseguita in modo iterativo (per asset). I dati della gerarchia sono ora incorporati nella tabella principale (i progressi possono essere trovati in input_example).
Ri: Impilamento in colonne indicizzate JSL per gruppo (dati dei sensori e risorse)L'operazione più semplice che ho trovato è stata automatizzare questi passaggi di dati.
1) Pila

2) Diviso

3) Concatenare

Impilamento in colonne indicizzate JSL per gruppo (dati e risorse dei sensori)Nel settore manifatturiero, è comune estrarre i dati dei sensori nel seguente modulo, dove A e B corrispondono a dispositivi simili (noti come risorse ).
In questo formato, l'utente deve creare una formula combinata per ciascun gruppo principale. Per esempio:
(Input: la tabella dei dati del sensore richiede colonne specifiche per gruppo principale)

Quando si gestiscono più risorse, ciò diventa complicato, quindi un modo migliore è impilare i dati per risorsa di gruppo.
Per fare ciò a livello di programmazione, abbiamo bisogno di dati contestuali contenenti la gerarchia. Per esempio:
(Input: gerarchia delle risorse)

In JSL, come è possibile passare dai dati dei sensori e dalla gerarchia (input) alla tabella delle risorse (output desiderato)?
(output: tabella dati asset)

Tutte le tabelle e gli script sono allegati. Ecco lo script della tabella di input (i metadati contenenti genitore-figlio vengono aggiunti come proprietà della colonna).
Names Default To Here( 1 );
// New data table
dt = New Table( "sensor table" );
n_rows = 10;
n_additional_rows = 0;
// New column: Index
dt << New Column( "Index", Numeric, "Continuous", Format( "Best", 12 ) ) <<
Begin Data Update << Add Rows( n_rows );
dt:Index << Set Formula( Row() );
dt << End Data Update;
// A sensor
dt << New Column( "A sensor 1",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Selected
) << New Column( "A sensor 2",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Selected
) << New Column( "A sensor 3",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Selected
) << Group Columns( "A sensors", {:A sensor 1, :A sensor 2, :A sensor 3} )
<< Begin Data Update;
For Each Row(
dt,
:A sensor 1 = Random Normal( 0, 1 );
:A sensor 2 = Random Normal( 0, 1 );
:A sensor 3 = Random Normal( 0, 1 );
);
dt << End Data Update;
// B sensors
dt << Add Rows( n_additional_rows );
dt << New Column( "B sensor 1",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Selected
) << New Column( "B sensor 2",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Selected
/*) << New Column( "B sensor 3",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Selected*/
) << Group Columns( "B sensors", {:B sensor 1, :B sensor 2}) //, :B sensor 3} )
<< Begin Data Update;
For Each Row(
dt,
:B sensor 1 = Random Normal( 0, 3 );
:B sensor 2 = Random Normal( 0, 2 );
//:B sensor 3 = Random Normal( 0, 3.5 );
);
dt << End Data Update;
colnames = dt << Get Column Names( String );
for each({col, index}, colnames,
column(dt, col) << Set Property( "child", col ) );
// Calculations.
// New formula column: Stdev[A sensor ...r 2,A sensor 3]
dt << New Column( "Stdev[A sensors]",
Numeric,
"Continuous",
Format( "Best", 12 ),
Formula( Std Dev( :A sensor 1, :A sensor 2, :A sensor 3 ) ));
// Move selected column: Stdev[A sensors]
dt <<MOVE selected="" columns=""></MOVE>
Automazione e scripting