一种问题从一个和一个关于列公式开始这篇文章。 如果只使用公式编辑器创建列公式,几乎可以忽略所有这些。 这篇文章是关于使用 JSL 创建列公式的。
首先,简单介绍一下公式命令。 这是一个非常简单的:
The formula for column C adds columns A and BThe formula for column C adds columns A and BThe formula for column C adds columns A and BThe formula for column C adds columns A and BC 列的公式将 A 列和 B 列相加
表格脚本(左上三角->复制表格脚本,粘贴到编辑器中)如下所示:
New Table( "abc", Add Rows( 2 ),
New Column( "a", Numeric, "Continuous",Format( "Best", 12 ),Set Values( [1, 7] )),
New Column( "b",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [2, 9] )),
New Column( "c", Numeric, "Continuous", Format( "Best", 12 ),
Formula( :a + :p</img> )
)
)
第 5 行设置公式;该公式是一个添加列 a 和 b 的表达式。 表达式直到很晚才运行。 表达式作为表达式保存为列的一部分。 如果向表中添加了另一行或者如果列 a 或 b 中的值发生更改,则可以再次计算表达式以获得列 c 的值。
这是既友好又不寻常的行为。 不寻常,因为大多数函数都会计算它们的参数:sqrt( 4 + 5 ) 返回 3。 友好,因为您几乎不希望 JMP 在将公式分配给列之前对其求值。
有时公式表达式可能真的很复杂。 如此复杂,编写一个程序来编写表达式会更容易。 要在公式命令中执行此操作,您需要一种方法来告诉公式命令预先计算参数并将结果表达式用作公式。 为此,您可以在要预评估的代码周围添加一个 eval() 包装器。 当公式命令看到“eval”环绕表达式时,它会运行代码并使用结果。
lookup = function({t,u}, expr(a+b) );
New Table( "abc",
Add Rows( 2 ),
New Column( "a",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [1, 7] )),
New Column( "b",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [2, 9] )),
New Column( "c", Numeric, "Continuous", Format( "Best", 12 ),
Formula( eval( lookup(1,2) ) )
)
)
用户定义的“查找”函数(第 1 行)不是很清楚,但必须执行它以检索 expr(a+b) 作为返回值。 在第 7 行,eval() 包装器意味着列公式不会设置为“lookup(1,2)”,而是设置为 lookup(1,2) 返回的表达式。与以前相同的表格,具有相同的列公式。
如果您希望将列公式设置为以 eval( ) 开头的表达式怎么办?公式命令如何做到这一点,因为以 eval() 开始意味着评估参数并使用结果? (我很难想出一个有趣的例子,但是多发性硬化症问题的答案中有一个。)答案是 Name Expr( )。 Name Expr 是一个 JSL 函数,通常用于从 JSL 变量中获取表达式而不对其求值。 作为公式命令中最外层的包装器,它只返回参数而不对其求值。 第一个例子可以使用它,除了这个解释之外没有任何理由,就像这样,返回完全相同的表:
New Table( "abc", Add Rows( 2 ),
New Column( "a", Numeric, "Continuous",Format( "Best", 12 ),Set Values( [1, 7] )),
New Column( "b",Numeric,"Continuous",Format( "Best", 12 ),Set Values( [2, 9] )),
New Column( "c", Numeric, "Continuous", Format( "Best", 12 ),
Formula( Name Expr( :a + :p</img> ) )
)
)
但对于多发性硬化症例如,它是需要的,因为 eval 的巧妙使用(可能需要另一篇博文来解释它的作用)。 这是原始问题的最终表。 我将自己的想法添加为第二个公式列。
New Table( "final?",Add Rows( 9 ),
New Column( "color",Character,"Nominal",
Set Values({"green", "green", "blue", "yellow", "red", "red", "yellow", "green", "green"})),
New Column( "count",Numeric,"Continuous",Format( "Best", 12 ),
Formula( Name Expr( Eval( Eval Expr( Col Sum( Row() <= Expr( Row() ), :color ) ) ) ) )),
New Column( "another count",Numeric,"Continuous",Format( "Best", 12 ),
Formula(
n = 0;
For( i = 1, i <= Row(), i++,
If( :color == :color[i], n++ )
);
n;
)
)
);
第三列的公式可以更快,但要以清晰度为代价,方法是让它向后查找最后一场比赛并在该计数上加一。 清晰度与效率是一种权衡。

因此,我要修复在此过程中发现的错误:当数据表创建脚本来重现自身时(如上面的示例),它也必须生成 JSL 来重现列公式。 如果列公式以特殊的 eval( ) 包装器开头,并且 eval 应该是公式的一部分,则 JMP 需要添加 Name Expr。
2018 年 4 月 21 日更新:修复上一篇博客的自动转换。