一貫性のない許容構文AllCols = dt << Get Column Names();
AllColNames = dt << Get Column Names(string);
for(i=3, i<=n items(AllCols), i++,
colcol = AllCols[i];
cname = AllColNames[i];
nnm1 = Col Number(colcol);
Fstr = "num(:\!""||cname||"\!"n)";
Fexpr = parse(Fstr);
newcol = dt << new column("Temp", numeric, formula(eval(evalexpr(Fexpr))));
nnm2 = Col Number(newcol);
if(nnm2 == nnm1,
newcol << delete formula();
dt << Delete Columns(colcol);
newcol << set name(cname), //else
dt << Delete Columns(newcol);
);
);私は Windows で JMP18 を使用しています。頻繁に使用したいコードを書くときは、そのためのツールバー ボタンを作成するのが好きです。しかし、開いているスクリプト ウィンドウから実行できるコードが、ツールバー アイコンから実行すると実行できないことがあります。次の例では、列をループし、すべてのエントリが数値の場合は文字から数値に変更しています。ツールバーから実行する場合、次の行に問題があります。
newcol = dt << new column("Temp", numeric, formula(eval(evalexpr(Fexpr))));
この構文は、スクリプト ウィンドウから実行する場合には許容されます。
なぜ状況ごとに jsl インタープリターが異なるのでしょうか?
これにはどのような構文が普遍的に受け入れられるでしょうか?
非常に大きなデータセットと列の場合、これは遅くなる可能性があります。これを行うより良い方法はありますか?
自動化とスクリプトデータのブレンドとクリーンアップウィンドウズRe: 一貫性のない許容構文どのようなエラーメッセージが表示されましたか?スクリプトウィンドウには現在のデータテーブルがありますが、ツールバースクリプトにはない可能性があります。
currentDatatable(dt);
スクリプトの先頭に記述するだけで十分です。
あなたは出来る
print(currentDatatable());
スクリプトの先頭で、ツールバー スクリプトが何を知っているかを確認します。
Re: 一貫性のない許容構文ツールバーは、スクリプトにNames Default To Here(1)(常に追加しておくべきだと思います)を追加している可能性があります。

すべてがグローバルスコープ内にある場合には表示されないエラーが表示される可能性があります(ただし、通常はエラーです)。私はEval(EvalExpr())またはEval(Substitute())を使用して数式を構築します。
Eval(EvalExpr(
newcol = dt << New Column("Temp", numeric, formula(Num(Expr(NameExpr(AsColumn(dt, i))))));
));
大規模なデータセットの場合は、このようなサンプリングを検討する必要があるかもしれません。数式を使わないソリューションもあり、より高速になる可能性がありますが、データに依存する可能性もあります。
何らかの理由で、私はこれを JMP コミュニティに公開していません (少なくとも見つけられませんでした)。 文字列を数値に変換 (github.com) 。https
/github.com/jthi-jmp-tools/character-columns-to-numeric/blob/main/bin/bin/character_columns_to_numeric.jslのコードを見て、このタスクをどのように実行したかを確認できます。それ以来、このスクリプトをやり直しましたが、正しく覚えていれば、最近は少し異なる方法を使用しています。
Re: 一貫性のない許容構文ツールバーアイコンは現在のデータテーブルを認識します():
問題はむしろその逆です。
「dt=現在のデータテーブル()」を定義してください。
dt << Get Column Names();
Re: 一貫性のない許容構文ありがとうクレイグ。
エラーメッセージは次のとおりです:
名前が解決されていません: '2PCS_X(um)' のアクセスまたは評価で 1 行目の 2PCS_X(um)、"2PCS_X(um)"n /*###*/
「2PCS_X(um)」は評価される最初の列の名前です。
したがって、最初の列の式は次のようになります。
newcol = dtTOSA << 新しい列("Temp", 数値, 数式(Num( :"2PCS_X(um)"n )));
Re: 一貫性のない許容構文また、実際のスクリプトでは、dt を変数として使用しません。dtTOSA のような、より説明的な変数を使用します。(上記を参照) 特定のデータ テーブルをアドレス指定するときは常に、このステートメントで行ったように、混乱を避けるために明示的に指定します。インタープリターが、私が別のテーブルを参照していると判断するのは理解できません。
Re: 一貫性のない許容構文おそらくそうですが、エラー メッセージは、JMP が「2PCS_X(um)」n を適切な場所で探していないことを示しています。ツールバー スクリプトがどのようなコンテキストを使用できるのかはわかりません。
Re: 一貫性のない許容構文クレイグ
あなたの提案に従って print ステートメントを使用しましたが、問題と思われる行に到達しませんでした。
newcol = dt << new column("Temp", numeric, formula(eval(evalexpr(Fexpr))));問題はこの行にありました。
nnm1 = Col Number(colcol);
そこでこれを変更したらうまくいきました。
nnm1 = dtTOSA << Col Number(colcol);
また、コードの後半で JMP に現在のテーブルが何であるかを再度知らせる必要があり、機能させるには列の削除で {} を使用する必要があることがわかりました。何らかの理由で、スクリプト ウィンドウから実行する場合、JMP はこれらの中括弧があっても気にしません。
コード スニペットは次のようになります。ちなみに、これはこれと別のテーブルも作成する、より長いコードの一部です。
AllCols = dtTOSA << Get Column Names();
AllColNames = dtTOSA << Get Column Names(string);
currentDatatable(dtTOSA);
for(i=3, i<=n items(AllCols), i++,
colcol = AllCols[i];
cname = AllColNames[i];
nnm1 = dtTOSA << Col Number(colcol);
Fstr = "num(:\!""||cname||"\!"n)";
Fexpr = parse(Fstr);
newcol = dtTOSA << new column("Temp", numeric, set formula(eval(evalexpr(Fexpr))));
nnm2 = dtTOSA << Col Number(newcol);
if(nnm2 == nnm1,
currentDatatable(dtTOSA);
newcol << delete formula();
dtTOSA << Delete Columns({colcol});
wait(0);
newcol << set name(cname), //else
dtTOSA << Delete Columns({newcol});
);
);しかし、今度は別の問題が発生しています。新しい列の名前を変更する前に古い列を削除したにもかかわらず、JMP は列名の後に不要な 2 を配置します。スクリプト ウィンドウから実行すると、これも実行されません。wait(0) ステートメントを含めてみましたが、役に立ちませんでした。
これをどうすれば修正できますか?
Re: 一貫性のない許容構文実際には、列の削除操作は実行されていません。
dtTOSA << Delete Columns({colcol});したがって、元の文字列と新しい数値の列が保持されます。
Re: 一貫性のない許容構文不思議なことに、「else」条件に進むと、その削除ステートメントは正常に機能します。
Re: 一貫性のない許容構文ただし、列は 2 つの異なる方法 (1 つはテキスト文字列名、もう 1 つは列タイプ) で参照されますが、最終的にはうまくいきました。私は 18 年間 jsl でコードを書いてきましたが、jsl で列を変数として参照するのは、一貫性がなく混乱を招くと感じています。
AllCols = dtTOSA << Get Column Names();
AllColNames = dtTOSA << Get Column Names(string);
currentDatatable(dtTOSA);
for(i=3, i<=n items(AllCols), i++,
colcol = AllCols[i];
cname = AllColNames[i];
nnm1 = dtTOSA << Col Number(colcol);
Fstr = "num(:\!""||cname||"\!"n)";
Fexpr = parse(Fstr);
newcol = dtTOSA << new column("Temp", numeric, set formula(eval(evalexpr(Fexpr))));
nnm2 = dtTOSA << Col Number(newcol);
if(nnm2 == nnm1,
currentDatatable(dtTOSA);
newcol << delete formula();
dtTOSA << Delete Columns(eval(cname));
currentDatatable(dtTOSA);
newcol << set name(cname), //else
dtTOSA << Delete Columns({newcol});
);
);Re: 一貫性のない許容構文私は常に列ベースとして文字列を使用し、必要に応じてそこから参照を構築します。これは、さまざまな種類の参照を処理する最も柔軟な方法であることがわかりました。
たとえば、スクリプトの目的をいくつか想定すると (3 列目から始めてすべてを調べ、値を数値に変更する新しい数式列を作成し、欠損値を比較して、結果に基づいてアクションを実行する)、JMP18 では次のように記述します。
Names Default To Here(1);
dtTOSA = New Table("Untitled",
Add Rows(4),
Compress File When Saved(1),
New Column("Column 1",
Numeric,
"Continuous",
Format("Best", 12),
Set Values([1, 2, 3, 4])
),
New Column("Column 2", Character, "Nominal", Set Values({"A", "1", "2", "3"})),
New Column("Column 3", Character, "Nominal", Set Values({"1", "2", "3", "4"})),
New Column("Column 4", Character, "Nominal", Set Values({"A", "B", "C", "D"}))
);
wait(1); // demo purposes
cols = dtTOSA << Get Column Names("String");
// Remove From(cols, 1, 2); // skipping this for demo purposes
For Each({colname}, cols,
// colname = cols[3]; // for testing
Eval(EvalExpr(
newcol = dtTOSA << New Column("Temp", numeric, Formula(
Num(Expr(Name Expr(As Column(dtTOSA, colname))))
));
));
newcol << Run Formulas;
newcol << delete formula();
orig_vals = Col Number(Column(dtTOSA, colname));
new_vals = Col Number(Column(dtTOSA, (newcol << get name)));
If(orig_vals == new_vals,
dtTOSA << Delete Columns(colname);
newcol << set name(colname);
,
dtTOSA << Delete Columns(newcol)
);
);
そして、もし私がこれを最初からやるとしても、あなたと少し似たようなアイデアを使うとしたら、私は(少なくとも現時点では)次のようなことをするでしょう。
Names Default To Here(1);
dt = New Table("Untitled",
Add Rows(4),
Compress File When Saved(1),
New Column("Column 1",
Numeric,
"Continuous",
Format("Best", 12),
Set Values([1, 2, 3, 4])
),
New Column("Column 2", Character, "Nominal", Set Values({"A", "1", "2", "3"})),
New Column("Column 3", Character, "Nominal", Set Values({"1", "2", "3", "4"})),
New Column("Column 4", Character, "Nominal", Set Values({"A", "B", "C", "D"}))
);
wait(1); // demo purposes
cols = dt << Get Column Names("Character", "String"); // We only need to check character columns
For Each({colname}, cols,
dt_summary = dt << Summary(
Group(Eval(colname)),
Freq("None"),
Weight("None"),
Link to original data table(0),
output table name("Summar of " || colname),
Private
);
orig_vals = Col Number(Column(dt_summary, 1));
Column(dt_summary, 1) << Set Data Type("Numeric");
new_vals = Col Number(Column(dt_summary, 1));
Close(dt_summary, no save);
If(orig_vals == new_vals, // we can change
Column(dt, colname) << Set Data Type("Numeric");
Column(dt, colname) << Set Modeling Type("Continuous");
);
);
私は Transform Each と Num を利用してこれらを実行する傾向がありますが、JMP に変換を実行させるだけで十分な場合もあります (ただし、これを実行したくない場合もあります...、スクリプト インデックスの Num() と、たとえば Num("5%") での動作を参照してください。<< Restrict はこの動作を回避します)
Re: 一貫性のない許容構文ジャーモ
ご意見ありがとうございます。列が数千、行が数万になることもあり、速度が問題になることがあります。現在の方法では、実際に以前の方法の約 1/3 に時間が短縮されましたが、それでも数分かかることがあります。いつかあなたの方法を試すこともできますが、毎回要約表を作成する方が遅いのか速いのか、どちらだと思いますか。
列参照の処理に関しては、Column(dt, colname) の使用を試みましたが、必ずしも機能するとは限りません。ただし、スクリプトでは As Column() も使用しています。原則として、数式には As Column() が使用されますか?
Re: 一貫性のない許容構文
@pcarroll1 は次のように書きました:
原則として、数式には As Column() が使用されますか?
はい、 column(columnname)または:column(dt, columnname)[]のいずれかとして
Re: 一貫性のない許容構文最初の「質問」: 特定のユースケースの速度を最適化しようとする場合、さまざまな方法があり、最も速い方法はデータに大きく依存する可能性があるため、どれが最も効果的か試してみる必要があります。この場合、複製値の確認を避けるために要約テーブル (または Summarize) を使用しましたが、前述したように、データ、JMP のバージョン、およびおそらく他の要因に依存します...
列参照の場合、私のルールは、常に列名とテーブル参照を開始点として使用し、それらから最終的な参照を構築することです。参照と見なすものは、どこでどのように使用するかによって異なります。たとえば、数式を作成する場合、数式で列を :mycol として参照するようにします (通常は問題ない AsColumn(mycol) や Column(mycol)[] ではなく)。また、式評価で NameExpr(AsColumn(dt,colname)) というかなり長いスタイルを使用して :mycol 形式を取得できます。通常、AsColumn(dt, colname) (または dt:colname) は Column(dt, colname)[Row()] (または Column(dt, colname)[]) と同じであり、現在の行の値を取得します (私の考えでは、常にこのようになるとは限りません。たとえば、プラットフォームでは、:mycol は行の特定の値ではなく参照であると考えています...)。
たとえば、mycol はすぐに評価され、JMP では Row() の初期値は 0 なので、欠損値が返されます (Row() は常に更新されるため、数式内では問題になりません)。
Names Default To Here(1);
dt = open("$SAMPLE_DATA/Big Class.jmp");
colname = "age";
mycol = NameExpr(AsColumn(dt,colname));
show(mycol)
これは、JMP の列参照、 As Column() (現在の行の値)とColumn() (列への参照)の違いを理解するのが最も難しい点です。これらの動作を理解するのは非常に困難です... 私は基本的に何度も失敗しながらそれを学んできました。そして今では、式を作成するときに最初にどちらを使用するかをよく理解しています (まだ時々間違っている可能性があります)。このトピックについては、いつかブログ記事を書きたいと思っています。なぜなら、私の意見 (現時点では) は他の人と異なる可能性があり、私は JMP (JSL) 開発者ではないものの、かなり優れた JMP スクリプト作成者であると考えているからです。
ここで注意すべき点が 1 つあります。私は JMP 開発者ではないので、開発者が JSL の動作をどう考えているかは気にしていません (開発者と意見が異なることもあります)。私の回答はすべて、私が使用した JMP バージョンでの経験に基づいています。
この投稿が少しわかりにくい場合は申し訳ありません(今晩ビールを少し飲んだかもしれません:))。このトピックに関する私の意見についてさらに詳しく知りたい場合は、このトピックに投稿してください(ただし、@ でタグ付けしていただければ、簡単に気付くでしょう)。必要に応じて、私にプライベート メッセージを送信することもできます。