Re : Empilage dans les colonnes indexées JSL par groupe (données de capteur et actifs)Peut-être quelque chose comme ça :
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 ) ) )
);
J'ai utilisé Worflow Builder dans JMP 17 pour "écrire" ce script.
La clé est d'utiliser les arguments "by" dans la formule.

Cela me permet d'empiler complètement les données pour avoir la hiérarchie complète avec les données dans une seule colonne.
Ensuite, j'obtiens le stddev de toute la colonne de données par actif et par index. Cela me permet de faire ce graphique:

Re : Empilage dans les colonnes indexées JSL par groupe (données de capteur et actifs)C'est une bonne approche. Pourtant, une table entièrement empilée a le problème d'être limitée aux formules qui ont un argument "par".
Par exemple, si je voulais faire une formule qui soit : (capteur 1 - capteur 2) / capteur 3, il faudra le tableau empilé.
Re : Empilage dans les colonnes indexées JSL par groupe (données de capteur et actifs)Réponse supprimée pour éviter la confusion du futur lecteur
Re : Empilage dans les colonnes indexées JSL par groupe (données de capteur et actifs)Une option consiste à utiliser une route JSL pure si vous avez la table hiérarchique. Le code pourrait peut-être s'expliquer :
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
);

Quelques hypothèses faites ici et aucune gestion d'erreur appropriée
Re : Empilage dans les colonnes indexées JSL par groupe (données de capteur et actifs)La hiérarchie peut déjà être dans la table en tant que métadonnées (propriété de colonne).
J'ai mis à jour l'exemple afin que vous ayez un parent (groupe), un alias parent, un enfant et un alias enfant intégrés dans la table.
Je pense que l'approche la plus intuitive sera d'empiler la table par un actif (sous-ensemble), de diviser les données par étiquette, puis de concaténer les tables ensemble.
Re : Empilage dans les colonnes indexées JSL par groupe (données de capteur et actifs)J'ai également simplifié les exigences (plus de valeurs vides) et trouvé une solution (pile, fractionnement, concat) qui doit être effectuée de manière itérative (par actif). Les données de la hiérarchie sont maintenant intégrées dans la table principale (la progression peut être trouvée dans input_example).
Re : Empilage dans les colonnes indexées JSL par groupe (données de capteur et actifs)L'opération la plus simple que j'ai trouvée consistait à automatiser ces étapes de données.
1) Pile

2) Fractionner

3) Concaténer

Empilement dans des colonnes indexées JSL par groupe (données de capteur et actifs)Dans le secteur de la fabrication, il est courant d'extraire les données des capteurs sous la forme suivante, où A et B correspondent à des appareils similaires (appelés actifs ).
Dans ce format, l'utilisateur doit créer une formule combinée pour chaque groupe parent. Par exemple:
(Entrée : le tableau de données du capteur nécessite des colonnes spécifiques par groupe parent)

Lors de la gestion de plusieurs actifs, cela devient fastidieux. Une meilleure solution consiste donc à empiler les données par actif de groupe.
Pour ce faire par programmation, nous avons besoin de données contextuelles contenant la hiérarchie. Par exemple:
(Entrée : hiérarchie des actifs)

En JSL, comment pouvez-vous passer des données et de la hiérarchie des capteurs (entrées) à la table des actifs (sortie souhaitée) ?
(sortie : tableau de données sur les actifs)

Tous les tableaux et scripts sont joints. Voici le script de la table d'entrée (les métadonnées contenant le parent-enfant sont ajoutées en tant que propriétés de colonne).
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>
Automatisation et scripts