一個問題從aandw關於列公式開始這篇文章。 如果您只使用公式編輯器創建列公式,您幾乎可以忽略所有這些。 這篇文章是關於使用 JSL 創建列公式的。
首先,稍微介紹一下公式命令。 這是一個非常簡單的:
The 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 日更新:修復上一篇博客的自動轉換。