[JSL] 针对大量指标进行双单侧 T 检验的脚本大家好,
我想编写一个 JSL 脚本来自动对大量指标(500+)进行 TOST(双向单侧 T 检验)。
TOST 按“级别”对工作,因此使用 2x 级别很容易,因为每个“对”只需要 1x 行。
我已经编写了一个适用于 2x 级别的脚本,通过生成“组合数据表”并向其中添加更多带有公式的列,最终得出结果:“等效”或“不等效”。
当我想要处理超过 2 个级别时,问题变得更加复杂,它需要找到所有可能的唯一“级别”对,然后对每个度量 + 级别对的组合运行 TOST 数学。
我找到了一种方法(在这个论坛上),从列表中找出所有可能的唯一对,并将它们放在表格或嵌套列表中(NchooseKmatrix())。
但我被困在那里。我需要的是:
1- 用所有可能的指标组合(列 1)和所有可能的级别对(列 2 和列 3)填充新表。
2-然后在每行上添加每对级别的统计数据
从这一点开始,我将能够计算出最终确定 TOST 的数学公式。
我附加了一个脚本,该脚本生成一个虚拟表,然后生成一个来自单向分析的组合数据表,然后我尝试创建第三个表,其中包含所有指标 + 唯一级别对的组合,但没有成功
提前感谢您的帮助
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- 传教士
自动化和脚本回复:[JSL] 针对大量指标进行双单侧 T 检验的脚本我附加了一个带有截图的文档“Untitled.png”,以(希望)更好地解释我的请求。
谢谢!
回复:[JSL] 针对大量指标进行双单侧 T 检验的脚本例如,您可以先堆叠您的组列,然后用结果更新它,然后再次拆分它。
此示例没有考虑到可以有多个 Metrics
// 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)
);
或者没有最终的分割,很可能看起来像这样

回复:[JSL] 针对大量指标进行双单侧 T 检验的脚本您好@Voizingu :TOST 只是检查 100(1-2alpha)% 置信区间是否完全包含在某些等价限度内;因此,也许一个适当的解决方法是使用“以 X 拟合 Y”多重比较程序为您完成所有组合?
回复:[JSL] 针对大量指标进行双单侧 T 检验的脚本有什么原因导致您无法使用 Oneway 平台内置的等效性检验?
回复:[JSL] 针对大量指标进行双单侧 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>回复:[JSL] 针对大量指标进行双单侧 T 检验的脚本你好MRB3855,
你说得很好,我不想在第一条消息中放太多信息来关注我的脚本问题,但在我的初始代码(适用于 2 个级别)中,我将等效限值设置为范围 [LSL;USL] 的 5%。
这当然是一个任意值,如果需要我可以更改。
它允许我筛选数百个指标,并根据此标准标记“不等同”指标(通常有十几个)。
然后我可以从这个列表中进行彻底的分析:
- 方差分析
- TOST 具有适当的范围
- ETC...
对于您的第二点,如果我理解正确的话,您建议为每个指标运行 TOST 平台,然后选取数据并通过 Display Box() 放入表中?如果是这样,那确实是一个可行的解决方案,但我更愿意自己进行数学运算以了解 TOST 原理并节省一些处理时间。
希望这是有意义的:)
谢谢你的帮助
- 传教士
回复:[JSL] 针对大量指标进行双单侧 T 检验的脚本你好,马克,
是的,起初我想到使用 TOST 平台并使用 Display Box() 选择统计数据,但我更喜欢采用不同的方法单独计算每个参数以获得与平台给出的相同结果。
事后看来,这也许是一个比重新发明轮子更快的方法,但是我现在已在这上面投入了这么多时间,而且我已经非常接近实现了,所以我还不如完成我开始的事情(虽然很艰难),哈哈!
这样做的一个好处是,我现在了解了 TOST 方法的每个步骤。
谢谢
- 传教士
回复:[JSL] 针对大量指标进行双单侧 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 = 新表(“tabletest”,添加行(5000),新列(“产品”,字符,“名义”,公式(“产品”|| Char(随机整数(1, 4)))),新列(“指标 1”,数字,“连续”,公式(随机正态(10, 1))),新列(“指标 2”,数字,“连续”,公式(随机伽马(10, 1))),新列(“指标 3”,数字,“连续”,公式(随机伽马(10, 2))),);列(dt,“指标 1”)<< 设置属性(“规格限制”,{LSL(5),USL(25),显示限制(0)}); Column(dt, "Metric2") << 设置属性("规格限制", {LSL(0), USL(40), 显示限制(0)}); Column(dt, "Metric3") << 设置属性("规格限制", {LSL(5), USL(40), 显示限制(0)}); SplitBy = "产品"; Summarize(ColumnSplitBy = by(Column(SplitBy))); MetricCols = dt << 获取列名(数字, 连续, "字符串"); ColumnSplitByCombo = As List(NChooseK Matrix(N Items(ColumnSplitBy), 2)); //创建一个带有统计数据的组合数据表(表 2) ow = dt << Oneway( Y(Eval(MetricCols)), X(Eval(SplitBy)), 平均值和标准差(1), SendToReport( Dispatch({"平均值和标准差"}, "标准差下限 95%", NumberColBox, {Visibility("Visible")} ), Dispatch({"平均值和标准差"}, "标准差上限 95%", NumberColBox, {Visibility("Visible")} ) ), Invisible ); tb = Report(ow[1])[Outline Box("平均值和标准差"), Table Box(1)]; dt2 = tb << 制作组合数据表; tb << 关闭窗口; //创建每对级别的嵌套列表 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> 回复:[JSL] 针对大量指标进行双单侧 T 检验的脚本嘿,Jarmo,
感谢您的快速回复。
这条线路出现故障
m = J(N Items(l) / mcols, mcols) (1::mcols);
你能解释一下它的目的是什么吗?
我通常不使用矩阵,我尝试自己调试但却无法......
感谢您的帮助
回复:[JSL] 针对大量指标进行双单侧 T 检验的脚本由于某种原因它丢失了:*
m = J(N Items(l) / mcols, mcols) :*</img> (1 :: mcols);
目的是创建一个这样的矩阵

然后将其转换为

使用形状。
另外,使用循环通常比奇怪的矩阵“技巧”更容易阅读和理解。
回复:[JSL] 针对大量指标进行双单侧 T 检验的脚本嗨,贾莫,
我测试了此行的几个版本,添加了在翻译中可能会丢失的特殊字符,但没有......
这行代码在我这边不起作用(我使用的是 JMP Pro 17)

没关系,使用矩阵进行优化确实很不错。正如你所说,使用循环也有效,所以我会使用它:)
再次感谢您花时间帮助我(再一次)!

- 传教士
回复:[JSL] 针对大量指标进行双单侧 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);
编辑时的截图

预览截图

回复:[JSL] 针对大量指标进行双单侧 T 检验的脚本嗨@Voizingu总而言之,看来你有一个适合自己的解决方案。太棒了!但是,为了不迷失方向,置信区间应该是 100(1-2alpha)% 区间。也就是说,如果你希望你的 1 型错误率为 5%,那么用于判断等价性的区间应该是 90% 置信区间(而不是 95%)。这是一个双单侧检验……每侧的测试值为 alpha = 0.05。见附件,