今年早些时候,我的经理给我发了一篇来自 Data Colada 的非常有趣的文章,这是一篇由三位行为科学家撰写的博客文章,研究已发表的研究。 Data Colada 的作者与一组匿名研究人员合作,在 2012 年论文中使用的汽车里程数据集中发现了一些奇怪的异常现象。我负责测试JMP中的探索模式平台,该平台可用于识别数据中异常或意外的模式。在这篇文章中,我使用探索模式以及 JMP 中的其他有用工具来搜索汽车里程数据中的意外或异常模式。
背景
汽车里程数据集的前几行和前几列如下所示。这些数据是从一项研究中收集的,该研究要求特定汽车保险机构的 13,488 名客户报告他们当前的里程表读数。客户报告的读数作为 update_car1 到 update_car4 列包含在数据中,因为每个客户最多报告四辆车的信息。该数据还包含首次签发保险单时每辆车的里程表读数。这些列被命名为baseline_car1 到baseline_car4。由于所有政策并非同时发布,因此本研究中观察到的从基线到更新所花费的时间各不相同。

在 Data Colada 帖子中,研究人员提出了在此数据集中发现的四个异常现象。让我们使用 JMP 深入研究这些发现。
异常#1:行驶里程的分布是均匀的
Data Colada 的作者发现,行驶里程的分布与 0 到 50,000 英里范围内的均匀分布一致。
由于数据包括每辆车里程表读数的基线和更新列,因此我们创建公式列来通过从更新值中减去基线值来存储行驶里程。然后,在 JMP 中,我们使用分布平台查看基线和更新值的分布,以及每辆车的总行驶里程。考虑每个客户的第一辆车的分配报告。

基线里程的分布形状与更新里程的分布相似,更新时里程表的中位数读数高出约 26,000 英里。这一发现本身并不令人惊讶。我发现基线和更新读数最有趣的是,两名参与者拥有的车辆已经行驶了近 100 万英里!他们必须拥有非常好的机械技术。
报告中最令人震惊的部分是上面的第三个分布,显示了前两个分布之间的差异。基线时间和更新时间之间的行驶里程分布似乎均匀分布在 0 到 50,000 英里之间。没有超过 50,000 英里的值,并且直方图的每个箱包含大约相同数量的参与者。在这种情况下,目视检查提供了数据均匀分布的有力证据。但是,对于不那么明显的数据,您可以使用分布平台中的 Fit Beta 选项执行拟合优度检验。
下面的屏幕截图显示了每辆参与者汽车的行驶里程分布(更新 - 基线)。我们发现第二、第三和第四辆车的每个分布也均匀分布在 0 到 50,000 之间。根据这种分布模式,我们可以得出结论,更新的里程值可以通过将均匀分布的随机值添加到基线里程值来生成。

异常#2:基线里程使用四舍五入,而更新里程则不四舍五入
Data Colada 的作者发现,基线里程中有许多值四舍五入到最接近的千位,而更新的里程不包含这种四舍五入。
Data Colada 的研究人员通过查看里程的最后三位数字来研究四舍五入的情况。我们可以使用 JSL 来采取类似的方法,但让我们使用 Explore Patterns!如果您以前从未使用过“探索模式”,则可以通过选择“分析”>“筛选”来找到它。

在我们启动探索模式来探索每个基线和更新列后,我们得到以下屏幕截图中所示的输出。在“单变量模式”报告中,选择第一辆汽车的基线和更新值以比较模式。

默认情况下,探索模式包括每列中重复次数最多的值、每列中最长的运行以及每列中最长的重复序列的报告。对于参与者拥有的第一辆车,从最长运行或最长重复序列报告中没有太多收获。然而,“最重复值”报告显示了一个有趣的对比。在第一辆拥有的汽车的基准里程中,有许多值似乎四舍五入到最接近的 10,000。这不一定是一个意想不到的模式;当我被问到我的车的里程数时,我总是绕着圈子回答。
更新里程的最重复值报告有很大不同。在此报告中,重复项要少得多,并且出现的重复项不像基线值那样进行四舍五入。如果通过将均匀分布的随机值添加到基线值来生成更新列,就会发生这种情况。因此,这一发现与异常#1 一致。
异常 #3 – 数据以两种字体输入,每个观察结果都有一个使用另一种字体的“双胞胎”
研究人员注意到,在原始数据文件中,观察结果是使用两种不同的字体记录的。通过一些巧妙的排序,研究人员发现一种字体中的每个基线观察对应于另一种字体中非常相似的行。
我赞扬研究人员注意到不同的字体并采取这种方法。但是,假设数据全部采用相同的字体,并且没有出现此危险信号。我们可以使用 JMP 来识别行和列之间的任何奇怪关系吗?我们当然可以——毕竟这是 JMP 博客。
我们可以使用探索模式来调查连续行的列之间是否存在任何线性关系。考虑以下简单示例。在前四行中,各列具有精确的线性关系,其中 Y=2*X。在接下来的三行中,两列再次具有精确的线性关系,其中 Y=0.5*X。

我们可以使用探索模式来搜索基线列之间的线性关系。如果我们还没有注意到异常#1,那么在更新的列中寻找线性关系也是有意义的。

如果存在许多精确的线性关系,或者可能存在大量线性关系,则可能表明一列中的值是使用另一列的倍数生成的。这里,只有几行的基线列具有精确的线性关系。我们可以使用“着色”选项来查看这些单元格并检查是否有任何不规则之处,但对于具有许多舍入值的这种大小的数据集,找到一些线性关系并不奇怪。
使用探索模式,我们调查了基线值的两列的行之间是否存在任何可疑的线性关系。然而,结果并不是很有用。现在,我们还寻找两行之间的列之间的线性关系,同样是基线值。为此,我们需要在数据转置上使用探索模式。
对于报告至少三辆车里程的参与者,我使用 JMP 中的转置选项按基线列转置数据。我排除了参与者拥有两辆或更少汽车的行,因为这些行无助于识别线性关系。

在此转置数据的“探索模式”报告中,存在许多斜率约为 1 的精确线性关系。因此,原始数据表中的许多行在汽车上具有几乎双行的基线值。 (提示:您可以右键单击“斜率”列,然后使用“选择位置”功能突出显示斜率接近 1 的所有行。斜率介于 0.99 和 1.01 之间的行有 69 对)。

您可以选择线性关系表上方的“着色”,以对精确线性关系中的所有值进行着色,也可以右键单击 Y 列对特定值进行着色。下表包含线性关系报告前三行的彩色值。

探索模式已经确定了几对“驾驶双胞胎”,其中所有汽车的基线里程值都非常相似,具有精确的线性关系。我们可以通过寻找更多不具有精确线性关系但仍然非常密切相关的对来跟进这一点。正如 Data Colada 帖子中所示,一旦您按第四辆车的基线值排序,就很容易识别出许多驾驶双胞胎。
异常 #4 – 一种字体具有许多舍入基线值,而另一种则没有
研究人员发现,Calibri 字体中的基线值进行了四舍五入,而 Cambria 字体中的值则没有四舍五入。
现在,假设我们知道某些行是用一种字体编写的,其他行是用第二种字体编写的,并且我们的数据中有一个列,其中每行都有该字体。我们可以使用“探索模式”,并将字体名称作为“按”列。

正如探索模式报告中所见,Calibri 字体行的基线里程值有许多舍入值,而 Cambria 行的基线值没有舍入。由于我们希望客户报告的里程进行四舍五入,这表明原始报告值是带有 Calibri 字体的行,并且创建了“驾驶双胞胎”数据,然后以 Cambria 字体输入。
结论
每当您获取新的数据集时,您可能会进行一些探索性分析和数据清理。也许您搜索异常值、 检查数据中是否有缺失值或查看每个变量的分布。我希望这篇文章鼓励您考虑使用探索模式来检查数据中的异常模式。并非您使用探索模式找到的所有模式都是错误或令人担忧的证据,但该实用程序为您提供了一个工具来查找值得进一步调查的模式。
你好@madhu 。 感谢您提出这个问题,我将分享两个解决方案,使转置数据表的列标题使用这种格式。
首先,您可以在原始数据表中创建一个新列,该列使用下面屏幕截图中所示的公式。

创建此列后,您可以在执行转置时将其用作标签列。

由于您已经创建了转置数据表,因此您可以使用的第二个选项是使用 JSL 编辑列标题。 为此,请打开转置数据表,然后选择文件 > 新建 > 脚本并将下面的脚本粘贴到脚本编辑器窗口中。 运行此脚本会将列标题更新为所需的格式。
dt = Data Table("Transpose of Car Mileage Data");
colNames = dt << Get Column Names(string);
For(i=2, i <= Length(colNames), i++,
Column(dt, i) << Set Name("id=" || char(colNames[i]))
);
我希望这有帮助。 再次感谢您的评论。
你好@jacob_rhyne
谢谢您的指导。 我现在已经创建了转置矩阵。
在这个练习中我唯一不能做的就是一次性更改列标题 id=12、id=23、id=36 等。 我需要手动更改每个列名称吗? 我想使用一个添加 id= 的公式来一次性替换所有列标题。
你好@madhu 。 您可以在“行”>“行选择”>“选择位置”下找到“选择位置”。

但是,如果您想以交互方式使用 JMP 来选择这些行,而不是使用 JSL,我建议添加一个新列并创建一个公式来标识这些行。 为此,请尝试执行以下步骤。
- 从顶部菜单中选择列 > 新列...
- 在“新建列”菜单中,选择“列属性”>“公式”
- 在公式编辑器中,输入如下公式

输入公式后,单击确定以创建列。 在新列中,值为 1 的行对应于拥有三辆或更多汽车的参与者。 您可以通过右键单击值为 1 的行并单击“选择匹配单元格”来选择值为 1 的所有行,如下所示。

对于有关使用 JSL 执行此操作的问题,一个很好的起点是查看增强日志以查找为您交互执行的操作生成的 JSL。 例如,下面的屏幕截图显示了打开附加到此页面的数据表、创建上述新公式列并使用所选行转置数据后的日志。 您可以将日志中的脚本保存到可以随时再次运行的新脚本。

我希望这是有帮助的。 再次感谢您的阅读。
你好@jacob_rhyne
感谢您的及时答复。 我是 JMP 新手(使用 JMP 16 Pro),对 JMP 不太了解。 不幸的是,我没有找到选择JMP 菜单上任意位置的功能。
另外,有没有办法在数据文件中插入JSL代码以自动执行代码?
你好@madhu感谢您的阅读和提问。 要识别报告至少三辆车里程的参与者,您可以使用 JMP 的“选择位置”功能来选择这些行。 然后在转置数据时,您可以选择仅使用选定的行。 下面是一个 JSL 脚本,它为拥有三辆或更多汽车的所有参与者选择行,然后仅使用选定的行转置数据。
Data Table( "Car Mileage Data" ) << Select Where(
Sum(Is Missing(:baseline_car1),
Is Missing(:baseline_car2),
Is Missing(:baseline_car3),
Is Missing(:baseline_car4)
) <= 1);
Data Table( "Car Mileage Data" ) << Transpose(
columns( :baseline_car1, :baseline_car2, :baseline_car3, :baseline_car4 ),
Transpose selected rows only( 1 ),
Output Table( "Transpose of Car Mileage Data" )
);
要创建汽车里程数数据转置,您如何识别(或挑选)报告了至少三辆车里程数的参与者? 我可以通过检查每一行来手动完成,但是,有什么公式可以使用吗?