[JSL] 多数の指標に対する 2 対 1 側 T 検定のスクリプトみなさんこんにちは
多数のメトリック (500 以上) に対して TOST (Two-One Side T-Test) を自動化する JSL スクリプトを作成したいと思います。
TOST は「レベル」のペアで動作するため、「ペア」ごとに 1 行のみ必要なので、2 レベルの操作は簡単です。
私はすでに、「結合データ テーブル」を生成し、それに数式を含む列を追加して、「同等」または「同等ではない」という結果を出すことで、2 倍のレベルで適切に機能するスクリプトを作成しました。
2 倍以上のレベルで作業する場合、問題はさらに複雑になります。すべての可能な一意の「レベル」のペアを見つけて、メトリック + レベルのペアのすべての組み合わせに対して TOST 計算を実行する必要があります。
私は (このフォーラムで) リストからすべての可能な一意のペアを見つけて、それをテーブルまたはネストされたリスト (NchooseKmatrix()) に配置する方法を見つけました。
しかし、私はそこで行き詰まっています。必要なのは次のものです。
1- メトリック (列 1) のすべての可能な組み合わせと、可能なレベルのすべてのペア (列 2 と列 3) を含む新しいテーブルを作成します。
2- 次に、各行の各レベルのペアの統計を追加します。
この時点で、TOST を最終決定するための計算を理解できるようになります。
ダミーテーブルを生成するスクリプトを添付しました。次に、Oneway分析から結合されたデータテーブルを生成し、次に、メトリックとレベルの一意のペアのすべての組み合わせを含む3番目のテーブルを作成するという失敗した試みを添付しました。
ご協力ありがとうございます
Names Default To Here( 1 );
clear symbols();
Deletesymbols();
//Create table with random distribution (table 1)
dt = New Table( "tabletest",
Add Rows( 500 ),
New Column( "Product", Character, "Nominal", formula("Product " ||char( Random Integer( 1, 4 )))),
New Column( "Metric1", Numeric, "Continuous", formula( Random Normal( 10, 1 ) ) ),
New Column( "Metric2", Numeric, "Continuous", formula( Random Gamma( 10, 1 ) ) ),
New Column( "Metric3", Numeric, "Continuous", formula( Random Gamma( 10, 2 ) ) )
);
Column( dt, "Metric1" ) << set property( "spec limits", {LSL( 5 ), USL( 25 ), Show Limits( 0 )} );
Column( dt, "Metric2" ) << set property( "spec limits", {LSL( 0 ), USL( 40 ), Show Limits( 0 )} );
Column( dt, "Metric3" ) << set property( "spec limits", {LSL( 5 ), USL( 40 ), Show Limits( 0 )} );
dt << save( "$Desktop\tabletest.jmp" );
//Get a list from all unique Product
SplitBy = "Product";
summarize(ColumnSplitBy=by(Column (SplitBy)));
show(ColumnSplitBy);
For( i = N Items( ColumnSplitBy ), i > 0, i--,
If( ColumnSplitBy[i] == "",
Remove From( ColumnSplitBy, i, 1 );
)
);
//Get Column name
MetricCols = dt << Get Column Names( numeric, continuous, "string" );
//Get all unique combo of 2 Products
ColumnSplitByCombo = aslist( nchoosekMatrix(nitems(ColumnSplitBy), 2));
show (ColumnSplitByCombo);
//Create a combinaed datatable with stats (Table 2)
ow = dt << Oneway(
Y(Eval(MetricCols)),
X(Eval(SplitBy)),
Means and Std Dev(1),
SendToReport(
Dispatch(
{"Means and Std Deviations"},
"Std Dev Lower 95%",
NumberColBox,
{Visibility("Visible")}
),
Dispatch(
{"Means and Std Deviations"},
"Std Dev Upper 95%",
NumberColBox,
{Visibility("Visible")}
)
),
Invisible
);
tb = Report(ow[1])[Outline Box("Means and Std Deviations"), Table Box(1)];
dt2 = tb << Make Combined Data Table;
tb << close window;
//Create new table for the result, each row has a unique pair of Levels
dt3 = astable( nchoosekMatrix(nitems(ColumnSplitBy), 2), << column names({"x", "y"}) );
dt3 << new column ("first", character, << set values ( ColumnSplitBy[dt3:x << get values]));
dt3 << new column ("second", character, << set values ( ColumnSplitBy[dt3:y << get values]));
dt3 << delete columns (1::2);
//Create a nested list with each pair of levels
Listdt3 = aslist( nchoosekMatrix(nitems(ColumnSplitBy), 2));
show (Listdt3);
// I tried to use associate array() to match the level and name but couldn't make it work- 説教者
自動化とスクリプトRe: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプト私のリクエストをより良く説明するために、スクリーンショット付きのドキュメント「Untitled.png」を添付しました。
ありがとう!
Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプトたとえば、最初にグループ列を積み重ね、結果で更新してから再度分割することができます。
この例では、複数のメトリックが存在する可能性があることを考慮していません。
// Loop over Metrics and perform these for each of them
// Concatenate results into single table
dt3 = As Table(NChooseK Matrix(N Items(ColumnSplitBy), 2), <<COLUMN names=""></COLUMN>// Metrics should be taken into account here OR stacked table should contain them
dt4 << Update(
With(dt2),
Match Columns(:Data = :Level)
);
または、最終的な分割がない場合は、おそらく次のようになります

Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプトこんにちは@Voizingu : TOST は、100(1-2alpha)% 信頼区間が同等性限界内に完全に含まれているかどうかを確認するだけです。したがって、おそらく適切な回避策は、Fit Y by X 多重比較手順を使用して、すべての組み合わせを実行することでしょうか?
Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプトOneway プラットフォームに組み込まれている同等性テストを使用できない理由はありますか?
Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプトこんにちは、ジャーモさん
スタック > 更新 > 分割は素晴らしいアイデアです!!!
正常に実装できましたが、コードが少し汚いです (For() ループ、中間ステップなどが多い)。
の代わりに:
- テーブルを複数回連結する
- 次に、繰り返しの指標のリストから列を入力します
コードの最適化をさらに上手にできるようになりたいです。
dt5 をよりクリーンかつ最適化された方法で入力する方法はありますか? (ネイティブの JMP コマンドを使用するなど)
これについてあなたの提案をお待ちしています
とにかく、この件で助けてくれてありがとう:D
- 説教者
Names Default To Here( 1 );
clear symbols();
Deletesymbols();
//Create table with random distribution (table 1)
dt = New Table( "tabletest",
Add Rows( 5000 ),
New Column( "Product", Character, "Nominal", formula("Product " ||char( Random Integer( 1, 4 )))),
New Column( "Metric1", Numeric, "Continuous", formula( Random Normal( 10, 1 ) ) ),
New Column( "Metric2", Numeric, "Continuous", formula( Random Gamma( 10, 1 ) ) ),
New Column( "Metric3", Numeric, "Continuous", formula( Random Gamma( 10, 2 ) ) ),
);
Column( dt, "Metric1" ) << set property( "spec limits", {LSL( 5 ), USL( 25 ), Show Limits( 0 )} );
Column( dt, "Metric2" ) << set property( "spec limits", {LSL( 0 ), USL( 40 ), Show Limits( 0 )} );
Column( dt, "Metric3" ) << set property( "spec limits", {LSL( 5 ), USL( 40 ), Show Limits( 0 )} );
dt << save( "$Desktop\tabletest.jmp" );
//Get a list from all unique Product
SplitBy = "Product";
summarize(ColumnSplitBy=by(Column (SplitBy)));
show(ColumnSplitBy);
For( i = N Items( ColumnSplitBy ), i > 0, i--,
If( ColumnSplitBy[i] == "",
Remove From( ColumnSplitBy, i, 1 );
)
);
//Get Column name
MetricCols = dt << Get Column Names( numeric, continuous, "string" );
show(MetricCols);
//Get all unique combo of 2 Products
ColumnSplitByCombo = aslist( nchoosekMatrix(nitems(ColumnSplitBy), 2));
show (ColumnSplitByCombo);
//Create a combinaed datatable with stats (Table 2)
ow = dt << Oneway(
Y(Eval(MetricCols)),
X(Eval(SplitBy)),
Means and Std Dev(1),
SendToReport(
Dispatch(
{"Means and Std Deviations"},
"Std Dev Lower 95%",
NumberColBox,
{Visibility("Visible")}
),
Dispatch(
{"Means and Std Deviations"},
"Std Dev Upper 95%",
NumberColBox,
{Visibility("Visible")}
)
),
Invisible
);
tb = Report(ow[1])[Outline Box("Means and Std Deviations"), Table Box(1)];
dt2 = tb << Make Combined Data Table;
tb << close window;
//Create new table for the result, each row has a unique pair of Levels
dt3 = astable( nchoosekMatrix(nitems(ColumnSplitBy), 2), << column names({"x", "y"}) );
dt3 << new column ("first", character, << set values ( ColumnSplitBy[dt3:x << get values]));
dt3 << new column ("second", character, << set values ( ColumnSplitBy[dt3:y << get values]));
dt3 << delete columns (1::2);
//Create a nested list with each pair of levels
Listdt3 = aslist( nchoosekMatrix(nitems(ColumnSplitBy), 2));
show (Listdt3);
// I tried to use associate array() to match the level and name but couldn't make it work
// Loop over Metrics and perform these for each of them
// Concatenate results into single table
dt3 = As Table(NChooseK Matrix(N Items(ColumnSplitBy), 2), <<COLUMN names=""></COLUMN>Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプトこんにちはMRB3855さん、
素晴らしい指摘ですね。スクリプトの問題に焦点を当てるために最初のメッセージにはあまり多くの情報を入れたくありませんでしたが、最初のコード (2 つのレベルで機能) では、同等性の制限を範囲 [LSL;USL] の 5% に設定しました。
もちろん、これは必要に応じて変更できる任意の値です。
これにより、数百を超えるメトリックをふるいにかけ、通常は 12 個あるこの基準から「同等ではない」メトリックにフラグを付けることができます。
次に、このリストから徹底的な分析を実行できます。
- 分散分析
- 適切な範囲のTOST
- などなど
2 番目の点についてですが、私がよく理解しているのであれば、各メトリックに対して TOST プラットフォームを実行し、データを選択して Display Box() を介してテーブルに配置することを提案しているのでしょうか? もしそうであれば、それは確かに可能な解決策ですが、TOST の原理を理解し、処理時間を節約するために、自分で計算を実行したいと思います。
意味が通じるといいのですが:)
助けてくれてありがとう
- 説教者
Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプトこんにちは、マーク。
はい、最初は TOST プラットフォームを使用して Display Box() で統計を選択することを考えましたが、プラットフォームが提供するのと同じ結果を得るために、各パラメータを個別に計算するという別のアプローチを好みました。
事後的に考えれば、車輪の再発明よりも速いアプローチだったかもしれませんが、私はこれに多くの時間を費やし、達成に非常に近づいているので、(困難な方法で)始めたことを終わらせたほうがよいかもしれません、ハハ!
この利点の 1 つは、TOST メソッドの各ステップを理解できるようになったことです。
ありがとう
- 説教者
Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプト私はループを使用する可能性が高いですが、いくつかのマトリックス演算でこれを行うこともできます。このスクリプトは、私の意見では、読みやすくするために書き直す必要があります (変数の名前をより適切にし、出力テーブル名を活用し、不要なテーブルを閉じて、一般的なクリーンアップを行う)。
もっと見る...
Names Default To Here(1);
//Create table with random distribution (table 1)
dt = New Table("tabletest",
Add Rows(5000),
New Column("Product",
Character,
"Nominal",
formula("Product " || Char(Random Integer(1, 4)))
),
New Column("Metric1", Numeric, "Continuous", formula(Random Normal(10, 1))),
New Column("Metric2", Numeric, "Continuous", formula(Random Gamma(10, 1))),
New Column("Metric3", Numeric, "Continuous", formula(Random Gamma(10, 2))),
);
Column(dt, "Metric1") << set property("spec limits", {LSL(5), USL(25), Show Limits(0)});
Column(dt, "Metric2") << set property("spec limits", {LSL(0), USL(40), Show Limits(0)});
Column(dt, "Metric3") << set property("spec limits", {LSL(5), USL(40), Show Limits(0)});
SplitBy = "Product";
Summarize(ColumnSplitBy = by(Column(SplitBy)));
MetricCols = dt << Get Column Names(numeric, continuous, "string");
ColumnSplitByCombo = As List(NChooseK Matrix(N Items(ColumnSplitBy), 2));
//Create a combinaed datatable with stats (Table 2)
ow = dt << Oneway(
Y(Eval(MetricCols)),
X(Eval(SplitBy)),
Means and Std Dev(1),
SendToReport(
Dispatch({"Means and Std Deviations"}, "Std Dev Lower 95%", NumberColBox,
{Visibility("Visible")}
),
Dispatch({"Means and Std Deviations"}, "Std Dev Upper 95%", NumberColBox,
{Visibility("Visible")}
)
),
Invisible
);
tb = Report(ow[1])[Outline Box("Means and Std Deviations"), Table Box(1)];
dt2 = tb << Make Combined Data Table;
tb << close window;
//Create a nested list with each pair of levels
Listdt3 = As List(NChooseK Matrix(N Items(ColumnSplitBy), 2));
mcols = N Items(MetricCols);
l = Repeat(Listdt3, mcols);
m = J(N Items(l) / mcols, mcols) :*</img> (1::mcols);
mfinal = Sort Ascending(Shape(m, 1, N Items(l)));
dt3 = As Table(Matrix(l), <<COLUMN names=""></COLUMN>
</CODE><NOSCRIPT><CODE class=" language-jsl"><DIV class="lia-spoiler-noscript-container"><DIV class="lia-spoiler-noscript-content">名前はデフォルトでここに設定されます(1); //ランダム分布のテーブルを作成します(テーブル 1) dt = New Table("tabletest", Add Rows(5000), New Column("Product", Character, "Nominal", formula("Product " || Char(Random Integer(1, 4))) ), New Column("Metric1", Numeric, "Continuous", formula(Random Normal(10, 1))), New Column("Metric2", Numeric, "Continuous", formula(Random Gamma(10, 1))), New Column("Metric3", Numeric, "Continuous", formula(Random Gamma(10, 2))), ); Column(dt, "Metric1") << set property("spec limits", {LSL(5), USL(25), Show Limits(0)}); Column(dt, "Metric2") << set property("spec limits", {LSL(0), USL(40), Show Limits(0)}); Column(dt, "Metric3") << set property("spec limits", {LSL(5), USL(40), Show Limits(0)}); SplitBy = "Product"; Summarize(ColumnSplitBy = by(Column(SplitBy))); MetricCols = dt << Get Column Names(numeric, Continuous, "string"); ColumnSplitByCombo = As List(NChooseK Matrix(N Items(ColumnSplitBy), 2)); //統計情報を含む結合データ テーブルを作成します (表 2) ow = dt << Oneway( Y(Eval(MetricCols)), X(Eval(SplitBy)), Means and Std Dev(1), SendToReport( Dispatch({"Means and Std Deviations"}, "Std Dev Lower 95%", NumberColBox, {Visibility("Visible")} ), Dispatch({"Means and Std Deviations"}, "Std Dev Upper 95%", NumberColBox, {Visibility("Visible")} ) ), Invisible ); tb = Report(ow[1])[Outline Box("Means and Std Deviations"), Table Box(1)]; dt2 = tb << Make Combined Data Table; tb << close window; // レベルのペアごとにネストされたリストを作成します。Listdt3 = As List(NChooseK Matrix(N Items(ColumnSplitBy), 2)); mcols = N Items(MetricCols); l = Repeat(Listdt3, mcols); m = J(N Items(l) / mcols, mcols) (1::mcols); mfinal = Sort Ascending(Shape(m, 1, N Items(l))); dt3 = As Table(Matrix(l), < <COLUMN names=""></COLUMN></DIV></DIV>
<P><SPAN class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="jthi_1-1724774273332.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1724774273332.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1724774273332.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1724774273332.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1724774273332.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1724774273332.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1724774273332.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_1-1724774273332.png" style="width: 400px;"><span class="lia-inline-image-display-wrapper" image-alt="jthi_1-1724774273332.png" style="width: 400px;"><img src="https://us.v-cdn.net/6038925/uploads/images/67576i7A33F8F17FEAD03D/jthi_1-1724774273332.png" role="button" title="jthi_1-1724774273332.png" alt="jthi_1-1724774273332.png" /></span></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></P>
<P><SPAN class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="jthi_2-1724774284315.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_2-1724774284315.png" style="width: 304px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_2-1724774284315.png" style="width: 304px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_2-1724774284315.png" style="width: 304px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_2-1724774284315.png" style="width: 304px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_2-1724774284315.png" style="width: 304px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_2-1724774284315.png" style="width: 304px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_2-1724774284315.png" style="width: 304px;"><span class="lia-inline-image-display-wrapper" image-alt="jthi_2-1724774284315.png" style="width: 304px;"><img src="https://us.v-cdn.net/6038925/uploads/images/67577i906F6E675ADD899F/jthi_2-1724774284315.png" role="button" title="jthi_2-1724774284315.png" alt="jthi_2-1724774284315.png" /></span></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></P>
<P><SPAN class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="jthi_0-1724774190734.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_0-1724774190734.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_0-1724774190734.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_0-1724774190734.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_0-1724774190734.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_0-1724774190734.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_0-1724774190734.png" style="width: 400px;"><SPAN class="lia-inline-image-display-wrapper" image-alt="jthi_0-1724774190734.png" style="width: 400px;"><span class="lia-inline-image-display-wrapper" image-alt="jthi_0-1724774190734.png" style="width: 400px;"><img src="https://us.v-cdn.net/6038925/uploads/images/67575i9361F045B1E7C693/jthi_0-1724774190734.png" role="button" title="jthi_0-1724774190734.png" alt="jthi_0-1724774190734.png" /></span></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></P>
<P> </P> Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプトやあ、ジャルモ、
迅速なご対応ありがとうございます。
このラインは失敗している
m = J(N Items(l) / mcols, mcols) (1::mcols);
何を目的としているのか説明していただけますか?
通常はマトリックスを使用しないので、自分でデバッグしようとしましたができませんでした...
ご協力いただきありがとうございます
Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプト何らかの理由でそれが見つからない:*
m = J(N Items(l) / mcols, mcols) :*</img> (1 :: mcols);
目的はこのようなマトリックスを作成することです

これを変換すると

Shape を使用します。
また、ループも使用してください。ループは一般に、奇妙なマトリックスの「トリック」よりもはるかに読みやすく、理解しやすいです。
Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプトこんにちは、ジャーモさん
翻訳で失われる可能性のある特殊文字を追加して、この行のいくつかのバージョンをテストしましたが、うまくいきませんでした...
この行は私の側では機能しません(JMP Pro 17 を使用しています)

大丈夫です。このマトリックスを使った最適化は本当に便利です。おっしゃるとおり、ループを使うのも有効なので、それを使ってみます。:)
時間を割いて助けてくださり、改めて感謝いたします (もう一度)!

- 説教者
Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプトコミュニティで問題となるコードの一部をスクリーンショットとして添付しました

これは行列Eの要素ごとの乗算ですMult()
@Ryan_Gilmore JMPコミュニティは食べている:*(: *ここにスペースを追加)
JSL コード ブロック:
m = J(N Items(l) / mcols, mcols) :*</img> (1::mcols);
文章:
m = J(N 項目(l) / mcols, mcols):* (1::mcols);
編集中のスクリーンショット

プレビューからのスクリーンショット

Re: [JSL] 多数のメトリックに対する 2 対 1 側 T 検定のスクリプトこんにちは@Voizingu結局のところ、あなたにはうまくいく解決策があるようです。すばらしい! ただし、それが失われないように、信頼区間は 100(1-2alpha)% 区間にする必要があります。つまり、タイプ 1 のエラー率を 5% にしたい場合、同等性の判断に使用する区間は 90% 信頼区間 (95% ではありません) にする必要があります。これは2 つの片側テストです。各側は alpha = 0.05 でテストされます。添付を参照してください。