如何使用 JSL 基於隨機列建立平均值列我想根據一些選擇條件建立一個列清單。列名事先未知。然後,我使用該列清單建立公式列,計算這些列的平均值(或標準差或數量)。
一個簡單的範例腳本,它會讀取所有數值列:
dt = Open( "$SAMPLE_DATA/Cars.jmp" );
ColList = {};
For(i=1, i<=NCols(), i++,
If(Column(i)<
<GETDATATYPE></GETDATATYPE>
<BR /> <BR /> <P>請注意,ColList 是一個有效的欄位清單。當將其插入第一列公式時,公式編輯器中的預覽顯示計算結果正確,但該列仍然為空。顯然,我們需要在 Mean() 函數中插入標量、列表或矩陣(但預覽無論如何都會正常工作)。</P> <P><SPAN class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><span class="lia-inline-image-display-wrapper" image-alt="pauldeen_0-1788272598908.png" style="width: 400px;"><img src="https://us.v-cdn.net/6038925/uploads/images/115064i3C11FFA7C1D866DE/pauldeen_0-1788272598908.png" role="button" title="pauldeen_0-1788272598908.png" alt="pauldeen_0-1788272598908.png" /></span><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN><SPAN class="lia-inline-image-caption" onclick="event.preventDefault();">pauldeen_0-1788272598908.png</SPAN></SPAN></P> <P>第二個公式列在列引用周圍加入了 AsColumn() 函數……這有點違反直覺,因為它本身就是一列。但現在它會建立一個列表、標量或矩陣,而 mean() 公式就能正常運作了。</P> <P>感覺我把事情想得太複雜了。有沒有更簡單的方法來程式化地產生這樣的總計列?</P>
回覆:如何使用 JSL 基於隨機列建立平均值列通常對於像這樣的簡單情況,我會使用 Substitute 將清單替換為其他表達式。
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Cars.jmp");
collist = dt << Get Column Names("Numeric", "String");
colrefs = Transform Each({colname}, collist,
Name Expr(As Column(dt, colname))
);
mexpr = Substitute(colrefs, Expr(List), Expr(Mean));
Eval(EvalExpr(
dt << New Column("AVG", Numeric, Continuous, Formula(
Expr(Name Expr(mexpr))
));
));
Write();
回覆:如何使用 JSL 基於隨機列建立平均值列謝謝,但這仍然是針對簡單問題的進階解決方案。我仍然很想知道是否有人能找到更簡單的方法,將列引用添加到列公式中。
回覆:如何使用 JSL 基於隨機列建立平均值列假設我們在表 dt 中有一個名為「TEST」的欄位。 「基本」之間存在差異
- 列(dt, "TEST")
- AsColumn(dt, "TEST")
- “測試”
- 名稱表達式(作為列(dt, "TEST"))
看更多...
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Cars.jmp");
Row() = 0; // default row value
col = "Size";
Show(col);
Show(Column(dt, col));
Show(AsColumn(dt, col));
Show(Name Expr(AsColumn(dt, col)));
Show(dt:col);
Show(AsName(col));
Write("\!N\!N");
Row() = 1;
Show(Column(dt, col)[Row()]);
Show(AsColumn(dt, col));
Show(Name Expr(AsColumn(dt, col)));
Show(dt:col);
Show(AsName(col));
您在尋找哪種解決方案?除非您在公式中使用方括號 [] 或 [Row()],否則您無法直接在公式中新增列參考。如果您取得的列是引用(或字串),通常需要將其轉換為「列存取」才能在公式中使用。
回覆:如何使用 JSL 基於隨機列建立平均值列我向JMP提交了一份錯誤報告。
這個錯誤在於列公式不接受 `Column(“name”)` 參數,而是必須先用 `As Column()` 表達式包裹起來。在使用視覺化公式編輯器時,可以在參數欄位中拖放列,因此 JSL 也應該體現相同的行為。將此功能新增至 JSL 將大大簡化從 JSL 建立列公式的過程。
顯然,公式編輯器中的預覽視窗能夠正確解讀這一點,因為它會顯示預覽。
回覆:如何使用 JSL 基於隨機列建立平均值列Column() 和 AsColumn()/:colname 並不相同,不應該以類似的方式使用。
我認為問題出在公式編輯器上,以及它顯示使用 JSL 建立的公式的方式。它會漏掉錯誤的公式(就像這個例子一樣),而且應該顯示錯誤訊息的時候它也不會顯示。
jthi_1-1788881236165.pngjthi_1-1788881236165.pngjthi_1-1788881236165.png
jthi_2-1788881243139.pngjthi_2-1788881243139.pngjthi_2-1788881243139.png
jthi_4-1788881274171.pngjthi_4-1788881274171.pngjthi_4-1788881274171.png
在這種情況下,它應該在列屬性中顯示此資訊。
jthi_7-1788882167381.pngjthi_7-1788882167381.pngjthi_7-1788882167381.png
以及公式編輯器中的這個
jthi_6-1788882151203.pngjthi_6-1788882151203.pngjthi_6-1788882151203.png
如果你嘗試應用它,會報這樣的錯誤
jthi_5-1788882131736.pngjthi_5-1788882131736.pngjthi_5-1788882131736.png
如果將其修改為 Column()[],則顯示正確,並且傳回正確的結果。
jthi_0-1788880964367.pngjthi_0-1788880964367.pngjthi_0-1788880964367.png
但最終由 JMP 開發人員決定這種行為應該如何表現。
回覆:如何使用 JSL 基於隨機列建立平均值列Jarmo 的觀點很好,並提供了一個使用 Column("name")[] 的替代方案。正如 Jarmo 所提到的,在公式編輯器中使用 Column("name")[] 看起來不太美觀。我下面的解決方案沒有涉及這個選項,但它解釋了為什麼很多用戶會對此感到困惑。它確實重複了 Jarmo 已經發布的大部分內容,但既然我已經輸入好了…
實際上,樓主提供的腳本並非漏洞。這是預期行為,也說明了許多使用者在引用欄位以及列公式求值方面所存在的困惑。
造成困惑的關鍵在於理解 `Column("name")` 文法和 `:name` 文法之間的差異。在某些情況下,兩者都是引用列的合法方式,但它們傳回的值不同。具體來說,`Column("name")` 傳回的是對列物件的引用,而 `:name` 傳回的是目前行 `name` 列中的值。順便一提,`:name` 是函數 `As Column("name")` 的運算子形式。換句話說,它們本質上是相同的。
以下範例腳本可供參考。該腳本假設您的 JMP 會話中已開啟並更新了 Cars.jmp 資料表。
Names Default To Here(1);
dt = Open( "$SAMPLE_DATA/Cars.jmp" );
// sending messages to a column; either syntax works
Column(dt, "Year") << Set Property("Range Check", LELE(87, 97));
dt:Head IC << Set Property("Spec Limits", {LSL( 150 ), Show Limits( 1 )});
// Return values
// returns a column object reference shown as Column( "Year" ) in log
Column(dt, "Year"); // returns Column( "Year" )
// returns value in Year column on the current row.
// Since current row is 0 (the default invalid row number), returns missing (.)
:Year; // returns .
// Set the current row to the first row
Row() = 1;
:Year; // returns 87
考慮到以上信息,應該很清楚 JMP 無法計算一組列引用的平均值。這就是為什麼第一列公式無法成功計算的原因。 `Mean()` 函數需要值-這些值在第二列公式中提供。資料表在計算列公式時,會將目前行設為 1,然後計算儲存在「公式」屬性中的表達式。它會將回傳值放入目前行的列儲存格中。然後,它會將當前行設定為下一個值並重複此過程。這些步驟會一直重複,直到計算完最後一行的公式。因此,列公式的語法必須能夠對資料表的每一行都進行計算。
對我來說,你的範例腳本中有一個出乎意料的結果。那就是 `As Column(Column("name"))` 語法與 `As Column("name")` 的計算結果相同。我原本以為它會報錯,但 JMP 卻接受了它並正確理解了其意圖。這就是腳本語言相對於正式程式語言的(有時)優勢。不過,我不建議使用這種語法,因為它將來可能會出錯。
我認為,根據範例腳本,實現目標的最佳方法是放棄第一種方法中的列公式,而採用第二種方法。此外,還需要將 ColList 定義為列名列表,而不是列引用。以下是修改後的 OP 腳本範例,應該更穩定可靠。
dt = Open( "$SAMPLE_DATA/Cars.jmp" );
ColList = {};
For( i = 1, i <= N Cols(), i++,
If( Column( i ) << GetDataType == "Numeric",
Insert Into( ColList, <FONT color="#FF6600"><STRONG>Column( i ) << Get Name</STRONG></FONT> )
)
);
MeanExpr2 = Name Expr( Mean() );
For( i = 1, i <= N Items( ColList ), i++,
Insert Into( MeanExpr2, Name Expr( As Column( ColList[i] ) ) )
);
Eval( Eval Expr( dt << New Column( "Average of numerics 2", Formula( Expr( Name Expr( MeanExpr2 ) ) ) ) ) );
回覆:如何使用 JSL 基於隨機列建立平均值列從理論和實際實現機制的角度來看,您說的或許完全正確…但使用者介面並非如此運作。我可以從表格中選擇列,然後將它們拖曳到 mean() 運算子上進行計算。然而,在腳本中,我無法選擇列,而必須選擇字串物件(對應於列名),然後告訴 JSL 將它們解釋為列引用,之後才能將這些引用注入到 mean 運算子中。如果能改進 JSL 運算符,使其將 Column("Name") 視為可以索引到行的列對象,豈不是一個簡單的解決方案?這樣做會更直觀,也更符合使用者介面的行為和使用者的思考方式。正如您所指出的,用戶對此有很多困惑。
正如 Jarmo 所指出的:公式編輯器中的錯誤訊息需要改進,使其更加清晰一致。再次強調:請注意,預覽顯示計算結果正確,但使用 Column("Name") 語法時,公式卻無法計算。