あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?2 つの異なるデータセットから取得した 2 つのグラフ ビルダーを含むウィンドウがあり、1 つのデータ フィルターで両方のグラフをフィルター処理したいと考えています。これは不可能だと思います。代わりに 2 つの「同期」データ フィルターを使用することを考えましたが、わかりませんでした。先週の JMP Discovery で、 @danschikore が2 つの同期フィルターを使用するための可能なソリューションとしてイベント ハンドラーを勧めてくれました。もうすぐ動作すると思いますが、行き詰まっています。
以下のスクリプトは、2 つのフィルターと 2 つのグラフを作成します。上部のフィルターで選択した内容が下部のフィルターに自動的に反映されるようにします。これが機能したら、下部のフィルターを非表示にして、ユーザーには 1 つのフィルターで両方のグラフが制御されているのが見えるようにします。
現状では、ユーザーが上部のフィルターで選択を行うと、スクリプトは「Get Where Clause」を使用してその Where 句をログに出力しますが、この Where 句を下部のフィルターに適用する必要があります。その Where 句のテキストを下部のフィルターに押し込むことができる「Set Where Clause」のようなコマンドが欲しいのですが、存在しないようです。テキスト文字列 (以下) を「解凍」して、下部のフィルターに渡すことができる形式に変換しなければならないシナリオを回避したいと本当に思っています。
選択範囲( :name == \!"ALICE\!" | :name == \!"BARBARA\!" )
最初のフィルターで 2 番目のフィルターを何らかの方法で制御できることを自分自身に納得させるために、最初のフィルターで 2 番目のフィルターの選択をクリアします。つまり、両方のフィルターと通信でき、最初のフィルターから where 句を抽出できますが、それを 2 番目のフィルターに適用することはできません。
ボーナスの質問です: この同期が機能したら、2 番目のフィルターを非表示にしたいと思います。スクリプトの最後の行は、最初のフィルターを非表示にします。代わりに 2 番目のフィルターを非表示にするには、これをどのように変更すればよいか知っている人はいませんか?
ありがとう、
トム

自動化とスクリプトRe: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?Eval():コードを実行します *)
Eval Expr: Expr() で囲まれたすべてを事前評価します *)
Expr():事前に評価する必要があるコードのマーカー *)
*) 私の脳:「E ワード」 - 3 回。
4番目はExpr Name()です; -)
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?同意する : )
Big Class の場合、簡単な解決策があるかもしれませんが、この解決策は実際の問題の解決には役立たない可能性があります。
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?@hogi 、これらのリンクをありがとうございます。Eval/Eval Expr() は、ここ数年、私にとって JSL で最もイライラする部分でした。コミュニティからの例をコピーして調整することで、何度かうまく使用しましたが、実際によく理解できたとは感じませんでした。あなたが収集したリソースのリストを確認するのが楽しみです。そうすれば、ようやく理解が深まるかもしれません。これは、私のツールキットに追加する必要があるものであることはわかっています。
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?連結を意味していました。更新/結合を行うことで、年が関連付けられていない身長データを、年ごとの体重データに関連付けます。新しいグラフでは、バーバラの身長が 2022 年、23 年、24 年に 60 インチと測定されたように見えますが、実際はそうではありません。
ここでのポイントは、下のデータは年と関連しているが、上のデータは関連していないため、中央に 1 つのバーを配置したいということです。身長の代わりに、「学生が生まれた時期と場所の 1 人あたりの GDP」を使用したほうがよかったかもしれません。明らかに 22/23/24 とは関連していません。
上部のグラフと下部のグラフの基礎となるデータの構造が異なるため、必要な図 (上記) を作成するには 2 つの個別のグラフ ビルダーが必要だと思います。
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?@TomF さん、ありがとうございます。ラベル設定の制限に対抗する非常にクールなトリックです。2 つのテーブルを使用します : )
なぜこのようなプロットを個別のグラフでも 1 つのグラフに組み合わせても生成できないのか疑問に思います。

1 つのグラフにラベルを設定すると、他のグラフにも自動的にラベルが表示されます 
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?さまざまなフィルタリング手法を知ることで、JMP でさまざまな便利な操作を実行できるようになります (特に大量のデータがある場合には、フィルタリング手法が必要になることもあります)。
連結とは更新/結合を意味し、このような単一のテーブルを持つことができると思います(一意の識別子がある場合は、仮想結合を使用できます)。

これからこのようなグラフを作成することができます

たとえば、テキストレット(ホバーラベル)を利用することで実現できます。
Graph Builder(
Size(1085, 688),
Show Control Panel(0),
Show Legend(0),
Variables(X(:Name), X(:Year, Position(1)), Y(:Height), Y(:Weight), Overlay(:Name)),
Elements(Position(1, 1), Bar(X(1), X(2), Y, Overlay(0), Legend(13))),
Elements(Position(1, 2), Line(X(1), X(2), Y, Legend(15)), Points(X(1), X(2), Y, Legend(16))),
Local Data Filter(
Add Filter(
columns(:Name),
Where(
:Name == {"AMY", "BARBARA", "CAROL", "CHRIS", "CLAY", "DANNY", "DAVID", "EDWARD", "ELIZABETH", "FREDERICK", "HENRY", "JACLYN"}
),
Display(:Name, N Items(15), Find(Set Text("")))
)
),
SendToReport(
Dispatch({}, "Name", ScaleBox, {Label Row(2, Show Major Grid(1))}),
Dispatch({}, "Graph Builder", FrameBox, {Set Textlet(Markup("Serial Number: {:Serial No.[local:_firstRow]}"))}),
Dispatch({}, "Graph Builder", FrameBox(2), {Set Textlet(Markup("Serial Number: {:Serial No.[local:_firstRow]}"))})
)
);
必要に応じて、表示されるテキストをさらにカスタマイズできます。JMP の使用 > JMPレポート > JMPグラフのホバーラベルのカスタマイズ > JMPグラフのホバーラベルにテキストを追加
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?こんにちは@TomF 、個々のステップを説明するためにコードにコメントを追加しました。
1 つのトリックは、Extract Expr()です。これは、式をスキャンして特定のパターンを検索します。
先ほど、1 つのデータ フィルターを使用して同じダッシュボード内の 4 つの追加データ フィルターを制御する古いスクリプトを調べてみました。
そしてそれは
For( i = 1, i <= N Arg( filterScript ), i++,
If( Head( Arg( filterScript, i ) ) == Expr( Add Filter() ),
filterExpression = Arg( filterScript, i )
)
);
Extract Expr()を介したアプローチははるかにエレガントです。私は昨年、このディスカッションで@jthiからそれを学びました。
:folded_hands: 式のインデックス作成: 読み取りおよび書き込みアクセス
もう一つのトリック: Eval (Eval Expr( Expr())) - スイスアーミーナイフ!
JSLの問題の95%を解決します:)
JMP での式の処理: Tipps と Trapdoors
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?残念ながら、そのコードの多くは私には理解できませんが、大体の考え方は理解できました。より複雑な状況では、これを念頭に置いておきます。ありがとうございます!
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?はい、異なるテーブルからの 2 つのレポートをフィルターする 1 つのフィルターが必要です。上で共有した単純な Big Class の例では意味がないと思いますが、実際のデータ セットの構造を厳密に模倣した、より複雑な例を添付します。
各生徒の現在の身長が記載された表と、過去 3 年間の各生徒の体重が記載された表があるとします。そのデータを次のように表示します。

身長データ セットには、生徒 1 人につき 1 行あることは明らかです。体重データは生徒 1 人につき 1 行 (体重の 3 列) から始まりますが、Graph Builder で体重を積み重ねずに下のグラフを作成する方法は知りません。これで、体重表の行数は身長表の 3 倍になりました。
データ フィルターは 2 つの異なるテーブルをフィルターできないため、これまでの解決策は、このグラフを作成できるようにテーブルを連結することでした。これはエレガントではありませんが、問題なく機能します。
本当に困ったのは、身長の上にマウスを置いたときに、測定中に靴を履いていたかどうかをポップアップで表示したいのですが、体重の上にマウスを置いたときに、使用された体重計のシリアル番号を知りたいのです。すべてのデータが 1 つのテーブルにあり、両方の列に Label(1) を作成すると、マウスを置いたときに値が欠落してしまいます (体重測定には体重計のシリアル番号がないため)。これも対処できますが、非常に面倒になってきました。
2 つの同期フィルター (1 つは非表示) を持つ 2 つのテーブルにデータを残すという解決策の方がはるかに効果的だと思います。ただし、このグラフを作成するためのより良い方法がある場合は、ぜひご提案ください。
Graph Builder と、それを JSL で制御する機能について、一般的な感想を述べておきます。2 つの異なるグラフをシームレスに融合できるのは、上のグラフの下部と下のグラフの上部にあるすべてのものをオフにして、それらを互いに近づけることができるからです。これにより、特定の状況で非常にカスタマイズされた、非常にデータ密度の高いグラフを作成できます。そして、今ではそれをエレガントにフィルタリングすることもできます:) 将来、他の人もこれを便利だと感じるかもしれません。
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?このような処理にはさまざまなオプションがあり、すべては実際に何が行われるか (データがどのように見えるか、行の状態を操作できるか、何がフィルターされるか (およびその理由)、など) によって異なります。ここでは、多くの場合 (通常) 非常にうまく機能する 1 つのオプションを示しますが、ハンドラーの機能は非常に複雑です (このような処理では、固定サイズ (Spacer Box() の助けを借りて) を追加することは、ウィンドウの煩わしい点滅を回避するために一般的に良いアイデアです)。
Names Default To Here(1);
dt1 = Open("$SAMPLE_DATA/Probe.jmp");
dt2 = dt1 << Subset(All Rows, Selected Columns(0));
dt2 << Delete Rows(dt2 << get rows where(:Process == "Old"));
nw = New Window("",
Data Filter Context Box(
H List Box(
Data Filter Source Box(
df1 = dt1 << Data Filter(
Local,
Show Controls(0),
Show Modes(0),
Mode(Include(1)),
Add Filter(Columns(:Site, :Process)), Display(:Site, N Items(5))
),
),
V List Box(
gb1 = dt1 << Graph Builder(
Size(525, 458),
Show Control Panel(0),
Variables(X(:Lot ID), Y(:DELL_RPNBR)),
Elements(Bar(X, Y, Legend(4)))
),
gb2_collector = V List Box()
)
)
)
);
create_gb2 = function({a},
c = df1 << Get where clause;
If(Is Missing(c), // could also just use dt2 instead of dt2_private
dt2_privatenew = dt2 << Subset(All Rows, Selected columns only(0), Link to original data table(1), private);
,
where = Arg(Parse(df1 << Get where clause));
dt2_privatenew = Eval(EvalExpr(dt2 << Subset(
Filtered Rows(Expr(Name Expr(where))),
Selected columns only(0),
Link to original data table(1),
private
)));
If(Is Empty(dt2_privatenew), // no rows left -> pick first row and remove it, no linking
dt2_privatenew = dt2 << Subset(Rows(1), Selected columns only(0), Link to original data table(0), private);
dt2_privatenew << Delete Rows(1);
);
);
nw << inval;
Try(Close(dt2_private, no save)); // will also remove old graph builder
dt2_private = dt2_privatenew;
gb2_collector << Append(
gb2 = dt2_private << Graph Builder(
Size(528, 458),
Show Control Panel(0),
Variables(X(:Lot ID), Y(:DELL_RPNBR)),
Elements(Bar(X, Y, Legend(20)))
)
);
wait(0);
nw << Update Window;
);
create_gb2(.);
nw:handler = df1 << Make Filter Change Handler(
create_gb2();
);
Eval(EvalExpr(
nw << On Close(
Try(Close(Expr(dt1), no save));
Try(Close(Expr(dt2), no save));
Try(Close(Expr(dt2_private), no save));
);
));
Write();Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?@hogiあなたのコードが何をするのか完全には理解していませんが、それを入力したところ完璧に動作しました。ありがとうございます!
正直に言うと、私は本当に落とし穴から逃げたわけではありません。落ちて、また脱出したのです。これコミュニティの投稿を読みましたが、イベント ハンドラーを変数として保存する理由が見当たらなかったので、保存しませんでした。うまくいきませんでした。投稿に注意深く従い、変数として保存したところ、動作するようになりましたが、何が起こったのか理解せずにそのまま続けました。将来誰かが傷つくのを防げればと、あなたの 2 つの落とし穴を使ってコードにコメントを入れました。
この場合、フィルタリングは単純で (常に 1 つの列)、両方のテーブルに同じ x 値が含まれているため、問題はありません。
更新されたコードを上記に掲載しました。
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?
@jthi は次のように書きました:
ローカルにする必要がある場合は、2 つのローカル データ フィルターを使用する以外のオプションもあります (これも可能です)。
フィルター状態ハンドラーは、データ フィルターの変更によってのみトリガーされるわけではありません。
棒グラフは保存されますが、ポイント プロットの場合は、マウスがデータ ポイントに触れるたびに状態ハンドラーがトリガーされます。
したがって、プロットの種類に応じて、現在のフィルター設定を以前の設定と比較し、変更を検出したときにその設定を 2 番目のプロットに適用することが適切な場合があります。
ここで投票してください:
JMP の状態ハンドラー (ホバー ラベル、行状態ハンドラー、フィルター状態ハンドラー、スケジューラーなど) を改善します。
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?両方のテーブルに同じ値が含まれていることを確認してください。
データ フィルターで一致する行が見つからない場合は、リセットされてすべての行が表示されます。

この問題はJMP19で修正されます:folded_hands:列プロパティ: 包含/強制値
<=JMP18の回避策として、残りの列に欠損データを含むダミー行を追加することができます。
-> プロットには表示されませんが、データ フィルターがリセットされるのを防ぎます。
もっと見る...
//Data Filter Event Handler Test.jsl
//2024-10-31
dtHeight = Open( "$SAMPLE_DATA/Big Class.jmp" );
dtHeight << delete columns({"age", "sex", "weight"});
dtHeight << Set Name ("Height");
dtWeight = Open( "$SAMPLE_DATA/Big Class.jmp" );
dtWeight << delete columns({"age", "sex", "height"});
dtWeight << Set Name ("Weight");
dtHeight << select where(:Name == "ALFRED") << delete rows(); // <- dangerous !!!!
Try(win << Close Window);
win = New Window("Height and Weight",
Data Filter Context Box(
H List Box (
V List Box(
df1_Wt = dtWeight << Data Filter( Local,
Show Controls( 0 ), Show Modes( 0 ), Mode( Include( 1 ) ),
Add Filter(Columns(:name)),
Display( :name, N Items( 4 ))
),
df2_Ht = dtHeight << Data Filter( Local,
Show Controls( 0 ), Show Modes( 0 ), Mode( Include( 1 ) ),
Add Filter(Columns(:name)),
Display( :name, N Items( 4 ))
)
),
V List Box (
gbWt = dtWeight << Graph Builder(
Size( 612, 250 ),
Show Control Panel( 0 ), Show Legend (0), Show Title (0),
Show X Axis (0), Show X Axis Title (0), Show Footer( 0 ),
Variables( X( :name ), Y( :weight ) ),
Elements( Bar( X, Y, Legend( 6 ) ) ),
//Dispatch( {}, "Graph Builder", OutlineBox, {Set Title( "" )} ),
Dispatch({},"weight",ScaleBox,{ Max( 200 )})
),
H List Box(
Spacer Box(Size(25,200)),
gbHt = dtHeight << Graph Builder(
Size( 600, 300 ),
Show Control Panel( 0 ), Show Legend (0), Show Title (0),
Variables( X( :name ), Y( :Height ) ),
Elements( Bar( X, Y, Legend( 6 ) ) ),
Dispatch( {}, "Graph Builder", OutlineBox, {Set Title( "" )} )
)
)
)
)
)
);
eh = df1_Wt << MakeFilterChangeHandler(
function({x},
dfscript = df1_Wt << get script();
filter = Extract Expr(dfscript, Add Filter(Wild List()));
Eval(Eval Expr(df2_Ht << delete all() << Expr (Name Expr(filter)))))
);
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?データフィルタコンテキスト/ソースボックスを使用して、1つのフィルタで2つ(またはそれ以上)のグラフをフィルタできますが、ソーステーブルが同じである必要があります。
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
nw = New Window("Selection Filter",
Data Filter Context Box(
H List Box(
dfsb = Data Filter Source Box(
dt << Data Filter(
Local,
Add Filter(columns(:age), Display(:age, N Items(6)))
),
),
Graph Builder(
Size(208, 207),
Show Control Panel(0),
Show Legend(0),
Variables(X(:age)),
Elements(Bar(X, Legend(3)))
),
Bubble Plot(
X(:weight),
Y(:height),
Sizes(:age),
Title Position(0, 0)
)
)
)
);
ここで質問したいのは、何をしようとしているのかということです。異なるテーブルから 2 つのレポートをフィルターする1 つのフィルターが必要ですか? ローカル データ フィルターを 1 つ使用し、それを使用して 2 番目のテーブルから行を非表示/除外します (ローカルだけではなくテーブルを変更できるようにする場合)。ローカルにする必要がある場合は、2 つのローカル データ フィルターを使用する以外のオプションがあります (これも可能です)。
Re: あるデータ フィルターを別のデータ フィルターにミラーリングするにはどうすればよいですか?ニース : )
最初の状態ハンドラーを作成したとき、フィルター状態ハンドラーを変数に保存するのを忘れたため、すぐに破棄されてしまいました。
そして、引数が 0 個の関数を使用したため、動作しませんでした。 -> よくできました。両方の落とし穴を逃れました : )
Set where 句はありません。Where句はデータ フィルターが理解できるメッセージではないため、テーブルに送信して行を選択できます。さらに、 << Get Where 句 () は文字列を返します。これを式に変換するには、 Parse を使用する必要があります。
解凍は予想よりも手間がかかりません。データ フィルターにスクリプトを要求し、 Extract Expr()でAdd Filter()部分を抽出し、2 番目のフィルターに適用するだけです。単純な選択には機能します *)
eh = df1_Wt << MakeFilterChangeHandler(
Function( {x},
dfscript = df1_Wt << get script(); // store the code to create DF1 - with all the settings
filter = Extract Expr(
dfscript, // take the code which is stored in dfscript and ...
Add Filter( Wild List() ) // search for the part with Add Filter(something). Wild List() - like magic :)
);
Eval( // run the code
Eval Expr( // search for any Expr() and execute it (*)
df2_Ht << delete all() // remove all previous settings
<< Expr( // (*) find this Expr() and execute it
Name Expr( filter ) // take the code which is stored in "filter" and replace filter with the actual code
)
)
);
)
);
*) OR() を介して複数のフィルターを組み合わせると、スクリプトには複数のadd Filter()が含まれ、 Extract Expr() は最初のフィルターのみを返します。
究極のクローン関数を取得するには、DF スクリプトを解析し、すべてのAddFilter()を収集し、それらを 2 番目のデータ フィルターに順番に適用します。