Programación en JSL para la asignación dinámica de columnas en el generador de gráficos.Estoy intentando crear un script de sesión para generar gráficos usando el Generador de gráficos de JMP. Sin embargo, surge un problema porque el número de columnas en mis datos varía según el período cada vez que se actualizan, lo que requiere modificar manualmente el script del Generador de gráficos para cada actualización.
To address this, I am considering a method where column names are prefixed (e.g., A_, B_, C_). This would allow me to dynamically assign columns: for instance, columns prefixed with A_ could be directed to the Local Data Filter, those with B_ to the Column Switcher, and so forth.
Me gustaría saber cómo implementar este enfoque en JSL (JMP Scripting Language), ya que no he logrado escribir un script efectivo. Mencionaste tener un borrador incompleto en JSL, pero no lo incluiste en tu pregunta. Si puedes proporcionarlo, con gusto te ayudaré a perfeccionarlo o te sugeriré una solución.
También me encuentro con el siguiente error.→[For Each , Bad Argument( colName ), For Each/*###*/(colName, columnNames,... El argumento debe ser una lista. ]
dt = Current Data Table();
A_list = {};
B_list = {};
columnNames = As List(dt << Get Column Names("String"));
For Each(colName, columnNames,<BR />
If(Contains(colName, "A_"),
Insert Into(A_list, colName)
);
If(Contains(colName, "B_"),
Insert Into(B_list, colName)
);
);
Graph Builder(
Variables(
X( :point ),
Y( :avg ),
Y( :stddev ),
Page( :category ),
Color(B_list[1])
),
Elements(
Position( 1, 1 ),
Points( X, Y( 1 ), Legend( 27 ) ),
Line( X, Y( 2 ), Y( 3 ), Color( 0 ), Legend( 29 ) )
),
Elements(
Position( 1, 2 ),
Points( X, Y( 1 ), Legend( 28 ) ),
Line( X, Y( 2 ), Y( 3 ), Color( 0 ), Legend( 31 ) )
),
Local Data Filter(
Conditional,
Add Filter(
columns( A_list ),
Display( A_list[1], N Items( 7 ), Find( Set Text( "" ) ) ),
Display( A_list[2], N Items( 7 ) ),
Display( :key, N Items( 12 ) )
)
),
Column Switcher(
:msr_dt,
B_list
)
);
Automatización y scriptingRe: Programación JSL para la asignación dinámica de columnas en el generador de gráficos¿Consideraste usar etiquetas de columna para "agrupar" las columnas?
Esto podría proporcionar una funcionalidad similar, e incluso permite la superposición de "grupos".
Algo como:
Names Default to Here(1);
dt = Open( "$SAMPLE_DATA/Big Class Families.jmp" );
dt:sex << setProperty( "Tags", {"pick"} );
dt:height << setProperty( "Tags", {"pick"} );
dt:weight << setProperty( "Tags", {"pick"} );
cols = dt << Get Tagged Columns( "pick" );
dt << Distribution( Column( Eval(cols) ));
Por cierto, es para cada ({col}, cols, body)
Re: Programación JSL para la asignación dinámica de columnas en el generador de gráficos
Gracias por tu respuesta, hogi.
No había considerado las etiquetas de columna. Intentaré revisar el script utilizando etiquetas de columna nuevamente.
Responderé después de hacerlo.
Re: Programación JSL para la asignación dinámica de columnas en el generador de gráficosDependiendo de su caso de uso, podría utilizar etiquetas como las ya sugeridas, propiedades de columna personalizadas, nombres de columna con prefijo, grupos de columnas, etc. Todas las opciones tienen sus propias ventajas y desventajas.
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
collist = dt << Get Column Names("String");
npn_cols = Filter Each({colname}, collist, Starts With(colname, "NPN"));
pnp_cols = Filter Each({colname}, collist, Starts With(colname, "PNP"));
gb = dt << Graph Builder(
Variables(X(:SITE), Y(:IVP1), Color(pnp_cols[1])),
Elements(
Position(1, 1),
Points(X, Y(1), Legend(27))
),
Elements(
Position(1, 2),
Points(X, Y(1), Legend(28)),
Line(X, Y(2), Y(3), Color(0), Legend(31))
)
);
filter_cols = npn_cols[1::2];
Insert Into(filter_cols, "SITE");
ldf = gb << Local Data Filter(
Conditional,
Add Filter(
columns(Eval(filter_cols)),
Display(filter_cols[1]),
Display(filter_cols[2]),
Display(filter_cols[3])
)
);
cw = gb << Column Switcher(pnp_cols[1], pnp_cols);
Además... ¿esto es una especie de híbrido entre una pregunta de la comunidad y una pregunta de LLM (somos humanos aquí en la comunidad, esperemos)?
Re: Programación JSL para la asignación dinámica de columnas en el generador de gráficosDisculpen que mi respuesta esté en japonés (pensé que así transmitiría mejor mis verdaderas intenciones).
Ahora estamos compartiendo con la comunidad casos en los que no se pudieron resolver las preguntas planteadas a JMP learnBot.
En definitiva, utilizo esta comunidad para mejorar mis propias habilidades de programación, aprendiendo sobre métodos de scripting y recibiendo consejos de personas con conocimientos en la materia, y también para contribuir al desarrollo de las habilidades de otros usuarios de JMP a mi alrededor.
Sin embargo, lo siento mucho, ya que me preocupa haber ofendido a jthi, quien siempre responde a mis preguntas con tanta amabilidad. Si hubo algo descortés o inapropiado en la forma en que formulé la pregunta, le agradecería que me lo hiciera saber para futuras ocasiones.
Re: Programación JSL para la asignación dinámica de columnas en el generador de gráficosTu publicación no me ofendió, sino que me resultó extraña, ya que parecía que nos estaban dando una pista. Si has usado alguna pista, te recomiendo que la separes.
LearnBot no funciona muy bien con JSL, ya que no se le indica cómo hacerlo. Assistant podría ser un poco mejor, pero podrías obtener mejores resultados si le indicas a LLM (como Claude, preferiblemente uno al que tu empresa tenga acceso) que entienda lo que debe hacer (JSL).
Re: Programación JSL para la asignación dinámica de columnas en el generador de gráficosComo señaló Jthi, no había hecho una distinción clara en mi mente entre las preguntas para LLM y las publicaciones en la comunidad de usuarios de JMP.
En el futuro, revisaré cuidadosamente el contenido para determinar si se trata de una pregunta para LLM o una publicación apropiada para la comunidad de usuarios de JMP. Gracias por señalar puntos importantes a tener en cuenta para una comunicación más fluida.
Espero contar con su continuo apoyo.
Re: Programación JSL para la asignación dinámica de columnas en el generador de gráficosSi buscabas cómo hacer funcionar el script, aquí tienes una versión actualizada que te puede servir de punto de partida. He comentado algunas secciones que he modificado; ten en cuenta que la más compleja consiste en insertar una lista de columnas en el filtro de datos local, lo que activa las funciones Eval( Eval Insert() ). Puedes consultar la sección «Insertar una expresión en otra usando Eval Insert, Eval Expr, Parse y Substitute» para ver diferentes opciones.
Names default to here(1);
Random reset(1);
msr_dt = New Table( "Example Data",
Add Rows( 200 ),
New Column( "A_1", Character, "Nominal", Formula( if(random uniform(1)<0.2,"",Substr( "ABC", floor(Random uniform( 4 )),1) ))),
New Column( "A_2", Character, "Nominal", Formula( if(random uniform(1)<0.2,"",Substr( "DEF", floor(Random uniform( 4 )),1) ))),
New Column( "B_1", Character, "Nominal", Formula( if(random uniform(1)<0.2,"",Substr( "GHI", floor(Random uniform( 4 )),1) ))),
New Column( "B_2", Character, "Nominal", Formula( if(random uniform(1)<0.2,"",Substr( "JKL", floor(Random uniform( 4 )),1) ))),
New Column( "point", Numeric, "Continuous", Format( "Best", 12 ), Formula( Row() ) ),
New Column( "avg", Numeric, "Continuous", Format( "Best", 12 ), Formula( Random Normal( 5 ) ) ),
New Column( "stddev", Numeric, "Continuous", Format( "Best", 12 ), Formula( Random Normal( 0.5 ) ) ),
New Column( "category", Character, "Nominal", Formula( Char( Floor( Row() / 101 ) ) ), Set Selected ),
New Column( "key", Character, "Nominal", Formula( Substr( "abcdefghijklmnopqrstufwxyz", floor(Random uniform( 27 )),1) )),
);
A_list = {};
B_list = {};
columnNames = As List(msr_dt << Get Column Names("String"));
For Each({colName},columnNames, // change here - note brackets
If(Contains(colName, "A_"),
Insert Into(A_list, colName)
);
If(Contains(colName, "B_"),
Insert Into(B_list, colName)
);
);
Eval(Eval expr(
Graph Builder(
Variables(
X( :point ),
Y( :avg ),
Y( :stddev ),
Page( :category ),
Color(B_list[1])
),
Show Control Panel( 0 ),
Elements(
Position( 1, 1 ),
Points( X, Y( 1 ), Legend( 27 ) ),
Line( X, Y( 2 ), Y( 3 ), Color( 0 ), Legend( 29 ) )
),
Elements(
Position( 1, 2 ),
Points( X, Y( 1 ), Legend( 28 ) ),
Line( X, Y( 2 ), Y( 3 ), Color( 0 ), Legend( 31 ) )
),
Local Data Filter(
Conditional,
Add Filter(
columns( Expr( A_list || {"key"} ) ), //this needs to be evaluated before the graph builder function is called
Display( A_list[1], N Items( 7 ) ), //removed the find term
Display( A_list[2], N Items( 7 ) ),
Display( :key, N Items( 12 ) )
)
),
Column Switcher(
B_list[1], // added reference to specific column here - was the data table
B_list
)
)
));
Re: Programación JSL para la asignación dinámica de columnas en el generador de gráficosSoy principiante en JSL, así que disculpen si esta pregunta ya se ha formulado y respondido anteriormente.
Lo que quiero hacer es modificar el script de Graph Builder anterior para graficar columnas IVP frente a columnas NPN con colores de columnas PNP. Adjunto el script modificado (Multiple Column Switcher.jsl), con tres conmutadores de columnas. Tengo que elegir manualmente las combinaciones de columnas IVP, NPN y PNP que deseo. Si sé que las columnas IVP, NPN y PNP se corresponden uno a uno (por ejemplo, IVP3 frente a NPN3 y PNP3), ¿cómo puedo usar un único conmutador de columnas para lograrlo?
Re: Programación JSL para la asignación dinámica de columnas en el generador de gráficosPresenté una versión simplificada de esto en mi presentación de consejos y trucos en Discovery Summit ( Salta, salta y usa JMP en un minuto: consejos prácticos de JMP de un superusuario (2026-EU-30MP-2767) , consejo "Conmutadores de columna para todos (Conmutadores de varias columnas)").
Esta es una forma bastante sencilla de hacerlo (tenga en cuenta que NPN tiene más columnas que el resto, por lo que en ese caso utilizará la columna incorrecta).
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
collist = dt << Get Column Names("String");
npn_cols = Filter Each({colname}, collist, Starts With(colname, "NPN"));
pnp_cols = Filter Each({colname}, collist, Starts With(colname, "PNP"));
ivp_cols = Filter Each({colname}, collist, Starts With(colname, "IVP"));
gb = dt << Graph Builder(
Variables(X(:NPN1), Y(:IVP1), Color(pnp_cols[1])),
Elements(
Position(1, 1),
Points(X, Y(1), Legend(27))
),
Elements(
Position(1, 2),
Points(X, Y(1), Legend(28)),
Line(X, Y(2), Y(3), Color(0), Legend(31))
)
);
cw1 = gb << Column Switcher(npn_cols[1], npn_cols);
cw2 = gb << Column Switcher(pnp_cols[1], pnp_cols);
cw3 = gb << Column Switcher(ivp_cols[1], ivp_cols);
Eval(EvalExpr(
post = Function({previousColumn, currentColumn, switcher},
c2 = Substitute((currentColumn << get name), "NPN", "PNP");
c3 = Substitute((currentColumn << get name), "NPN", "IVP");
Expr(cw2) << Set Current(c2);
Expr(cw3) << Set Current(c3);
);
));
handler = cw1 << Make Column Switch Handler(post);
// might want to hide other column switchers
cw_obs = (Report(gb) << Top Parent) << XPath("//ColumnSwitcherContextOutlineBox");
cws = cw_obs << Get Scriptable Object;
cw_obs[2] << Visibility("Collapse");
cw_obs[3] << Visibility("Collapse");
Write();
Las tablas de datos apiladas y los filtros de datos locales también pueden ser una buena opción para cosas como esta.