帮助编写一个根据用户选择更新的交互式窗口各位,
我正在编写一个脚本,该脚本将部署到我组织中的用户,以便为用户执行一些简单的快速统计,而无需调用分发平台。 下面的脚本是我目前拥有的截图,然后是我遇到问题的列表。 用户将运行 JMP 16.1,我运行 JMP Pro 16.0。 所有机器都是windows 10、64位机器。
该脚本的预期目的是显示数字列(也许稍后我将处理分类列),并且根据选择的单选按钮,它将执行一些简单的统计并在同一个窗口中显示结果,并在同一个窗口中显示标记为 Stats 的列计算的统计类型和所述计算结果的值。 在选择列面板框中的适当列后,结果面板框应在选择单选按钮时更新。
当前的 JMP 脚本(仅供参考,我正在熟悉的 Big Class.jmp 文件中对其进行测试):
Names Default To Here( 1 );
//Clear Symbols();
//the width of the column list box in pixels
lbWidth = 100;
dt = Current Data Table();
//List of statistics to calculate
StatsListA = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsListB = {"95% quantile", "50% quantile", "5% quantile"};
StatsListC = {};
//Expression to do math
MathA = Expr(
response_col = Column( dt, Eval( Eval Expr( Expr( ycols ) ) ) );
ymean = Col Mean( response_col );
ystdev = Col Std Dev( response_col );
ymin = Col Min( response_col );
ymax = Col Max( response_col );
yrange = ymax - ymin;
yN = Col Number( response_col );
NumResultsA = {ymean, ystdev, ymin, ymax, yrange, yN};
);
//Expresseion for other math
MathB = Expr(
);
ValueDlg = Expr(
nwin = New Window( "GUI for quick stats",
<<RETURN result=""></RETURN>
这是我到目前为止所拥有的:

以下是我遇到问题的清单:
- 对 Radio Box() 的调用列出了局部变量名称“StatsListA”等,而不是实际列出将要计算的统计信息。 例如,第一个单选按钮后面应该有以下列表:Mean、Std Dev、Max、Min、Range、N。这也应该用于 StatsListB 和 StatsListC(我还没有定义 C 列表)。 我不确定如何让它评估我在 JSL 代码顶部制作的预定义列表。 我不想写出每一个项目,因为我可能想要更改列表中的项目,并且更改局部变量 StatsListX 比每次都编辑 Radio Box() 调用更容易。
- 现在,我不想列出所有列,而只列出数字。 当我将 Col List Box() 中的选项从 All 更改为 Numeric(带或不带“”)时,我得到一个空的列列表。 无法弄清楚为什么会发生这种情况,当我定义了该选项时,它应该只列出数字列。
- 这是我认为最难的一个:如前所述,我希望面板框“结果”中的结果在左侧“统计”列中更新(其中列出了来自 StatsListX 的统计信息以及那些的计算结果右列“值”中的统计信息。 每次单击单选按钮时都应更新此信息。 因此,如果您最初查看的是 :height,但想查看 :weight,您可以选择 :weight,然后单击其中一个单选按钮以获取相关的统计摘要。 我尝试按照此处显示的 Set Function 示例进行操作,但没有成功(我不太了解 Set Function 调用)。

MathA 的 Expr() 旨在通过关闭原始窗口并打开一个带有结果的新窗口来调用,但在 JMP 讨论中进行了更多研究后,我发现可以更新现有窗口中的字段,这是我更喜欢解决这个问题的方式。 所以,我知道我代码顶部的原始编码不是我打算做的正确代码。
非常感谢您对此的任何帮助。
谢谢!,
DS
脚本回复:帮助编写一个根据用户选择更新的交互式窗口这太整洁了。 感谢您的讨论。
回复:帮助编写一个根据用户选择更新的交互式窗口大家好,
我要感谢您不断提出的更改建议。 我对脚本进行了一些更改,并且更喜欢最新的修改版本,所以我非常感谢其他人的贡献。 更新后的脚本将在此回复的末尾发布。 这个新脚本还提供字符数据类型的汇总统计信息。 我还稍微修改了面板的布局。
@jthi ,我觉得你的建议很好,我已经采纳了。 我喜欢结果统计的彩色标题名称。 另外,类似于什么@ErraticAttack在他们的代码中,我这样做是为了在选择新列或选择新的数字结果时更新统计信息。 我允许字符统计结果更改其垂直大小,因为可能有很多级别,例如 Big Class.jmp 数据表。 更改为该列类型时,分类统计信息也会更新,但如果选择字符列然后有人单击数字统计选项,则会引发错误。 我确实保留了宽度建议,因此窗口不会不断改变宽度大小。 对不起@ErraticAttack ,此时我对定义新名称空间以及如何修改代码并不熟悉。 它看起来确实非常有用,也是处理事情的好方法,我只需要学习如何正确地做到这一点。
我敢肯定还有其他关于如何改进这一点的建议,尤其是美学。 如果是这样,请发布,但请务必标记我,以便我知道此讨论有更新。 再次感谢大家提出的改进建议。
谢谢!,
DS
下面
//GUI for quickly reporting statistics written by D. Schmidt, ver1.5
//Thanks to JMP User community members: jthi, ian_jmp, and ErraticAttach for helpful suggested changes.
Names Default To Here( 1 );
Clear Symbols();
//the width of the column list box in pixels
lbWidth = 217;
dt = Current Data Table();
//dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
//List of statistics to calculate
StatsList1 = {"µ", "σ", "Max", "Min", "Range(Δ)", "N"};
StatsList2 = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsList3 = {"N", "N Missing", "N 0", "Prop 0", "Prop non-0"};
maxStatCount = Max( N Items( StatsList1 ), N Items( StatsList2 ), N Items( StatsList3 ) );
//RadioBox() arguments
rbArg = Eval List( {Concat Items( StatsList1, ", " ), Concat Items( StatsList2, ", " ), Concat Items( StatsList3, ", " )} );
rbcArg = {"Select for categorical columns"};
//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
Col N Missing( tempCol )
);
statZero = Expr(
N Items( Loc( tempCol << get as matrix, 0 ) )
);
statProp0 = Expr( statZero / statN );
statPropn0 = Expr( 1 - statProp0 );
CatStats = Expr(
coltype = tempCol << Get Data type;
If( coltype == "Character",
catdist = dt << Distribution( Nominal Distribution( Column( tempCol ) ), Invisible );
rpt_catdist = catdist << Report;
lvl = rpt_catdist[String Col Box( 1 )] << Get;
Count = rpt_catdist[Number Col Box( 1 )] << Get;
Prob = rpt_catdist[Number Col Box( 2 )] << Get;
SummNMiss = rpt_catdist[List Box( 7 )][2] << Get Text;
SummLvl = rpt_catdist[List Box( 8 )][1] << Get text;
numNMiss = Num( SummNMiss );
numLvl = Num( SummLvl );
catdist << Close Window;
);
Insert Into( lvl, {"N Missing", "N Levels"} );
Insert Into( Count, numNMiss );
Insert Into( Count, numLvl );
);
//List for results
StatList = Eval List( {StatsList1, StatsList2, StatsList3} );
StatListRes1 = Expr(
Eval List( {statMean, statStd, statMax, statMin, statRange, statN} )
);
StatListRes2 = Expr(
Eval List( {., statQ95, statQ75, statQ50, statQ25, statQ5} )
);
StatListRes3 = Expr(
Eval List( {statN, statMiss, statZero, statProp0, statPropn0} )
);
StatListRes = Expr(
Eval List( {StatListRes1, StatListRes2, StatListRes3} )
);
//User window
ValueDlg = Expr(
nwin = New Window( "GUI for quick stats",
<<RETURN result=""></RETURN>
回复:帮助编写一个根据用户选择更新的交互式窗口你好@jimloughlin ,
我认为那只是一些调试代码@jthi在为我发布的原始代码提供他的建议编辑时正在使用。 我正在发布一个更新的内容,其中考虑了在此线程上撰写的其他人的一些建议编辑。 当我发布更新的脚本时,我会标记你。 我让它与 Big Class.jmp 数据表一起工作得很好。
谢谢!,
DS
回复:帮助编写一个根据用户选择更新的交互式窗口在这里投入我的两分钱。通常最好将脚本尽可能地分成逻辑隔离的单元或函数。为此,我发现从显示树中删除逻辑并尽可能扁平化函数定义要好得多。
在我下面的示例解决方案中,您将看到所有功能都适用于自己命名空间,并且每个函数中的第一行范围自己命名空间。在实践中,我所做的是创建一个自动执行此操作的元编程包装器,这样我就不必显式定义自己命名空间或包括self = 命名空间(“名称”)行作为每个函数的第一个参数。如果您创建了许多交互式 GUI,您可能想要做类似的事情,因为它可以节省大量工作。这还具有不需要将脚本包装在评估(评估表达式(“<代码>”))堵塞。
另外,如果你沿着这条路线走,我发现为内置显示框生成一个包装器最容易,它可以直接调用自己功能,并且不需要在<< 设置函数()消息。
/* quick stats */
self = New Namespace();
self:tool name = "Quick Stats";
Eval( Eval Expr(
self:initialize = Function( {}, // called before the display tree is generated
self = Namespace( Expr( self << Get Name ) );
self:table = Current Data Table();
self:radio inputs = {
"Mean, Std Dev, Max, Min, Range, N",
"Quantiles: 0.05, 0.25, 0.50, 0.75, 0.95",
"N, N Missing, N Zero, Prop 0, Prop non-0"
};
self:stat list = {
{"Mean", "Std Dev", "Max", "Min", "Range", "N"},
{"5%", "25%", "50%", "75%", "95%"},
{"N", "N Missing", "N Zero", "Prop 0", "Prop non-0"}
};
1
);
self:content = Function( {}, // holds the display tree
self = Namespace( Expr( self << Get Name ) );
self:container = H Splitter Box(
V List Box(
H List Box(
Lineup Box( N Col( 1 ), Spacing( 0 ),
Spacer Box( <<SET auto="" stretching=""></SET>self:window << Update Window;
self:finalize();
) );
self << Get Name;
回复:帮助编写一个根据用户选择更新的交互式窗口当我运行 statsstart.jcl 时,我收到以下错误:
名称未解析: tempCol{1} 正在访问或评估 'tempCol' , tempCol/*###*/
也许是因为我正在运行 v13.2.1?
回复:帮助编写一个根据用户选择更新的交互式窗口在你让脚本大部分按你想要的方式工作之后,我会考虑几个视觉方面的事情:
- 表格大小发生变化并使窗口“弹跳”一点
- 如果用户没有选择列,则会出现错误
- 如果没有打开数据表,您可以停止脚本执行并通知用户
- 如果用户更改 Col List Box 中的列,您可能应该使用当前选择的 Radio Box 重新计算统计信息,或者将表格设置为空。
几个想法:
- 对于结果面板框。 您可以使用 Set Widths 来防止表格更改水平大小,并使用预定义的列表大小隐藏占位符 String Col Box 以防止垂直大小更改
- 选择列面板框。 您可以添加 Max Selected(1) 以防止用户选择多个列。
- 选择快速统计面板框。 如果用户没有选择列,则进行某种“错误处理”。
完成一些修改的脚本:
查看更多...Names Default To Here( 1 );
//Clear Symbols(); //dont like using this
If(N Items(Get Data Table List()) == 0,
Throw("No datatables open. Stopping...");
stop();
);
//the width of the column list box in pixels
lbWidth = 205;
dt = Current Data Table();
//dt = Open("$SAMPLE_DATA/Big Class.jmp");
//List of statistics to calculate
StatsList1 = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsList2 = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsList3 = {"N", "N Missing", "N Zero", "Prop 0", "Prop non-0"};
maxStatCount = Max(N Items(StatsList1), N Items(StatsList2), N Items(StatsList3));
//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
Col N Missing( tempCol )
);
statZero = Expr(
N Items( Loc( tempCol << get as matrix, 0 ) )
);
statProp0 = Expr( statZero / statN );
statPropn0 = Expr( 1 - statProp0 );
//RadioBox() argument
rbArg = Eval List( {Concat Items( StatsList1, ", " ), Concat Items( StatsList2, ", " ), Concat Items( StatsList3, ", " )} );
//List for results
StatList = Eval List( {StatsList1, StatsList2, StatsList3} );
StatListRes1 = Expr(
Eval List( {statMean, statStd, statMax, statMin, statRange, statN} )
);
StatListRes2 = Expr(
Eval List( {., statQ95, statQ75, statQ50, statQ25, statQ5} )
);
StatListRes3 = Expr(
Eval List( {statN, statMiss, statZero, statProp0, statPropn0} )
);
StatListRes = Expr(
Eval List( {StatListRes1, StatListRes2, StatListRes3} )
);
//User window
ValueDlg = Expr(
nwin = New Window( "GUI for quick stats",
<<RETURN result=""></RETURN>
回复:帮助编写一个根据用户选择更新的交互式窗口你好@jthi和@ian_jmp ,
谢谢你们的大力帮助! 感谢最后两个提示@jthi ,我能够克服关联数组字母“问题”。 我确实喜欢 AA 的强大功能,我可以看到它们在哪里可以派上用场,但是因为用户的原因,我需要维护一定的秩序。
我能够使用列表建议和您对我遇到的 Count Zero 问题的建议进行更改。 谢谢! 代码按预期工作,现在我需要扩展它以进行分类列,然后调查我的用户以查看他们需要的实际统计列表。
再次感谢你的帮助! 工作代码(至少对于数字列)如下。
谢谢!,
DS
Names Default To Here( 1 );
Clear Symbols();
//the width of the column list box in pixels
lbWidth = 205;
dt = Current Data Table();
//dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
//List of statistics to calculate
StatsList1 = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsList2 = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsList3 = {"N", "N Missing", "N Zero", "Prop 0", "Prop non-0"};
//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
Col N Missing( tempCol )
);
statZero = Expr(
N Items( Loc( tempCol << get as matrix, 0 ) )
);
statProp0 = Expr( statZero / statN );
statPropn0 = Expr( 1 - statProp0 );
//RadioBox() argument
rbArg = Eval List( {Concat Items( StatsList1, ", " ), Concat Items( StatsList2, ", " ), Concat Items( StatsList3, ", " )} );
//List for results
StatList = Eval List( {StatsList1, StatsList2, StatsList3} );
StatListRes1 = Expr(
Eval List( {statMean, statStd, statMax, statMin, statRange, statN} )
);
StatListRes2 = Expr(
Eval List( {., statQ95, statQ75, statQ50, statQ25, statQ5} )
);
StatListRes3 = Expr(
Eval List( {statN, statMiss, statZero, statProp0, statPropn0} )
);
StatListRes = Expr(
Eval List( {StatListRes1, StatListRes2, StatListRes3} )
);
//User window
ValueDlg = Expr(
nwin = New Window( "GUI for quick stats",
<<RETURN result=""></RETURN>回复:帮助编写一个根据用户选择更新的交互式窗口1. 由于使用关联数组,统计数据将重新排序。 您可能只使用列表并修改引用以使用索引
2. 修改计算 0 值的方式可能会起作用。 例如,您可以将示例 Loc() 与 N Items() 一起使用:
statZero = Expr(N Items(Loc(tempCol << get as matrix, 0)));

回复:帮助编写一个根据用户选择更新的交互式窗口你好@jthi和@ian_jmp ,
非常感谢两位的快速反馈! 你的建议很有效,我能够取得更大的进步。 现在我遇到了两个可能非常简单的问题,我在下面包含了更新的代码。 仅供参考,我删除了 :height 中的一些值并在 :height 中添加了一些零来测试它
问题:
- 当它列出统计信息时,它按字母顺序排列,我想保持我在列表中定义的顺序,这可能吗?
- 我试图通过首先计算零的数量来计算零和非零的比例。 不幸的是,它的工作并不完全正确。 我可以将汇总放在 Expr() 中,但是我无法定义关联数组,并且我没有得到正确的后续计算。 我确信有一种更简单的方法可以做到这一点,但我在 JSL 中找不到任何直接命令来只计算零。 我手动输入了 5 个缺失值和 7 个零值。 因此,prop-non-zero 应该是 0.8,prop-zero 应该是 0.2。
Names Default To Here( 1 );
Clear Symbols();
//the width of the column list box in pixels
lbWidth = 205;
dt = Current Data Table();
//dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
//List of statistics to calculate
StatsListA = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsListB = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsListC = {"N", "N Missing", "N Zero", "Prop 0", "Prop non-0"};
//RadioBox() argument
rbArg = Eval List( {Concat Items( StatsListA, ", " ), Concat Items( StatsListB, ", " ), Concat Items( StatsListC, ", " )} );
//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
Col N Missing( tempCol )
);<BR /><BR />//Here's where I'm having trouble with the N Zero and proportions zero and non-zero.
Expr(
Summarize( dt, eg = By( tempCol ), em = Count( tempCol ) )
);
PropTemp1 = Expr(
Associative Array( eg, em )
);
statZero = Expr( PropTemp1["0"] );
statProp0 = Expr( statZero / statN );
statPropn0 = Expr( 1 - statProp0 );
maths = Associative Array();
maths["StatListA"] = Associative Array( StatsListA, {statMean, statStd, statMax, statMin, statRange, statN} );
maths["StatListB"] = Associative Array( StatsListB, {., statQ95, statQ75, statQ50, statQ25, statQ5} );
maths["StatListC"] = Associative Array( StatsListC, {statN, statMiss, statZero, statProp0, statPropn0} );
rbOptions = maths << Get Keys;
//User window
ValueDlg = Expr(
nwin = New Window( "GUI for quick stats",
<<RETURN result=""></RETURN>
再次感谢您迄今为止的帮助,我希望您能在这些小事上提供帮助。
谢谢!,
DS
回复:帮助编写一个根据用户选择更新的交互式窗口关于第 1 点,并在回复中添加一点@jthi , 你可以做:
Names Default To Here( 1 );
//the width of the column list box in pixels
lbWidth = 100;
dt = Open("$SAMPLE_DATA/Big Class.jmp");
//List of statistics to calculate
StatsListA = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsListB = {"95% quantile", "50% quantile", "5% quantile"};
//RadioBox() argument
rbArg = EvalList({ConcatItems(StatsListA, ", "), ConcatItems(StatsListB, ", ")});
//Window
New Window( "GUI for quick stats",
Panel Box( "Select Columns", ColListData = Col List Box( dt, all, <<SET data="https://community.jmp.com/" type=""></SET>
回复:帮助编写一个根据用户选择更新的交互式窗口我做了一些快速测试并附上了脚本。 它有你如何解决这个问题的可能想法,但可能不是最好的解决方案。
1. 处理关联数组和表达式。
2. 不得不为此使用一些奇怪的语法 ColListData = Col List Box(dt, All, <
3. Set Function 正在使用 Evals 处理这个问题。
附加的脚本将给出我现在如何处理这个问题的最佳想法。
