JMP脚本语言最常见的用途是自动化工作流程。其次,它可能是从JMP窗口中提取结果。虽然操作简单,但对于新手来说,如何使用脚本实现这一点却并不直观。本文将介绍如何使用统一的显示对象模型构建窗口,并演示如何访问任意窗口中的任何内容。最后,我们将展示几种不同的访问方式。
本文将重点介绍 XPath 查询语言。除了严谨的背景知识外,我们还提供了在编写 JMP 开发单元测试脚本时积累的实用示例。此外,我们还将着重介绍一些交互式 JMP 工具,这些工具能够让您更直接、更轻松地访问 JMP 内容,并分享一些最佳实践。让我们向您展示如何以最佳方式从 JMP 结果中获取所需信息!
大家好,我是 Mark Bailey,我的同事 Tanya Muldon 也在这里。我们今天的演讲题目是“我能看到结果,但如何获取结果?”。我们将探讨一个常见问题。JMP 会在不同的窗口中生成许多不同的结果,有时您可能需要自动化分析、自定义或修改显示内容,甚至提取一些信息用于进一步计算。这就引出了几个问题:我该如何操作?是否有方法可以访问这些结果?是否有工具可以帮助我?最后,在编写 JMP 脚本近四分之一世纪之后,是否有任何最佳实践可以用于此目的?
在正式开始演示之前,我想先说明一点。您可以随时让 JMP 为您的平台保存脚本。您对显示所做的任何修改都会通过平台启动脚本中的“发送到显示”参数自动记录下来。将来当您想要重现该分析及其结果时,可以运行此脚本。
“发送到显示”参数是 JMP 用来记录这些更改的一种机制,但它并非设计用于脚本编写。我们将向您展示 JMP 中真正最佳实践的技巧。
首先,您需要了解,在 JMP 中查看窗口时,实际上看到的是两个协同工作的对象。第一个对象称为分析层,它负责所有计算。您可以通过上下文菜单与分析层进行交互。例如,单击三角形即可进行选择。另一个对象称为报表层,它负责组织和显示分析层的结果。
你想与报表层通信。我们通过对象引用来实现这一点,我们可以向该对象引用发送消息。报表层具有分支树状结构,你最初使用的引用指向该显示树的根节点。每个分支上的节点都是 JMP 显示框。现在的问题是,如何定位或识别要向其发送消息的显示框?我们使用下标来实现。下标位于原始报表层引用后面的方括号内。如果显示框嵌套很深,则可能需要使用多个下标。这些下标可以是连续的,也可以是包含不同显示框列表的单个下标。
下标可以采用多种形式,例如绝对下标、相对下标或条件下标。为了说明这一点,我将举一个非常简单的例子。这里,我打开一个大型 REST 数据表。我向该数据表发送消息 `by variant`,以启动体重与身高的分析。现在,我已经将该引用保存在一个变量对象中,可以向其发送消息了。例如,我发送消息 `fit line`,并将数字设置为 1,以启用该分析,您可以看到结果,即红色的最小二乘拟合线。
但我想要选中显示图表的那个框。我需要通过报告消息向分析层请求该框的引用。我保存了引用。现在我可以给这个引用添加下标,在本例中,“frame box one”就是合适的下标。我们稍后会讲到。然后我可以发送消息“select”。这就是我们使用下标的基本方法。
我们先来谈谈绝对下标。在这种情况下,你使用一个索引来告诉你,在遍历所有这些显示框的分支结构时,应该选择哪个分支。假设我想选择拟合概要中的某一列数字。我从根节点(即给定的引用)开始,然后沿着分支向下遍历。从根节点出发,我依次向下遍历第二个分支、第一个分支、第二个分支,依此类推。最后,我调用 select 方法。
您可以看到这种方法确实有效。绝对脚本虽然有效,但很难编写,也很难阅读。它们还非常不稳定。我的意思是,它们很容易失效,这取决于各种情况,例如您打开的程序、执行某些操作的顺序,当然还有 JMP 本身的更新。我们不推荐使用绝对脚本。
相对形式更容易指定和阅读。在这个例子中,为了找到同一列数字,我先输入报告,然后下标如下所示:我想要大纲框编号 3、表格框编号 1、数字列框编号 1。读到这里,你几乎可以想象出操作过程。结果是一样的,但这种方式更稳定可靠。
第三种方法是使用 XPath 查询语言。在这种情况下,我们将 XPath 消息发送到报表,它接受一个参数,即一个用于查找所需内容的字符串。与前两种方法一样,这种方法的结果也相同,但它更稳定可靠。此外,它功能最强大、最灵活。它会返回所有匹配项的列表,并且该查询语言还支持许多函数和条件逻辑。
此幻灯片展示了该双变量窗口的 XML 文件开头部分。XML 是一种可扩展标记语言。我们不会深入讲解其细节,但其核心思想是,它是一种表示 JMP 窗口的方式,而 XPath 查询语言正是基于这种形式。
JMP 显示树以及 JMP 中的任何窗口都可以使用 XML 来表示。XML 通常是一种用于标记和存储层级数据及属性的方法。JMP 实现了该语言的第一个版本,我们另有一份讲义详细介绍了该语言并提供其他在线资源。
我现在想先介绍一些基本的语法规则,让大家有个概念,然后我会把话筒交给 Tanya,让她给大家展示一些我们如何使用它的实际例子。
XPath 也支持绝对路径,即以一个斜杠开头,后跟要查找的节点名称。要显示连续的节点,可以使用更多的斜杠。但通常来说,这并非 JMP 显示树状结构的最佳方式,因为 JMP 窗口是动态的。
更好的方法是使用相对路径。在这种情况下,我们使用两个斜杠来标识第一个节点。该节点可以出现在显示树中的任何位置,之后可以添加其他节点,最终找到目标节点。这些节点不必相邻,即不必是连续的分支。
第三行是一个简单的例子。搜索字符串是查找包含大纲框的相对路径。这将返回所有位于大纲框中的节点列表,因此功能非常强大。另一方面,您可以使用谓词进行更精确的搜索,在本例中,谓词指的是方括号内的内容。我稍后会详细讲解这些谓词,但这里我们可以进行限定,我们想要的不是所有大纲框,而只是包含标题、摘要或拟合的大纲框。
同样,我们也有通配符,它允许我们指定搜索的部分细节,而不是全部细节。例如,我想查找标题包含“summary”一词的任何大纲框。标题可以是“summary”,也可以是类似“summary of fit”这样的标题。它会找到所有匹配项。我们还可以用它来匹配下一级的所有节点。`Outlinebox/*` 将返回所有大纲框内的所有显示框。
同样,我们不仅可以搜索节点,还可以搜索属性。在本例中,我们要查找所有轮廓框的所有属性。@ 是属性符号,星号表示任意属性。
现在我们再详细谈谈谓词。谓词用方括号括起来。在这个例子中,我们要查找值为“summary of fit”的轮廓框。但我们还可以做更多。在第二行,您可以看到相同的搜索,只是在最后,我们不需要所有数字列框,只需要最后一个。您可以指定这类信息,例如在第三行,我们要搜索前三个轮廓框。我们使用了位置函数,并且它必须小于匹配的值。它不仅可以是关于节点的,还可以是关于该节点的属性。我们可以查找所有宽度大于 10 的文本编辑框。您可以使用这种强大的功能。
在搜索过程中,有时你需要获取某个显示框的引用,或者发送一条消息。但有时你只需要获取节点中的值或属性。举个例子,我们要找到所有访问框,以及每个访问框中的所有文本编辑框。我们不需要返回显示框的引用,而是需要获取该文本框中的值、当前文本等等。最后一行代码需要获取窗口中所有轮廓框的宽度。
最后,我想谈谈 XPath 的坐标轴概念。坐标轴的作用和我之前提到的分支类似,它指的是从一个节点跳转到下一个节点,以及沿途找到的内容,包括向前、向后或向侧查找。第一个例子中,我要找到所有坐标轴框,然后,这里不用指定节点类型,而是用两个句点来表示我想要这些坐标轴框的父节点。
第二行也是一样,我们要查找标题为“平方和”的数字列框,然后找到它的父节点,也就是实际的数字列框。我可以显式声明它们之间的关系。在第三个例子中,我查看第一个图片框,并查找其子元素,该子元素的类型为文本编辑框。
我也可以反过来做。这和这张幻灯片上的第二个例子类似。我要查找一个类型为“T 比率”的数字列框标题,然后我想找到该显示框的父级,类型也是数字列框。你拥有强大的功能和极大的灵活性。通常,一个简单的搜索字符串就足够了,但必要时,你可以使用谓词和我提到的其他一些语法工具。
JMP提供了一些帮助功能。如果您打开帮助菜单并搜索脚本索引,您可以更改浏览器设置以显示显示框,在那里您可以找到所有可用的显示框及其关联的协议,而且所有内容都可以搜索。
此外,如果您右键单击轮廓框前面的灰色三角形,会弹出一个菜单,您可以从中选择“显示显示树”或“显示属性”。这些交互式工具可以帮助您浏览显示树,了解其中的值和属性。这会非常有用。
此外,增强日志是查看搜索结果的绝佳方式,可以帮助您确定是否需要进行任何进一步的修改。JSL 消息中有一个名为“Get XML”的函数。有时您需要查看底层 XML 表示形式,这会很有帮助。另外,JSL 函数“Get Display Path”可以告诉您目标显示框的正确下标形式或 XML 路径形式。
我的讲解就到这里。现在我将把现场演示交给塔尼亚。
谢谢你,马克。我想研究的第一个案例是使用 JSL 来获取报告中显示的值。首先,我需要确定哪个元素包含这些值。一种方法是通过“显示属性”功能。
“显示属性”告诉我,平均值包含在一个数字列框中。这个面板显示了 Mark 之前提到的嵌套或分支树状结构。这个数字列框是表格框的一部分,表格框又是大纲框的一部分,以此类推。
您还会在这里找到这个“路径”框的轮廓节点。这里是 JSL 代码,您可以用来获取名为“mean”的数字列框的引用。默认模式是下标方法。您也可以将其更改为 XPath,JMP 将显示用于获取名为“mean”的数字列框引用的 XPath 代码。
确定信息存储在哪个元素后,接下来需要弄清楚可以向该元素发送哪些命令。一种方法是通过脚本索引。查找“数字列框”时,我们可以发现有多种 GET 消息可以发送给它。这里我将使用“GET 作为矩阵”这条消息。
我将使用几种不同的方法来获取这些信息。第一种方法是将数据发送到我的报表中。RPT 是我的报表层,Mark 之前已经提到过。在我的报表中,我将找到第一个数字列的方框,并将这些值以矩阵的形式获取。我可以在下面的日志中看到这些值。如果我查看我的报表,可以看到它们是相同的值。
接下来,我将使用 XPath 命令来获取相同的信息。这次,我将查找标题为“测量变异性汇总”的大纲框。我将查找标题为“均值”的数字列框,并将其作为矩阵获取。
最后,我将在这里使用一些相对下标。在我的报告中,我将查找测量值的变异性汇总,以及名为“均值”的数字列,并将其作为矩阵获取。
虽然这三种方法都能得到相同的结果,但我们并不推荐使用第一种方法,因为它不够稳定。如果将来 JMP 修改报表,在我前面添加一个数字列,那么运行这段代码就无法得到我预期的结果了。
最后这两个例子都体现了相当稳健的改进。我最后展示的相对论示例比 XPath 示例要短一些。通常情况下,当你只从报告中提取单个元素时,情况就是这样。XPath 的真正优势在于一次性提取多个元素,或者当你使用通配符和谓词进行一些复杂的操作时,例如 Mark 之前提到的那种情况。
我们来看一个更复杂的例子。在这个案例研究中,我们想要提取两个响应的限值汇总信息。这里有两个响应,我们需要获取它们各自的信息。我们可以使用两列的相对下标来实现这一点。
在报表层,我们可以在其下方显示的第一个表格框中查找重量限制汇总信息。然后,我们可以使用第二个命令在第一个表格框中查找重量限制汇总信息并获取该信息。
或者,我们可以使用单个 X 图形命令。在报表图层中,我们可以找到名为“控制图生成器”的轮廓框。您可以在这里看到它。我们可以查找“控制图生成器”下显示的所有表格框,并获取相关信息。
编写这段代码后,我们在日志中看到了比预期多得多的信息。您在这里看到的是报告中显示的表格框,以及一些不可见的表格框。报告中还有其他表格框,例如新增的限制或 Sigma 报告,但我们尚未将这些信息添加到报告层中。我们可以向 XPath 语句中添加一些信息,使其可见。
对于所有这些表格框,我们不仅要查看表格框本身,还要查看它的父级表格框,并判断它们是否可见。在这段代码中,我们检查的是可见性是否为 false,但这里还有一个 not 语句。实际上,我真正想要的是报表中可见的表格框。运行这段代码后,我发现它得到了与之前使用两条语句相同的信息。XPath 让我能够通过一条语句而不是两条语句来获取这些信息。
在接下来的案例研究中,我将创建一个预测分析器,并最大化期望值。我想获取报告中红色的 Y 值和红色的 X 值。由于它们都是坐标轴值,而且都是红色,您可能会认为它们存储在同一个元素中。然而,事实并非如此。
我们可以返回“显示属性”窗口查看这一点。如果我点击对了,可以看到 Y 值实际上是文本框,X 值是数字编辑框。首先,我们来处理这些文本框。我们将通过 XPath 查找预测分析器,然后查找可见的文本框。同样,我们需要添加一些代码来设置可见性,因为报告中有些文本框不可见,我们不想获取这些文本框。
运行这段代码后,我们发现不仅得到了红色数值,还得到了置信区间的蓝色数值,这是因为它们也以文本框的形式存储了。我们可以添加一个 for 循环来遍历每个元素,只提取每隔三个红色数值中的一个,并将这些信息存储在一个矩阵中。
现在我们有了之前用红色显示的 Y 值,但我们还需要之前用红色显示的 X 值。这些值存储在数字编辑框中。我们可以使用 XPath 语句在这些数字编辑框中查找预测分析器,并将这些值以矩阵的形式获取。这些值记录在下面的日志中。
在接下来的案例研究中,我想获取第一个框架框或位置图中每条线的 Y 值,也就是平均直径。查看“显示属性”后,你会发现无法真正进入这个框架框图层。点击这里会显示一个框架框,但我看不到框架框内的内容。我需要知道这些值是如何存储在框架框中的。获取此信息的另一种方法是使用“显示树状结构”。
在“显示树状结构”中,我还可以看到 Mark 之前提到的分支结构。在这个框架框内,我看到有各种各样的线段。我感兴趣的是出现在下面的这些线段。我可以使用 XPath 语句从第一个框架框中获取所有线段。
之前我的所有 XPath 语句都有一个轮廓框节点,但这个没有。在控制图生成器中,它并非必需。即使有多个响应,控制图生成器中的所有图表都会显示在此轮廓框下方。因此,我并不需要它,它并非必要。
运行这段代码后,可以看到有七个元素。我可以选择使用关联数组来获取这些元素对应的 Y 值。运行后,我看到加上平均值后的 Y 值为 4.2,加上下限后的 Y 值为 4.1,依此类推。
接下来的案例研究中,我有三个不同的图表。我希望每个图表的 Y 轴具有相同的最小值和最大值,并为每个图表添加相同的参考线。首先,我需要获取坐标轴框的句柄。我将使用 XPath 查找“拟合组轮廓”节点。然后,我将查找所有可见的坐标轴框。
我看到有六个不同的坐标轴框。有三个图表,每个图表都有一个 X 轴和一个 Y 轴,所以一共六个。我将使用 for 循环来遍历每个坐标轴的值。对于 Y 轴,我将设置最小值和最大值,并添加一条参考线。现在,对于我的三个图表,我都添加了参考线,并将最小值和最大值设置为相同的值。
接下来,我想缩短这份“西格玛能力汇总报告”的显示范围。我只想看到截至 PP 的部分,不想看到 CPM、预期值或观测值。我可以通过 XPath 来实现。我将向报告图层发送一个大纲框命令,查找“西格玛能力汇总报告”。
在获取到报告的相应层级后,我想使用 XPath 选择以“预期”、“观察”或“等于 CPM”开头的标题框。选择完成后,我将发送折叠显示命令。现在我发现这些值已从报告中消失。切勿从报告中删除项目。删除项目可能会导致意想不到的后果。我们建议您折叠或隐藏报告中的内容,而不是删除项目。
我还有最后一个例子。在这个案例研究中,我们将“管理限额”平台放在了一个新窗口中,并且我们希望移除这个帮助按钮。创建 JSL 脚本时,您通常会这样做,因为您想与他人分享结果。因此,您需要确保脚本在您的计算机上的运行情况与在其他人的计算机上的运行情况相同。
Windows 和 Macintosh 系统中按钮的位置通常不同。你不应该根据按钮在报表中的位置来查找它,而应该根据按钮的名称而不是位置来查找。这里我不会深入讲解窗口处理程序代码,但我想让你注意的是这条 XPath 语句。我正在查找名为“帮助”的按钮框,然后将其隐藏。你会看到“帮助”按钮不再显示在这里了。我刚才又点击了一下。我不想把它从报表中删除,因为我不想造成意想不到的后果。
我已经向您展示了三种从报表中获取值的方法。绝对下标并非理想之选,它对数据变化不够稳健。XPath 方法和相对下标则相当可靠。如果您只是从报表中获取单个值,相对下标的代码可能更简洁。XPath 代码适用于一次性获取多个信息,以及需要使用通配符等复杂操作的情况。
希望这些信息对你有所帮助,让你能够回去继续编写剧本。