Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columnaTengo un conjunto de especificaciones que un producto en producción debería aprobar. Tengo una columna con una fórmula que especifica los valores necesarios (Límites) por cada especificación y crea un aprobado/fallo binario. Esta fórmula se utiliza para crear un gráfico de Pareto de número y porcentaje de paso. Quiero crear un gráfico de Pareto interactivo con cuadros deslizantes para ajustar los límites de la prueba, y ver cómo cambiar estos límites cambiaría la cantidad de elementos que aprueban/desaprueban la prueba.
Mis dos problemas principales son los siguientes:
1) Hay varios tipos de productos que se probarán. No tendré una cantidad constante de especificaciones por producto, por lo que planeo insertar estas especificaciones en una lista (en el código adjunto que sería "especificación") y usar una tabla de datos externa para completar esas especificaciones para el producto deseado. Esto no es algo con lo que necesite ayuda, pero es algo a tener en cuenta, ya que tendré que ingresar cuadros deslizantes, cuadros numéricos, etc. en un bucle for sin hacer referencia directa a las variables.
2) Necesito una matriz de variables (límites de especificación) para poder actualizar la fórmula con fines de prueba. De nuevo, esto tendrá que estar en un bucle for. Tal como está la secuencia de comandos en este momento, parece que los valores de los límites de especificación no se actualizan en la fórmula para la columna de aprobación/rechazo. Cuando el cuadro deslizante recibe el comando << inval y el gráfico se actualiza, no sucede nada ya que la columna real de aprobado/reprobado no se actualiza. Actualmente estoy usando una matriz asociativa para almacenar los límites de especificación. Esta puede no ser la forma correcta de hacer esto.
He adjuntado la tabla de datos de muestra que estoy usando, así como el script actual. ¡Gracias!
Names default to here(1);
RangeMin = Associative array(["m1" => 0,
"m2" => 0,
"m3" => 0,
"thickness" => 0]);
RangeMax = Associative array(["m1" => 1,
"m2" =>1,
"m3" => 1,
"thickness" => 20]);
limit = Associative array(["m1" => 0.5,
"m2" => 0.5,
"m3" => 0,
"thickness" => 4]);
SliderVars = {0.5,0.5,0.5,10};
spec = {"m1","m2","m3","thickness"};
GraphingTable = current data table();
finalDisplay = New Window ("test", testlist = h list box());
:name("Pass/Fail") << Set Formula(
if((:thickness >= limit["thickness"] & :m3 >= limit["m3"] & m2 >= limit["m2"] & m1 >= limit["m1"]), "Pass", "Fail" )
);
PP= Graphing Table << Pareto Plot( Cause( :"Pass/Fail"n ) );
ValuesOutlineBox = Outline Box ( "Values", SliderList = v list box());
For(i=1, i<= n items(spec),i++,
SliderList << append(
h list box(
Text box(spec[i]),
testing = spec[i];
eval(
parse(
eval insert(
"Var^char(i)^ = ^SliderVars[i]^;
SB^char(i)^ = Slider Box(
^RangeMin << get value(spec[i])^,
^RangeMax << get value(spec[i])^,
Var^char(i)^,
NEB^char(i)^ << set( Var^char(i)^ );
limit[testing] = Var^char(i)^;
testlist[2] << Delete Box();
wait(0.1);
testlist << append(report(PP));
);"
);
);
),
testing = spec[i];
eval(
parse(
eval insert(
"NEB^char(i)^ = Number Edit Box( Var^char(i)^,
<< set function(
Function( {this},
Var^char(i)^ = this << get;
SB^char(i)^ << inval;
limit[testing] = Var^char(i)^;
testlist[2] << Delete Box();
wait(0.1);
testlist << append(report(PP));
)
)
);"
);
);
),
)
)
);
testlist << append(ValuesOutlineBox);
testlist << append(report(PP));Ingeniería de Calidad y ProcesosventanasRe: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columnaNo parece estar cambiando la matriz de especificaciones. Eso es lo que pensé inicialmente al principio también. Sin embargo, pude hacer referencia a los cuadros individuales dentro del cuadro de lista V.Agradezco su ayuda como siempre.
Re: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columna¡Gracias! Buen ejemplo.
Re: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columnaCreo que los valores deben guardarse en la matriz asociativa de especificaciones cuando los cambia. Pero también puede intentar guardar las referencias a los cuadros de edición de números en una lista u otra matriz asociativa. O tal vez pueda usar XPath (o algún otro medio para viajar por la estructura de árbol) para obtener esas referencias cuando las necesite.
Re: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columnaEncontré otro problema con este script y esperaba conocer su opinión. Si ingreso manualmente un número en el cuadro de edición de números para las especificaciones, quiero agregar un botón para poder guardar las especificaciones en otra tabla. Agregar el botón no es un problema, pero no sé cómo podré hacer referencia a los valores actuales de los cuadros de edición de números. Después de para cada función, se agregan al cuadro de lista V y esos valores se actualizan en la columna de fórmula. Pero sin una forma de hacer referencia a los valores del cuadro de edición de números individuales o la capacidad de almacenar esos números e ingresarlos en una estructura de datos separada con una referencia a la especificación, no sé cómo puedo guardar estos nuevos límites en el script. Hacer referencia al cuadro de lista new_control H solo mostrará el último cuadro que pasó por cada ciclo. Cualquier pensamiento o sugerencia sería genial.
Re: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columnaSegún el soporte de JMP, el desarrollo de JMP lo consideró un comportamiento no deseado y se abordará en una versión futura.
Re: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columnaGracias. Si escucha algo sobre el problema del cuadro deslizante de rango, me interesaría mucho verlo.
Re: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columnaUsaría Range Slider Box, pero parece que no funciona correctamente con la matriz asociativa y la lista como cuarto argumento (mañana enviaré un correo electrónico a soporte sobre esto). Así que volvería a las cajas Slider.
Esto ahora usa expresión de fórmula y cuadros de doble control deslizante (es bastante fácil romper scripts como este que dependen de los nombres de las variables en las ventanas, por lo que es posible que deba agregar espacios de nombres o algo más para esos)
Names Default To Here(1);
//declare associative array for specs
specs = Associative Array();
//open limits file in JMP
LimitsTable = open("vinyl data limits.jmp", invisible);
//set testing data to be able to manipulate in JMP
GraphingTable = open("Vinyl Data.jmp");
//Select the Specs you want to compare by using a COL LIST BOX
ListNumericCols = GraphingTable << Get Column Names(numeric);
nw = New Window("Select Wanted Specifications", << Modal, << return result,
clb = Col List Box (<< Set Items (ListNumericCols))
);
ListSpecNames = nw["clb"];
show(ListSpecNames);
//insert spec names into associative array
for (i=1,i< (N Items(ListSpecNames) + 1), i++,
Insert Into(specs, ListSpecNames[i]);
ColSpec = Column(LimitsTable, 1); //1 is the coolumn for spec name
LimitList= {};
//Insert Lower Limit onto
for(j=1, j < (nrows(LimitsTable)+1), j++,
if (ColSpec[j] == ListSpecNames[i],
ColLimit = Column(LimitsTable, 2);//2 is the column for lower limit
MinVal = 0;
if(ColLimit[j] > 0, MinVal = ColLimit[j] / 2, MinVal = ColLimit[j]*2);
InsertInto(LimitList, MinVal );
break();
));
for(k=1, k < (nrows(LimitsTable)+1), k++,
if (ColSpec[k] == ListSpecNames[i],
ColLimit = Column(LimitsTable, 2);//2 is the column for lower limit
InsertInto(LimitList, ColLimit[k]);
break();
));
for(l=1, l < (nrows(LimitsTable)+1), l++,
if (ColSpec[l] == ListSpecNames[i],
ColLimit = Column(LimitsTable, 3);//3 is the column for lower limit
InsertInto(LimitList, ColLimit[l]);
break();
));
for(m = 1, m < (nrows(LimitsTable)+1), m++,
if (ColSpec[m] == ListSpecNames[i],
ColLimit = Column(LimitsTable, 3);//3 is the column for upper limit
MaxVal = 0;
if(ColLimit[m] > 0, MaxVal = ColLimit[m] *2, MaxVal = ColLimit[m] /2 );
InsertInto(LimitList, MaxVal );
break();
)
);
show (LimitList);
specs[ListSpecNames[i]] = LimitList
);
//show(specs); for debugging and making sure specs array is being populated
//sel_specs = Associative Array(ListSpecNames);
//specs << Intersect(sel_specs);
//*******************************************************************
//Create Pass Fail column if not existing.
if(!contains(GraphingTable << Get Column Names("String"), "Pass/Fail"),
GraphingTable << new column("Pass/Fail", Character);
);
//using a string to insert a formula into the row that can be called upon dynamically
formula_expr = Expr(
f = "If(All(";
For Each({{spec, limits}}, specs,
f ||= Eval Insert("^limits[2]^ < :^spec^ < ^limits[3]^ & ");
);
//drop last &
f = Left(f, Length(f) - 3);
f ||= "),"; // close all
f ||= "\!N\!t\!"PASS\!",\!"FAIL\!"
)";
Eval(EvalExpr(Column(GraphingTable, "Pass/Fail") << Set Formula(
Expr(Parse(f));
)));
);
formula_expr;
nw2 = New Window("test", testlist = H List Box(
ValuesOutlineBox = Outline Box("Values", SliderList = V List Box()),
Graphing Table << Pareto Plot(Cause(:"Pass/Fail"n))
));
For Each({{spec_name, spec_list, idx}}, specs,
new_control = H List Box(
Text Box(spec_name),
rsb = Slider Box(spec_list[1], spec_list[4]),
Number Edit Box(spec_list[2], << Set Minimum(spec_list[1]), << Set Maximum(spec_list[4]), << Set Function(function({this},
(this << Prev Sib) << Set(this << get);
formula_expr;
)))
);
Eval(EvalExpr(rsb << Set Var(specs[Expr(spec_name)][2])));
rsb << Set Function(function({this},
(this << sib) << Set(this << Get, Run Script(1));
));
SliderList << Append(new_control);
);
For Each({{spec_name, spec_list, idx}}, specs,
new_control = H List Box(
Text Box(spec_name),
rsb = Slider Box(spec_list[1], spec_list[4]),
Number Edit Box(spec_list[2], << Set Minimum(spec_list[1]), << Set Maximum(spec_list[4]), << Set Function(function({this},
(this << Prev Sib) << Set(this << get);
formula_expr;
)))
);
Eval(EvalExpr(rsb << Set Var(specs[Expr(spec_name)][3])));
rsb << Set Function(function({this},
(this << sib) << Set(this << Get, Run Script(1));
));
SliderList << Append(new_control);
);
Ejemplo del problema:
Names Default To Here(1);
var1 = 1;
var2 = 2;
var3 = 2;
var4 = 1;
aa = ["low" => 1, "up" => 2];
l = {};
l[1] = 1;
l[2] = 2;
nw = New window("test",
rsb1 = Range Slider Box(1, 2, var1, var2, Show(1)),
rsb2 = Range Slider Box(1, 2, aa["low"], aa["up"]),
rsb2_1 = Range Slider Box(1, 2, aa["low"], var3),
rsb1_2 = Range Slider Box(1, 2, var4, aa["up"]),
rsb3 = Range Slider Box(1, 2, l[1], l[2]),
);
Show(rsb1 << Get Lower Var, rsb1 << Get Upper Var);
Show(rsb2 << Get Lower Var, rsb2 << Get Upper Var);
Show(rsb2_1 << Get Lower Var, rsb2_1 << Get Upper Var);
Show(rsb1_2 << Get Lower Var, rsb1_2 << Get Upper Var);
Show(rsb3 << Get Lower Var, rsb3 << Get Upper Var);
Eval(EvalExpr(rsb3 << Set Lower Var(Expr(Expr(l[1])))));
Eval(EvalExpr(rsb3 << Set Upper Var(Expr(Expr(l[2])))));
Show(rsb3 << Get Lower Var, rsb3 << Get Upper Var);
Re: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columna¿Cree que funcionaría mejor tener dos cuadros deslizantes, uno para el límite superior y otro para el límite inferior de cada especificación en lugar de tratar con los argumentos de los cuadros deslizantes de rango? Las pruebas de ayer arrojaron muchos más problemas con los cuadros deslizantes de rango con mucha menos documentación sobre los argumentos del tipo de cuadro. Creo que solucionaría el problema del cuadro de rango, pero podría complicar la parte de la fórmula.
Re: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columnaPara la fórmula, tiene al menos dos opciones: puede usar la expresión para actualizar el valor en la fórmula que ejecuta cada vez que se actualizan las especificaciones o modificar la fórmula para usar la matriz asociativa de especificaciones
f = "If(All(";
For Each({{spec, limits}}, specs,
f ||= Eval Insert("specs[\!"^spec^\!"][2] < :^spec^ < specs[\!"^spec^\!"][3] & ");
);
//drop last &
f = Left(f, Length(f) - 3);
f ||= "),"; // close all
f ||= "\!N\!t\!"PASS\!",\!"FAIL\!"
)";
Range Slider Box es aún más complicado que Slider Box, por lo que resolver los problemas con eso es un desafío mayor. Lo más probable es que ni siquiera me moleste con Eval(EvalExpr()) y simplemente usaría Eval(Parse()) y trataría de obtener las referencias correctas allí. Comenzaría solo con Ranger Slider Box y después de que los hiciera funcionar, agregaría Number Edit Boxes uno a la vez (el cuarto argumento de Range Slider Boxes podría tener un poco de errores ...)
Re: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columnaAgradezco mucho la ayuda que me ha brindado en los últimos días. He estado trabajando a través de sus soluciones a esto, así como a mi otra publicación, Tener una actualización de fórmula de columna basada en una matriz asociativa a la que hace referencia una lista.
Revisé y traté de resolver las expresiones parse y eval y estoy entendiendo cómo funciona eso en jsl. Tengo un problema con la combinación de las dos ideas. Me di cuenta de que sería mejor tener 4 índices en la matriz asociativa para almacenar especificaciones. En el formato "espec" => {, , , }. Gracias a su ayuda con el análisis, la siguiente secuencia de comandos ahora crea esta matriz y una columna Aprobado/Fallado para ver si se cumplen todas las especificaciones. El objetivo es aflojar las tolerancias en los límites, hasta las tolerancias más bajas o máximas para obtener la nueva tasa de rendimiento de paso deseada del producto, y actualizar el gráfico de Pareto como lo arregló anteriormente. He intentado implementar un cuadro deslizante de rango, ya que esto sería más intuitivo para relajar las tolerancias en los límites, pero tengo problemas. También rompe la actualización automática del diagrama de Pareto como antes.
Creo que un problema podría ser que debido a que la cadena "f" se define inicialmente, no creo que se actualice para futuras ejecuciones de configuración de la fórmula para la columna de falla de paso. Cualquier forma en que pueda ayudar sería muy apreciada.
Names Default To Here(1);
//declare associative array for specs
specs = Associative Array();
//open limits file in JMP
LimitsTable = open("vinyl data limits.jmp", invisible);
//set testing data to be able to manipulate in JMP
GraphingTable = open("Vinyl Data.jmp");
//Select the Specs you want to compare by using a COL LIST BOX
ListNumericCols = GraphingTable << Get Column Names(numeric);
nw = New Window("Select Wanted Specifications", << Modal, << return result,
clb = Col List Box (<< Set Items (ListNumericCols))
);
ListSpecNames = nw["clb"];
show(ListSpecNames);
//insert spec names into associative array
for (i=1,i< (N Items(ListSpecNames) + 1), i++,
Insert Into(specs, ListSpecNames[i]);
ColSpec = Column(LimitsTable, 1); //1 is the coolumn for spec name
LimitList= {};
//Insert Lower Limit onto
for(j=1, j < (nrows(LimitsTable)+1), j++,
if (ColSpec[j] == ListSpecNames[i],
ColLimit = Column(LimitsTable, 2);//2 is the column for lower limit
MinVal = 0;
if(ColLimit[j] > 0, MinVal = ColLimit[j] / 2, MinVal = ColLimit[j]*2);
InsertInto(LimitList, MinVal );
break();
));
for(k=1, k < (nrows(LimitsTable)+1), k++,
if (ColSpec[k] == ListSpecNames[i],
ColLimit = Column(LimitsTable, 2);//2 is the column for lower limit
InsertInto(LimitList, ColLimit[k]);
break();
));
for(l=1, l < (nrows(LimitsTable)+1), l++,
if (ColSpec[l] == ListSpecNames[i],
ColLimit = Column(LimitsTable, 3);//3 is the column for lower limit
InsertInto(LimitList, ColLimit[l]);
break();
));
for(m = 1, m < (nrows(LimitsTable)+1), m++,
if (ColSpec[m] == ListSpecNames[i],
ColLimit = Column(LimitsTable, 3);//3 is the column for upper limit
MaxVal = 0;
if(ColLimit[m] > 0, MaxVal = ColLimit[m] *2, MaxVal = ColLimit[m] /2 );
InsertInto(LimitList, MaxVal );
break();
)
);
show (LimitList);
specs[ListSpecNames[i]] = LimitList
);
//show(specs); for debugging and making sure specs array is being populated
//sel_specs = Associative Array(ListSpecNames);
//specs << Intersect(sel_specs);
//*******************************************************************
//Create Pass Fail column if not existing.
if(!contains(GraphingTable << Get Column Names("String"), "Pass/Fail"),
GraphingTable << new column("Pass/Fail", Character);
);
//using a string to insert a formula into the row that can be called upon dynamically
f = "If(All(";
For Each({{spec, limits}}, specs,
f ||= Eval Insert("^limits[2]^ < :^spec^ < ^limits[3]^ & ");
);
//drop last &
f = Left(f, Length(f) - 3);
f ||= "),"; // close all
f ||= "\!N\!t\!"PASS\!",\!"FAIL\!"
)";
Eval(EvalExpr(Column(GraphingTable, "Pass/Fail") << Set Formula(
Expr(Parse(f));
)));
nw2 = New Window("test", testlist = H List Box(
ValuesOutlineBox = Outline Box("Values", SliderList = V List Box()),
Graphing Table << Pareto Plot(Cause(:"Pass/Fail"n))
));
filler = {};
For Each({{spec_name, spec_list, idx}}, specs,
new_control = H List Box(
Text Box(spec_name),
Range Slider Box(spec_list[1], spec_list[4] , spec_list[2], spec_list[3], << Set Function(function({this},
(this << Sib) << Set(this << get, run Script(1));
))) ,
Number Edit Box(spec_list[2], << Set Minimum(spec_list[1]), << Set Maximum(spec_list[4]), << Set Function(function({this},
(this << Prev Sib) << Set(this << get);
specs[((this << parent) << child) << get text][2] = this << get;
Column(GraphingTable, "Pass/Fail") << Eval Formula;
))),
Number Edit Box(spec_list[3], << Set Minimum(spec_list[1]), << Set Maximum(spec_list[4]), << Set Function(function({this},
(this << Prev Sib) << Set(this << get);
specs[((this << parent) << child) << get text][3] = this << get;
Column(GraphingTable, "Pass/Fail") << Eval Formula;
)))
);
SliderList << Append(new_control);
);
Re: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columna¡Muchas gracias! Esta es mi segunda semana escribiendo scripts en JSL y no tienes idea de cuánto me ayudaste.
Re: Creación de un diagrama de Pareto interactivo con cuadros deslizantes interactivos para actualizar la fórmula de la columnaEl código está bastante modificado y no estoy 100% seguro de qué tan confiable será, pero usaría la función set y child/sib/parent para obtener las referencias correctas relacionadas con los cuadros deslizantes. También Pareto parece actualizarse cuando se actualiza el valor de la fórmula. Esto podría beneficiarse de algún uso de Eval(EvalExpr())
Names Default To Here(1);
specs = Associative Array();
specs["m1"] = {0, 0.5, 1};
specs["m2"] = {0, 0.5, 1};
specs["m3"] = {0, 0, 1};
specs["thickness"] = {0, 4, 20};
GraphingTable = Current Data Table();
Column(GraphingTable, "Pass/Fail") << Set Formula(
If((:thickness >= specs["thickness"][2] & :m3 >= specs["m3"][2] & m2 >= specs["m2"][2] & m1 >= specs["m1"][2]),
"Pass",
"Fail"
)
);
nw = New Window("test", testlist = H List Box(
ValuesOutlineBox = Outline Box("Values", SliderList = V List Box()),
Graphing Table << Pareto Plot(Cause(:"Pass/Fail"n))
));
filler = {};
For Each({{spec_name, spec_list, idx}}, specs,
new_control = H List Box(
Text Box(spec_name),
Slider Box(spec_list[1], spec_list[3], 0, << Set Function(function({this},
(this << Sib) << Set(this << get, run Script(1));
))),
Number Edit Box(spec_list[2], << Set Minimum(spec_list[1]), << Set Maximum(spec_list[3]), << Set Function(function({this},
(this << Prev Sib) << Set(this << get);
specs[((this << parent) << child) << get text][2] = this << get;
Column(GraphingTable, "Pass/Fail") << Eval Formula;
)));
);
SliderList << Append(new_control);
);
En su código, parece que podría estar perdiendo ^ en torno a las pruebas para obtener valores en la matriz asociativa límite actualizada.