Intento crear bucles anidados:
El primer bucle crea algunas columnas y tiene una fórmula.
El segundo ciclo crea algunas otras columnas y la fórmula necesitará columnas del primer ciclo.
Mi pregunta está en el segundo ciclo, no puedo configurar correctamente los nombres de las columnas en la fórmula usando eval() + substitue() + expr()
Names Default To Here( 1 );
dt = current data table();
a=3;
b=3;
alist = {1,2,3};
blist = {1,2,3};
// In actual script, above numbers will come from H list box input
For (i=1, i <= a, i++,
dt << New Column( eval("a_" || char(alist[i])), Formula(:gap*2) );
col = "a_" || char(alist[i]);
For (k=1, k <= b, k++,
eval(
substitute(
Expr(
dt << New Column( eval("a_" || char(alist[i]) || " b_" || char(blist[k])), Formula( If(:vvv > 0 & (:vvv < blist[k] ),1,0) ) );
),
Expr(vvv),
col //here gives wrong result, the formula doesn't really use column a_1, a_2, a_3, instead it use "a_1"......etc
)
)
)
)
Esto podría dar alguna idea
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
a = 3;
b = 3;
alist = {1, 2, 3};
blist = {1, 2, 3};
// In actual script, above numbers will come from H list box input
For(i = 1, i <= a, i++,
new_col = dt << New Column(Eval("a_" || Char(alist[i])), Formula(:height* 2));
For(k = 1, k <= b, k++,
Eval(Substitute(
Expr(dt << New Column("a_" || char(new_col << get name) || " b_" || char(blist[k]),
Formula(If(vvv > 0 & (vvv < www), 1, 0))
)),
Expr(vvv), Name Expr(AsColumn(new_col)),
Expr(www), blist[k]
)
)
);
);
Editar:
Si tiene JMP16+, puede cambiar los bucles a For Each (esto también usa Eval(EvalExpr()) en lugar de Eval(Substitute()) ya que en mi opinión es más claro en casos simples como este.
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
alist = {1, 2, 3};
blist = {1, 2, 3};
For Each({aval}, alist,
new_col = dt << New Column("a_" || Char(aval), Formula(:height * 2));
For Each({bval}, blist,
col_title = "a_" || Char(new_col << get name) || " b_" || Char(bval);
Eval(EvalExpr(
dt << New Column(col_title, Numeric, Nominal, Formula(
If(0 < Expr(Name Expr(As Column(dt, new_col))) < Expr(bval),
1
,
0
)
))
));
);
);
Esto resolvió mi pregunta, gracias. Y el segundo método parece aún más claro.
Una pregunta más, yo uso blist[k] directamente en mi código y tú usas "www" y luego lo reemplazas. Ambos dan el mismo resultado calculado.
¿Es porque mi método dejará una variable blist[k] en la fórmula que puede salir mal si el usuario intenta aplicar la fórmula nuevamente después de que se haya ejecutado el código?
Respuesta corta:
Sí. Si pierde la referencia a blist o k, la fórmula no puede volver a evaluarse. Y si las fórmulas se reevalúan mientras todavía tienes acceso a ambas, mismo k se utilizará para todas aquellas fórmulas que producirían respuestas incorrectas. Deberías poder probar esto ejecutando dt << Volver a ejecutar fórmulas;
Ver más...
Respuesta larga:
Sí, si no los evalúa, dejará blist[k] en su tabla de datos. Este sería entonces el último valor k que tiene en todas las fórmulas (problema si las fórmulas se reevalúan mientras aún se tiene acceso a blist y k) y si la tabla se vuelve a abrir (o por alguna razón pierde el acceso a blist/k) esos no existirán en absoluto. Este tipo de casos generalmente se pueden verificar fácilmente verificando la fórmula


Otro lugar donde esto puede suceder fácilmente son los scripts gráficos y puedes verlos de manera similar desde la ventana del script gráfico.</CODE></P>
<P> </P>
<PRE><CODE class=" language-jsl">Names Default To Here(1);
dt = open("$SAMPLE_DATA/Big Class.jmp");
gb = dt << Graph Builder(
Variables(X(:weight), Y(:height), Overlay(:sex)),
Elements(Points(X, Y, Legend(9)), Line Of Fit(X, Y, Legend(11)))
);
line = 60;
framebox = Report(gb)[frame box(1)];
framebox << Add Graphics Script(
H Line(line)
);
line = 70;
framebox << Add Graphics Script(
H Line(line)
);
Tendrás dos scripts como este.

y no habrá línea en Y = 60. Además, si copia el script del generador de gráficos, tendrá una línea allí en lugar de valores.
Graph Builder(
Variables(X(:weight), Y(:height), Overlay(:sex)),
Elements(Points(X, Y, Legend(9)), Line Of Fit(X, Y, Legend(11))),
SendToReport(
Dispatch(
{},
"Graph Builder",
FrameBox,
{Add Graphics Script(9, Description(""), H Line(line)),
Add Graphics Script(10, Description(""), H Line(line))}
)
)
)
y una solución fácil para esto es evaluar los valores
Names Default To Here(1);
dt = open("$SAMPLE_DATA/Big Class.jmp");
gb = dt << Graph Builder(
Variables(X(:weight), Y(:height), Overlay(:sex)),
Elements(Points(X, Y, Legend(9)), Line Of Fit(X, Y, Legend(11)))
);
line = 60;
framebox = Report(gb)[frame box(1)];
Eval(EvalExpr(
framebox << Add Graphics Script(
H Line(Expr(line))
);
));
line = 70;
Eval(EvalExpr(
framebox << Add Graphics Script(
H Line(Expr(line))
);
));
En términos más generales, diría que si comienza a reemplazar nombres de variables evaluándolos en valores, a veces podría ser una buena idea evaluarlos todos. Lo que quiero decir con esto en este caso es que podría ser beneficioso evaluar también el título de la columna.
Eval(EvalExpr(
dt << New Column(Expr(col_title), Numeric, Nominal, Formula(
If(0 < Expr(Name Expr(As Column(dt, new_col))) < Expr(bval),
1
,
0
)
))
));
);
Esto tiene, por ejemplo, un beneficio adicional cuando depura su código. A continuación se muestra un ejemplo simple de cómo crear una columna a partir de una referencia y con una variable que funciona bien
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
new_col = dt << New Column("Test", Numeric, Continuous, << Set Each Value(1));
col_title = (new_col << get name) || "* var";
var = 2;
Eval(EvalExpr(
dt << New Column(col_title, Numeric, Nominal, Formula(
Expr(NameExpr(AsColumn(dt, new_col))) * Expr(var)
));
));
pero si tuviera algunos problemas, podría simplemente resaltar EvalExpr() y todo lo que contiene y ejecutar esa parte del script.

col_title no se evalúa (no es un problema en este caso, PERO podría estarlo si tuviera un script más complicado) y simplemente agregando (en este caso) una Expr() más obtendrá más información sobre lo que realmente está sucediendo.
