使用矩阵

这个演示将展示一些矩阵的使用方法。在课程日志的“固化时间数据”部分,我将点击“固化时间数据”。假设我们需要计算每个日期的平均固化时间。我们将每行的所有固化时间值相加,然后除以样本数量。我将使用矩阵来执行此计算。同样,这些向量化运算将提高效率。回到课程日志,我有一个预先编写的脚本,名为“使用矩阵计算统计数据”。让我移动它,以便我们可以看到“固化时间表”(我们甚至会把它弄得更宽一些)和我们的脚本。脚本首先创建一个名为 s 的变量。s 将存储 J 函数的结果。J 函数会创建一个具有指定行数、指定列数和起始值的矩阵。在本例中,我使用不带参数的 Nrow 函数。所以它只会查看当前数据表中的行数。所以我运行一行。你可以在日志中看到,现在存储在s中的是一个全零的列向量。我将使用它来就地添加每个固化时间值。所以我使用了一个for循环。我初始化c等于,因为对于固化时间数据,我想从第二列开始。我测试c是否小于或等于列数。同样,最佳实践是,尤其是在处理更大的数据表时,在for循环之外进行计数,将其存储在一个变量中,然后将c与该变量进行比较。接下来,解析器会评估for循环的主体。所以我们首先看一下赋值函数的右侧。所以我首先将消息get作为矩阵发送到列,然后将其就地添加到s中。然后我们使用后置增量运算符更新c。这样就将c就地加一。我们进行测试以确保 c 仍然小于或等于列数。现在我们将列作为矩阵并将其添加到 s 中。所以我将继续运行行并记住 for 函数将缺失值返回到对数。但您可以将鼠标悬停在 s 上以查看它现在包含这些相当大的数字,即所有五个固化时间列的总和。最后,我将向当前数据表发送一条消息,即新列消息。新列的标题将是平均值。对于值——再次强调,这可以是设置值或值——我实际上将进行计算。因此,我再次向值参数提供函数,而不必先创建变量来存储它们。所以这里的函数——我有一个除法函数和一个减法函数。我取 s,即固化时间各列的总和,然后将其除以 c - 之所以除以 c - 是因为我们开始计算 c 的位置,这样就从我们加起来的项目数中减去一个。当然,c 必须通过测试才能增加。它必须未通过测试。因此,c 的最终值——我可以将鼠标悬停在上面并看到它是,但是,我们实际上只添加了项目。这就是为什么我们要除以 c - 所以我将继续运行最后一行。您可以看到在固化时间数据表中已创建平均值列。并且在日志中显示,您可以看到我已经创建了一个列对象的实例。实际上,如果我想继续使用该列,则可以将结果分配给一个变量。现在,对于演示的下一步,我想一次处理所有固化时间数据并执行计算。因此,我将以矩阵形式提取整个数据表,而不是像在这个预先编写的脚本中那样一次提取一列。在此之前,我想删除刚刚创建的列。因此,我将选择“脚本编辑器”窗口的所有内容。然后,我将向当前数据表发送一条消息,删除列。我要删除的列名为“平均值”。再次强调,在测试或演示时,使用当前数据表非常方便。在生产脚本中,我们确实希望使用对表格更明确的引用。因此,在练习编写脚本时,使用当前数据表会很方便,只需测试一下工作原理即可。但在实践中,如果您计划部署或使用一个脚本,并且希望在多个 JMP 版本以及多种使用情况下进行维护,我们希望使用明确的数据表引用,而不是当前数据表。因此,我将继续运行这个脚本。这样就删除了我想要删除的列。将那条可编写脚本的消息返回到日志中。现在,让我清空脚本编辑器窗口的内容。我将把整个数据表提取为一个矩阵,并将其存储在变量 m 中。因此,m 将被赋值为向当前数据表发送消息的结果。这条消息是 get as matrix。我将运行它。您可以在日志中看到,或者您可以将鼠标悬停在 m 上,我现在得到了这个矩阵。第一列是一些非常大的数字。当然,这是因为当我将 get as matrix 发送到数据表时,它会提取所有数字列。这包括日期。所以这里的日期被视为数字。您可以通过建模类型图标来判断,因为它是连续的。数据类型必须是数字。实际上,如果我把它弄宽,即使日期看起来包含字符,那也只是格式化。所以它是右对齐的,因为它是一个数字。因此 get as matrix 也提取了该值。如果我想计算固化时间——事实上,我想要计算的是找出最小值和最大值——我不希望矩阵中出现当天的大值。所以我要换行。我会小心操作。我希望保留我已经在窗口中显示的代码,但我不想把整个过程都运行一遍。所以我会非常小心地一次运行一行。为了去掉第一列,我将使用变量 m,并用 0 和 1 作为下标。如果你还记得的话,下标的意思是,不要选择任何特定的行。换句话说,给我第一列的所有行。我将为它分配一个空矩阵,也就是方括号,里面什么都没有。同样,如果只运行这一行,我可以高亮显示该行,并使用我们运行整个脚本时使用的任何方法。但它只会运行选定或突出显示的部分。或者,在标准桌面键盘的数字键盘上,我可以使用最右侧的 Enter 键。因此,返回到日志的只是一个空矩阵。但是,如果我现在将鼠标悬停在 m 上,或者我突出显示 m 并运行它,您会看到我们现在只有固化时间值。我们已经删除了包含那些大日期数字的第一列。我将换行查看其他一些可以使用的矩阵函数。因此,我将创建一个变量 a,并将使用 loc 函数 LOC 的结果赋值给它。我将在这个矩阵 m 中找出值大于的位置。当我只运行这一行时,我们将矩阵 m 视为一个行向量,从第一个位置开始计数,然后返回矩阵中所有大于的元素的位置(单个下标位置)。现在,如果我想要实际值,我将创建一个名为 avals 的变量。我要对存储在m中的矩阵用变量a下标的结果进行签名。然后我只运行这一行。实际的固化时间值超过了……当然,为了简化这个脚本,如果我不需要存储所有这些值的位置,我实际上可以简单地用loc函数对矩阵m进行下标——让我复制一下这个。我不需要这个额外的步骤来存储位置,然后再使用它,除非我有其他原因需要处理我最初在这个例子中存储在a中的位置。所以接下来我要对这个矩阵进行的操作是计算一些变换值。这个变换是将每个固化时间的观测值减去整个表中的最小值,除以最大到最小固化时间值的范围,然后乘以……这有点像将每个观测值与最小固化时间的距离作为范围的比例。这说明了使用矩阵的另一个优势。为了找到整个数据表的最小值,无论我是编写脚本还是以交互方式工作,处理数据表中的各个列都需要很多步骤才能找到最小值或最大值。但是使用矩阵,我可以用一行很短的代码完成。所以在我的脚本编辑器窗口中——让我继续,现在清除内容——我将创建一个变量 minCT——也就是最小固化时间,并将使用以 m 为参数的 min 函数的结果赋给该变量。我将继续运行该行。所以最小值是 然后我还将创建一个变量 maxCT。我将使用以 m 为参数的 max 函数的结果赋给它。我只运行该行。就是这样 现在我可以使用这些变量来计算这个变换了。我将创建一个变量 t,来存储变换值。让我换行。因此,t 将被赋值为时间的结果,然后用括号表示分子 m 减去 minCT,用括号表示除法符号,然后用括号表示分母 maxCT 减去 minCT。这样,我只需运行这一行,就能得到这些变换值。每个观测值减去最小值,作为固化时间值范围的比例。现在,小数位数很多。我们实际上没有那么高的精度。所以我们实际上可以对这些值进行四舍五入。然后我再换一行。我将通过将 round 函数的结果赋值回 t 来覆盖 t 中的值。如果您想保留原始值,也可以在新变量中执行此操作。但我要输入 t,然后输入赋值运算符,即 round 函数。参数是:首先,我要四舍五入什么?所以我要对 t 中存储的值进行四舍五入。然后,我想要多少位小数?我想要零。现在,这将截断矩阵中的值。这与将数据列格式化为只有零位小数(完整值仍存储在后台)不同。所以我这里不是格式化,而是截断值。我继续运行它。现在我得到了转换后的整数值。现在,如果您想将这些值放回固化时间数据表中,您可以循环遍历矩阵并创建新列。如果我只想创建一个全新的数据表,可以使用一个名为 as table 的非常简单的函数。它有一些可选参数用于命名此表和列。为了便于演示,我将使用变量 t 作为 as table 的参数。运行该函数时,我会得到一个带有通用列名的无标题表。但该转换矩阵中的所有值都填充到了此表中。同样,我可以将名称和列标题指定为 as table 参数的一部分。或者,我可以使用脚本在事后进行修改。因此,我们研究了几种从数据表中提取数值的不同方法,可以按列或整个数据表、所有数字列、整个数据表,以及我们可以对矩阵进行的一些操作。