Re: Apilamiento en columnas indexadas JSL por grupo (datos y activos del sensor)Tal vez algo como esto:
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 ) ) )
);
Usé Worflow Builder en JMP 17 para "escribir" este script.
La clave es usar los argumentos "por" en la fórmula.

Esto me permite apilar completamente los datos para tener la jerarquía completa con todos los datos en una columna.
Luego obtengo el stddev de toda la columna de datos por activo y por índice. Eso me permite hacer este gráfico:

Re: Apilamiento en columnas indexadas JSL por grupo (datos y activos del sensor)Este es un buen enfoque. Sin embargo, una tabla completamente apilada tiene el problema de estar limitada a aquellas fórmulas que tienen un argumento "por".
Por ejemplo, si quisiera hacer una fórmula que sea: (sensor 1 - sensor 2) / sensor 3, se necesitará la tabla apilada.
Re: Apilamiento en columnas indexadas JSL por grupo (datos y activos del sensor)Respuesta eliminada para evitar la confusión del futuro lector
Re: Apilamiento en columnas indexadas JSL por grupo (datos y activos del sensor)Una opción es seguir la ruta JSL pura si tiene la tabla de jerarquía. El código podría explicarse 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
);

Se han hecho bastantes suposiciones aquí y no hay un manejo adecuado de errores.
Re: Apilamiento en columnas indexadas JSL por grupo (datos y activos del sensor)La jerarquía ya puede estar en la tabla como metadatos (propiedad de columna).
He actualizado el ejemplo para que tenga padre (grupo), alias padre, hijo y alias hijo incrustados en la tabla.
Creo que el enfoque más intuitivo será apilar la tabla por un activo (subconjunto), dividir los datos por etiqueta y luego concatenar las tablas.
Re: Apilamiento en columnas indexadas JSL por grupo (datos y activos del sensor)También simplifiqué los requisitos (no más valores vacíos) y encontré una solución (apilar, dividir, concatenar) que debe hacerse de forma iterativa (por activo). Los datos de la jerarquía ahora están incrustados en la tabla principal (el progreso se puede encontrar en input_example).
Re: Apilamiento en columnas indexadas JSL por grupo (datos y activos del sensor)La operación más sencilla que encontré fue automatizar estos pasos de datos.
1) Pila

2) dividir

3) Concatenar

Apilamiento en columnas indexadas JSL por grupo (datos de sensores y activos)En la fabricación, es común extraer datos del sensor en la siguiente forma, donde A y B corresponden a dispositivos similares (conocidos como activos ).
En este formato, el usuario necesita crear una fórmula combinada para cada grupo principal. Por ejemplo:
(Entrada: la tabla de datos del sensor necesita columnas específicas por grupo principal)

Cuando se manejan varios activos, esto resulta engorroso, por lo que una mejor manera es apilar los datos por activo del grupo.
Para hacer esto mediante programación, necesitamos datos contextuales que contengan la jerarquía. Por ejemplo:
(Entrada: jerarquía de activos)

En JSL, ¿cómo se puede pasar de los datos y la jerarquía del sensor (entradas) a la tabla de activos (salida deseada)?
(salida: tabla de datos de activos)

Se adjuntan todas las tablas y guiones. Aquí está el script de la tabla de entrada (los metadatos que contienen padre-hijo se agregan como propiedades de columna).
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>
Automatización y secuencias de comandos