使用 JSL 动态设置列公式I'm working on a JSL script where I need to dynamically build a formula for a given column inside a loop. The idea is to reference a different column for each iteration, so that the formula uses the evaluated column name (e.g., :col_name) rather than inserting the literal code.
这是我在循环中尝试实现的简化版本(我在此代码中尝试了 Expr、Eval、Parse 的多种变体,但都无济于事):
all_cols = dt << Get Column Names();
col = Column(all_cols[N Items(all_cols)-1]); // Changes for every i in the loop
// Dynamically build the formula expression using column names directly
formula = If(
col > :UL_outliers | col < :LL_outliers,
1,
0
);
outlier_col << Set Formula(formula);The problem is that when I set the formula using Set Formula(), instead of dynamically evaluating the column reference, the formula is inserted literally into the column's formula editor. As a result, the column formula is not evaluated and is simply:
If(
col > :UL_outliers | col < :LL_outliers,
1,
0
);我读过动态创建公式不评估和其他一些相关文章,但我的思绪已经崩溃。我只希望我的离群值列中有一些 1 或 0。
任何帮助或解决方法都将不胜感激。提前致谢!
自动化和脚本回复:使用 JSL 动态设置列公式不能 100% 确定你想做什么,但这可能会给你一些想法
Names Default To Here(1);
dt = open("$SAMPLE_DATA/Big Class.jmp");
dt << new column("LL_outliers", Numeric, Continuous, Set Each Value(50));
dt << new column("UL_outliers", Numeric, Continuous, Set Each Value(70));
all_cols = dt << Get Column Names("Continuous", "String");
colname = all_cols[1];
f_expr = Substitute(
Expr(If(_col_ > :UL_outliers | _col_ < :LL_outliers,
1,
0
)),
Expr(_col_), Name Expr(AsColumn(dt, colname));
);
new_col = dt << New Column("F", Numeric, Nominal);
Eval(EvalExpr(
new_col << Set Formula(Expr(NameExpr(f_expr)));
));回复:使用 JSL 动态设置列公式JMP 具有字符串数据类型:
a = “猫”;
b =“3 + 5”;
a 和 b 是字符串。B 看起来像表达式,但实际上不是。
c = 解析(b);
c 是一个表达式,它可以表示为一棵树:
operator(+)
/ \
3 5
c = expr( 3 + 5 ); // 是获取存储在 c 中的相同表达式的另一种方法
d = eval( c ); // 或者只是 d = c; 无论如何都会对右侧进行求值
d 是 8。
有时 JMP 会自动将 c 求值为 8,有时则不会。有时您想要 8,有时您想要 3+5。
e = 名称表达式(c);
e 获取 c 持有的表达式;将 nameexpr 视为一个薄包装器;当对包装器进行求值时,它会阻止更深层次的求值并返回未求值的 3 + 5 表达式,而不是 8。
JMP 还有一组用于操作表达式树的函数,这里不作介绍。例如, @jthi使用替代。
我认为您感到困惑的部分是 JSL 中不同函数处理表达式参数的方式之间的差异:
cos(c) 与大多数函数一样,将计算 c 为 8。这正是您所期望的。
列名< 逐字复制表达式 (c, 不是 3+5, 不是 8 )8)到列公式而不对其进行求值。(就像对 <
因此 setformula 有两种特殊情况:
列名< c (不特殊)
列名< 8(评估包装器)
列名< 3+5(nameexpr 包装器)
请注意,这些确实是特殊情况;setformula 会额外努力检测 eval 或 nameexpr 包装器,以使 JSL 按照您的期望执行。
现在我快完成了,我希望我使用 x+y 而不是 3+8 来完成这部分工作;这样会更清楚为什么你可能想要将评估推迟到稍后的时间点。此外,即使是像 8 这样的单个数字也是一个表达式;eval(8) 就是 8。
回复:使用 JSL 动态设置列公式感谢您的解释令人费解,但很有教育意义。我想我至少从概念上理解了它。
我想我会找到答案的。
多谢 !:)