ランダムな列に基づいて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>2番目の数式列は、列参照の周りに AsColumn() を追加します。これは既に列なので少し直感に反しますが、これでリスト、スカラー、または行列が作成され、mean() 数式が機能するようになります。</P> <P>なんだか複雑にしすぎている気がします。このような集計列を手順的に生成するもっと簡単な方法はないでしょうか?</P>
Re: 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();
Re: JSLでランダムな列に基づいて平均列を作成する方法ありがとうございます。しかし、これは単純な問題に対する高度な解決策です。列参照を列数式に追加するもっと簡単な方法を誰かが考え出してくれるかどうか、引き続き興味があります。
Re: 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()] を使用する必要があります。列が参照(または文字列)として取得されている場合、通常は数式で使用するために「列アクセス」に変換する必要があります。
Re: JSLでランダムな列に基づいて平均列を作成する方法JMPにバグ報告を提出しました。
このバグは、列の数式が Column(“name”) 引数を受け付けず、代わりに As Column() 式で囲む必要があるという点です。ビジュアル数式エディタを使用する場合、引数フィールドに列を追加するので、JSL も同様の動作を反映させるべきです。これを JSL に追加することで、JSL から列の数式を作成する作業が大幅に簡素化されます。
どうやら、数式エディタのプレビューウィンドウはこれを正しく解釈しているようで、プレビューが表示されます。
Re: 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の開発者が決定することである。
Re: 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() 関数には値が必要であり、その値は 2 番目の列の数式で指定されます。データ テーブルが列の数式を評価する際、現在の行を 1 に設定し、Formula プロパティに格納されている式を評価します。そして、戻り値を現在の行の列のセルに配置します。次に、現在の行を次の値に設定して、この処理を繰り返します。これらの手順は、最後の行の数式が評価されるまで繰り返されます。したがって、列の数式の構文は、データ テーブルの各行に対して評価できるものでなければなりません。
あなたのサンプルスクリプトには、私にとって予想外の結果が一つあります。それは、As Column(Column("name")) という構文が As Column("name") と同じ結果になるということです。私はエラーが発生すると予想していましたが、JMP はこれを受け入れ、意図を正しく解釈します。これは、形式的なプログラミング言語に対するスクリプト言語の(時として)利点と言えるでしょう。しかし、この構文は将来的に問題が発生する可能性があるため、使用することはお勧めしません。
サンプルスクリプトを踏まえると、目的を達成する最善の方法は、最初の列数式によるアプローチを廃止し、2番目のアプローチを採用することだと思います。さらに、ColListを列参照ではなく列名のリストとして定義するように変更します。以下に、元のスクリプト例を修正した、より堅牢なバージョンを示します。
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 ) ) ) ) ) );
Re: JSLでランダムな列に基づいて平均列を作成する方法理論的にも実際の動作原理的にも、あなたの指摘は恐らく全く正しいでしょうが、ユーザーインターフェースの動作はそうではありません。テーブルから列を選択してmean()演算子にドラッグすると計算されます。しかし、スクリプトでは列を選択できず、文字列オブジェクト(列名に対応するもの)を選択し、JSLにそれらを列参照として解釈するように指示する必要があります。そうすることで、mean演算子に挿入できます。JSL演算子を拡張して、Column("Name")を列オブジェクトとして扱い、行にインデックス付けできるようにするのは簡単な修正ではないでしょうか?そうすれば、はるかに直感的になり、ユーザーインターフェースの動作、ひいてはユーザーの思考を反映することになります。ご指摘のとおり、この点に関して多くのユーザーが混乱しています。
Jarmoさんの指摘についてですが、数式エディタのエラーメッセージは、より分かりやすく、一貫性のあるものに改善する必要があります。繰り返しになりますが、Column("Name")構文を使用した場合、プレビューでは正しく評価されているように見えても、実際には数式が評価されない点にご注意ください。