帮助编写根据用户选择更新的交互式窗口脚本各位,
我正在编写一个脚本,该脚本将部署到我的组织中的用户,以便为用户执行一些简单的快速统计,而无需调用分发平台。 下面的脚本包含我当前拥有的屏幕截图,然后是我遇到问题的列表。 用户将运行 JMP 16.1,我运行 JMP Pro 16.0。 所有机器都是windows 10、64位机器。
该脚本的预期目的是显示数字列(也许稍后我将处理分类列),并且根据选择的单选按钮,它将执行一些简单的统计并在同一窗口中显示结果,并带有标记为“统计”的列用于计算的统计数据类型和所述计算结果的值。 在“选择列”面板框中选择适当的列后,“结果”面板框应根据选择单选按钮进行更新。
当前的 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() 中的选项从“全部”更改为“数字”(带或不带“”)时,我得到一个空的列列表。 无法弄清楚为什么会发生这种情况,当我定义了该选项时它应该只列出数字列。
- 这是我认为最难的一个:如前所述,我希望面板框中“结果”中的结果用左侧“统计”列进行更新(其中列出了 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 = 命名空间(“名称”) line 作为每个函数的第一个参数。如果您创建许多交互式 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' 时存在 tempCol{1},tempCol/*###*/
也许是因为我运行的是 v13.2.1?
回复:帮助编写根据用户选择更新的交互式窗口脚本当你让脚本基本上按照你想要的方式工作后,我会考虑一些视觉上的事情:
- 表格大小发生变化,使窗口有点“弹跳”
- 如果用户没有选择列,则会出现错误
- 如果没有打开数据表,您可以停止脚本执行并通知用户
- 如果用户更改列列表框中的列,您可能应该使用单选框的当前选择重新计算统计数据或将表设置为空。
几个想法:
- 对于结果面板框。 您可以使用设置宽度来防止表格更改水平尺寸,并使用预定义列表尺寸的隐藏占位符字符串列框来防止垂直尺寸更改
- 选择“列”面板框。 您可以添加 Max Selected(1) 以防止用户选择多列。
- 选择“快速统计”面板框。 如果用户没有选择列,则进行某种“错误处理”。
经过一些修改的完整脚本:
查看更多...
回复:帮助编写根据用户选择更新的交互式窗口脚本你好@jthi和@ian_jmp ,
感谢你们两位的大力帮助! 感谢最后两个提示@jthi ,我能够克服关联数组字母“问题”。 我确实喜欢 AA 的力量,我知道它们可以在哪里派上用场,但由于用户的原因,我需要维护一定的顺序。
我能够根据列表建议和您对我遇到的计数零问题的建议进行更改。 谢谢! 该代码按预期工作,现在我需要扩展它以执行分类列,然后调查我的用户以查看他们需要的实际统计信息列表。
再次感谢你的帮助! 工作代码(至少对于数字列)如下。
谢谢!,
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 处理此问题。
随附的脚本将给出我目前如何处理此问题的最佳想法。
