La secuencia de comandos funciona en el editor de secuencias de comandos, pero no en el elemento del menú (Obtener nombres de columnas que no se comportan de la misma manera)Cuando ejecuto el siguiente script desde el editor de scripts, funciona bien.Pero cuando lo ejecuto desde un elemento de menú personalizado que creé en Ver->Personalizar, no funciona.Lo rastreé hasta que la función Obtener nombres de columna no se comporta de la misma manera.Cuando coloco una declaración de impresión para generar el valor de cada nombre de columna y su Tipo antes de usar Obtener propiedad en él, veo esto (por ejemplo) cuando se ejecuta desde el editor de secuencias de comandos:
:ejec_tipo
"Nombre"
SIN EMBARGO, cuando lo ejecuto desde mi elemento de menú, obtengo esto:
tipo_ejecutivo
"Nombre"
Note la falta del colon.(Lo que sea que haga el colon, no lo sé.)
En última instancia, la secuencia de comandos falla porque cuando intento ejecutar la función Obtener propiedad en la columna llamada exec_typ, JMP no la reconoce como un nombre de columna o algo así:
Send Expects Scriptable Object{7} en acceso o evaluación de 'Send', colNames[colInd] << /*###*/Get Property( "Spec limits") /*###*/
¿Alguna idea de qué diablos está pasando?¿Por qué la función Obtener nombres de columnas se comporta de manera diferente si se llama desde el editor de secuencias de comandos en lugar de hacerlo desde un acceso directo del menú?
Código a continuación.Sí, algo de eso es desordenado.
//Reports all failing tests for a unit. Not temperature-smart (yet!)
dt = Current Data Table();
colNames = dt << get column names(Numeric);
//I need to clean up the add columns scripts... once I understand how it works.
dt << add multiple columns(
"Num Tests Failing",
1,
After( "20:Neg_Contact:Cont_int2[1]" ),
numeric( 10 )
);
colf = Column( "Num Tests Failing" );
colf << Modeling Type ( Nominal );
dt << add multiple columns(
"Failing Tests",
1,
After( "20:Neg_Contact:Cont_int2[1]" ),
numeric( 10 )
);
colf = Column( "Failing Tests" );
colf << Data type( Character );
For (i = 1, i <= N Rows(dt), i++,
Row() = i;
failingTests = "";
NumOfFailingTests = 0;
If (:Name("HBIN_NAM") != "Good" & :Name("HBIN_NAM") != "1:Good" , //It's a fail
//Efficiency could be improved by extracting all spec limits first.
For (colInd = 1, colInd <= N Items(colNames), colInd++,
//print statements for debugging.
print(colNames[colInd]);
print(Type(colNames[colInd]));
//THIS IS WHERE IT KEEPS CRASHING
specLimits = colNames[colInd] << Get Property ("Spec limits");
LSL_Char = Char(specLimits[1]);
USL_Char = Char(specLimits[2]);
LSL_Char = SubStr(LSL_Char, 5, (Length(LSL_Char) - 5));
USL_Char = SubStr(USL_Char, 5, (Length(USL_Char) - 5));
LSL_Num = 0; //initializing value to set its scope; is this necessary? Donno.
USL_Num = 0;
If(LSL_Char == "." | LSL_Char == "",
LSL_Char = "NO LIMIT",
//else
LSL_Num = Num(LSL_Char);
);
If(USL_Char == "." | USL_Char == "",
USL_Char = "NO LIMIT",
//else
USL_Num = Num(USL_Char);
);
failedTest = 0;
If(LSL_Char != "NO LIMIT",
If( colNames[colInd][i] < LSL_Num,
failedTest = 1;
NumOfFailingTests = NumOfFailingTests + 1;
);
);
If(USL_Char != "NO LIMIT",
If( colNames[colInd][i] > USL_Num,
failedTest = 1;
NumOfFailingTests = NumOfFailingTests + 1;
);
);
If(failedTest == 1,
failingTests = failingTests || Char(colNames[colInd]) || "; ";
);
);
);
:Name( "Failing Tests" )[i] = failingTests;
:Name( "Num Tests Failing" )[i] = NumOfFailingTests;
);
Re: La secuencia de comandos funciona en el editor de secuencias de comandos, pero no en el elemento del menú (Obtener nombres de columnas que no se comportan de la misma manera)1. Para que el código se muestre como JSL, debe usar la herramienta en la parte superior de la ventana de entrada para ingresar su texto.
2. La razón principal por la que creo que mi código funcionará más rápido que su método se basa en 2 elementos.
a. Sí, las fórmulas están optimizadas.
b. El uso de dt << Select Where junto con la posibilidad de asignar a todas las filas seleccionadas a la vez es extremadamente rápido.Recorrer una tabla de datos con todas las declaraciones "IF" que tiene su código es muy lento.
3. Con respecto a los valores límite de especificación de su carácter.¿Cómo está asignando los límites de especificación?La propiedad de la columna Límites de especificación solo debe permitir valores numéricos.Si está accediendo a la lista de Límites de especificaciones usando funciones de caracteres como Substr(), obtendrá cadenas de caracteres.Eche un vistazo a la Guía de secuencias de comandos sobre cómo manipular las listas JSL
Re: La secuencia de comandos funciona en el editor de secuencias de comandos, pero no en el elemento del menú (Obtener nombres de columnas que no se comportan de la misma manera)¡Gracias por el guión Jim! Tiene razón, no tengo idea de cómo funciona el alcance de la variable en el script JMP, excepto que he visto alguna evidencia que sugiere que las variables declaradas son variables locales por defecto.
¿Cómo conseguiste que tu script se mostrara correctamente en estos foros?Cuando pego código en la ventana de código de estos foros, se arruina el formato y se eliminan todas las tabulaciones y la sangría de espacios en blanco.¡Qué bueno que no estamos tratando de compartir el código de Python!
De todos modos, estoy adaptando mi script para usar elementos tuyos, y finalmente ya está funcionando.Intenté usar su secuencia de comandos directamente con dt = tabla de datos actual (); y otra edición o dos, pero no funcionó.Sé que mi secuencia de comandos es ineficiente, pero, por ejemplo, todos mis intentos de convertir la USL y la LSL en números fallaron, así que tuve que convertirla en una cadena y usar una subcadena.Sin embargo, si hago el ajuste que anoto en los comentarios para extraer todos los límites de especificaciones solo una vez, eso no importará demasiado.¡Incluso es útil ver un ejemplo de archivo abierto, porque lo que realmente me gustaría hacer es tener la opción de extraer límites de prueba de archivos diferentes al que estoy analizando!
Lo que es extraño para mí es su implicación (porque dijo que su secuencia de comandos era más rápida) de que agregar columnas y eliminarlas sería más eficiente que dos bucles For anidados.La computadora todavía tiene que analizar todas y cada una de las celdas de su tabla de datos.¿JMP está optimizado de tal manera que establecer y ejecutar fórmulas sea más eficiente?No puedo hacer que su enfoque funcione realmente para tratar de averiguarlo, tal vez debería intentar lo que sugiere el posador de seguimiento.
Por cierto, mis tablas de datos tienen algo así como 600 columnas y pueden tener decenas de miles de filas, por lo que es posible que deba tener en cuenta las consideraciones de eficiencia de ejecución.
De todos modos, el cambio mínimo que necesitaba hacer para que mi script funcionara era reemplazar todos los
colNames[colInd]
con
Columna( dt, colNames[colInd] ) .
Aunque no puedo hacer que funcione con mis archivos de datos, intentaré adaptar algunos elementos más de su secuencia de comandos.
Re: La secuencia de comandos funciona en el editor de secuencias de comandos, pero no en el elemento del menú (Obtener nombres de columnas que no se comportan de la misma manera)Jim,
Buen trabajo.necesitaba agregar
dt << Run Formulas;
después de Eval (Parse (theExpr)) y antes de la declaración de fórmula de eliminación, en dos lugares de su script bien escrito.
Re: La secuencia de comandos funciona en el editor de secuencias de comandos, pero no en el elemento del menú (Obtener nombres de columnas que no se comportan de la misma manera)Mi suposición es que, dado que no está analizando específicamente sus variables (:), se encuentra con problemas al intentar ejecutar en los 2 entornos diferentes.El otro elemento que observé es que su método resultará en un código muy lento.Dado eso, he reescrito su secuencia de comandos, utilizando algunos métodos que creo que funcionarán en ambos entornos y también se ejecutarán mucho más rápido.El siguiente script se ejecuta en la tabla de datos de capacidad de semiconductores que se distribuye con JMP.Pero si simplemente elimina la referencia a la apertura de esa tabla, junto con la declaración que sigue a la apertura de la tabla de datos y los reemplaza con su
dt = tabla de datos actual();
el código debería funcionar en sus datos.
He anotado el código a continuación, así que creo que debería poder seguirlo.Además, RECOMIENDO ENCARECIDAMENTE que lea la Guía de secuencias de comandos distribuida con su instalación de JMP.
Ayuda==>Libros==>Guía de secuencias de comandos
Te dirá todo sobre lo que son esos dos puntos locos.
Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/semiconductor capability.jmp" );
dt << delete columns( {2, 3, 4} );
// Get the numeric column names as strings
colNames = dt << get column names( Numeric, string );
// Create the new calculated columns
// They will be populated later
dt << New Column( "Num Tests Failing", numeric );
dt << New Column( "Failing Tests", character );
// Create a new column for each column in the colNames list
// and populate the colNames name, if it does NOT pass
For( i = 1, i <= N Items( colNames ), i++,
// Create the new colum
dt << New Column( "PassFail " || Char( i ), character );
// Get the Spec Limits for the first column
specLimits = Column( dt, colNames[i] ) << get property( "Spec Limits" );
// If no Spec Limits are found, do not process
If( Is Empty( specLimits ) == 0,
// Get the USL and LSL and if not present set to missing
LSL = Try( specLimits["LSL"], . );
USL = Try( specLimits["USL"], . );
// If the LSL is not missing process
If( Is Missing( LSL ) == 0,
// Find all rows where the colNames column is less than
// the LSL
dt << select where( As Column( dt, colNames[i] ) < LSL );
// If any rows are selected, then process
If( N Rows( dt << get selected rows ) > 0,
// Set the value in the PassFail column to the name of
// the colNames being processed. This will allow for
// the counting and the concatenating for the new
// calculation columns
Column( dt, "PassFail " || Char( i ) )[dt << get selected rows] = colNames[i]
|| "; "
);
);
// See above comments for LSL
If( Is Missing( USL ) == 0,
dt << select where( As Column( dt, colNames[i] ) > USL );
If( N Rows( dt << get selected rows ) > 0,
Column( dt, "PassFail " || Char( i ) )[dt << get selected rows] = colNames[i]
|| "; "
);
);
);
);
// Clean up and selected columns
dt << clear select;
// Create the command string required for the formula for the
// Failing Tests, which is a concatenated string of all of the
// PassFail columns.
theExpr = "dt:Failing Tests << set formula(Concat(:PassFail 1";
For( i = 2, i <= N Items( colNames ), i++,
theExpr = theExpr || ",:PassFail " || Char( i )
);
theExpr = theExpr || "))";
// Execute the command string
Eval( Parse( theExpr ) );
// Delete the formula, which will remove the formula, but not
// the calculated values
dt:Failing Tests << delete formula;
// Create the command string for the Num Tests Failing column
// The count is the sum of the "True" Boolean comparisions.
// That is, if PassFail 1 != "", it will be "True" and therefore
// will have the value of 1. If the cell is blank, it will have a
// value of 0. The sum of all of these comparisons will be equal to
// the number of non passing parameters(tests)
theExpr = "dt:Num Tests Failing << set formula(sum(:PassFail 1 != \!"\!"";
For( i = 2, i <= N Items( colNames ), i++,
theExpr = theExpr || ",:PassFail " || Char( I ) || " != \!"\!""
);
theExpr = theExpr || "));";
Eval( Parse( theExpr ) );
dt:Num Tests Failing << delete formula;
// Delete all of the PassFail columns, just to clean up the data table
dt << delete columns(index(n cols(dt)-N items(colNames)+1,ncols(dt)));