Encontré un problema cuando traté de crear dinámicamente columnas de fórmula. Logré resolverlo al final, pero me gustaría saber qué está pasando aquí. Mi conjetura es que de alguna manera está relacionado con la forma en que estoy creando la fórmula y que la "fórmula" se evalúa antes de que se establezca en la columna y luego de alguna manera estropea la fórmula de la columna.
Aquí hay un ejemplo: las columnas creadas por test1 y test2 tienen problemas y test3 funciona bien (test4 y test5 también parecen funcionar bien, pero no estoy seguro si me sentiría seguro al usarlos ya que no tengo idea de por qué se vuelven convertido en referencias de columna de cadenas)
Names Default To Here(1);
test1 = function({dt, val_col, by_cols}, {Default Local},
ref_list = Transform Each({col_name}, Insert(by_cols, val_col, 1),
Name Expr(As Column(dt, col_name));
);
new_col = Eval(Substitute(
Expr(dt << New Column("Formula", Numeric, Continuous,
Formula(_new_formula_)
)),
Expr(_new_formula_), Substitute(ref_list, Expr(list), Expr(Col Median))
));
return(new_col);
);
test2 = function({dt, val_col, by_cols}, {Default Local},
ref_list = Transform Each({col_name}, Insert(by_cols, val_col, 1),
Name Expr(As Column(dt, col_name));
);
new_formula = Substitute(ref_list, Expr(list), Expr(Col Median));
new_col = Eval(Substitute(
Expr(dt << New Column("Formula", Numeric, Continuous,
Formula(_new_formula_)
)),
Expr(_new_formula_), Name Expr(new_formula)
));
return(new_col);
);
test3 = function({dt, val_col, by_cols}, {Default Local},
ref_list = Transform Each({col_name}, Insert(by_cols, val_col, 1),
Name Expr(As Column(dt, col_name));
);
new_formula = Char(Substitute(ref_list, Expr(list), Expr(Col Median)));
new_col = Eval(Substitute(
Expr(dt << New Column("Formula", Numeric, Continuous,
Formula(_new_formula_)
)),
Expr(_new_formula_), Parse(new_formula)
));
return(new_col);
);
test4 = function({dt, val_col, by_cols}, {Default Local},
new_col = Eval(Substitute(
Expr(dt << New Column("Formula", Numeric, Continuous,
Formula(Col Median(_new_formula_))
)),
Expr(_new_formula_), Insert(by_cols, val_col, 1)
));
return(new_col);
);
test5 = function({dt, val_col, by_cols}, {Default Local},
new_col = Eval(Substitute(
Expr(dt << New Column("Formula", Numeric, Continuous,
Formula(_new_formula_)
)),
Expr(_new_formula_), Substitute(Insert(by_cols, val_col, 1), Expr(List), Expr(Col Median))
));
return(new_col);
);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
by_cols = {"age", "sex"};
val_col = "height";
col1 = test1(dt, val_col, by_cols);
col2 = test2(dt, val_col, by_cols);
col3 = test3(dt, val_col, by_cols);
col4 = test3(dt, val_col, by_cols);
col5 = test3(dt, val_col, by_cols);
Show(col1 << get formula);
Show(col2 << get formula);
Show(col3 << get formula);
Show(col4 << get formula);
Show(col5 << get formula);
//dt1 = dt << Subset(All Rows, Selected columns(0), Suppress formula evaluation(0));
//Close(dt, no save);
Si, por ejemplo, abro el editor de fórmulas de Fórmula 2 y presiono aplicar, podría obtener un error

¿Hay alguna forma de recuperarse de las fórmulas "rotas" y existe la posibilidad de ver que se romperá durante la creación? Puedo usar Parse(Char()) para obtener una fórmula que funcione y también puedo crear un subconjunto de los datos y las fórmulas funcionarán allí.
Probado con JMP Pro 16.2.0 en Windows 10.
tratar
Expr(Col Median())
con el extra ().
El analizador ve los paréntesis y establece el función marca en el nodo en el árbol de expresión. Sin padres, el Col mediana node es solo un nombre que tiene hijos que no se usarán (excepto por conversión arg() y char()). En tiempo de ejecución, el nombre no está en el espacio de nombres de las variables, y el espacio de nombres de las funciones integradas no se usará, por lo tanto, el mensaje.
Creo que esta explicación es consistente con el comportamiento de las 5 pruebas.
Fórmula (...) es diferente de ColMedian(...); ColMedian es una función JSL. Fórmula es una palabra clave que reconoce el mensaje NewColumn. El manejo de palabras clave espera niños, por lo que es posible que no necesite expr (Fórmula ()), pero probablemente funcione bien con él.
editar: estoy bastante seguro de que el función la bandera no está expuesta en JSL a través de arg(), etc.