威廉·鲍姆(沃杰鲍姆),新罕布什尔大学统计学研究生
我的项目是使用 JMP 脚本语言从多个网站提取数据来预测职业足球比赛的胜利。 该脚本自动执行了收集、聚合和重新组织数据以进行分析的繁琐过程。 该脚本的几个部分包含不同的功能,例如消除下标的单元格处理以及多个数据集的串联和连接。 使用关联数组来比较不同行中列公式的输出。 最后,对多个预测模型的结果进行比较。 该项目的目的主要是说明如何使用 JSL 以可重复的方式自动化数据收集、组织和预测的过程。
介绍
大约两年前,我了解到 JMP 可以使用 JMP 脚本语言 [JSL] 从网络上抓取数据。 作为一名统计学研究生,我经常寻找练习数据来磨练我的分析技能并提高我的编码能力。碰巧我是一名狂热的美式足球迷,并且可以从许多不同的来源在线轻松获得体育统计数据。作为一项练习,我尝试使用从网络上抓取的数据来预测每个职业足球队一个赛季的总胜场数。
数据抓取和清理技术可应用于网络上以 html 表格形式提供的任何数据。我发现令人惊奇的是,JSL 可以用于在单个脚本或复合脚本组中自动进行数据清理和执行建模。此外,JMP 还可以帮助那些编程经验有限的用户,让用户能够通过其图形用户界面 [GUI] 进行分析,然后将流程保存为可重复使用的脚本。 当用户使用更新的或新的数据重复分析时,这可以节省大量时间。
设置
第一步是创建文件夹来存储数据聚合过程中创建的文件。我发现为每个数据源创建一个文件夹可以很好地组织生成的许多文件。

接下来,我要求脚本用户为文件存储分配本地路径,以使代码更清晰: dir = Pick Directory(“选择文件存储目录”, show files(0));
该本地路径也可以进行硬编码。
选择路径后,就会从多个网站抓取数据并保存到单独的文件中(每个 HTML 表一个文件)。稍后在数据聚合阶段引用这些文件。
抓取数据
使用 JMP,只需将 URL 名称从浏览器地址栏复制并粘贴到 JSL 代码中即可。还可以直接在脚本中放置指向网站的链接,这有助于在编辑 JSL 代码时打开网站:Web(" http://url_name.com ”);
导入数据
JMP 拥有各种有用的工具来帮助数据导入。首先,可以尝试直接将 html 表另存为 JMP 文件。当数据几乎不需要重组时,此方法效果最佳。第二种方法是首先将 html 表另存为逗号分隔值 [CSV] 文件,然后可以使用通过 JSL 提供的用户定义设置将其导入到 JMP。查看导入的表格后,我注意到有几个空列。使用“删除列”命令,我可以通过一个简短的脚本从表中删除空列。

JMP 自动从网络中提取信息并保存文件。人们不一定需要保存这些文件,但从网络上抓取的数据有时可能会有点混乱。将数据保存到文件中可以更轻松地进行调试,因为可以查看导入的表并根据需要调整代码。
方法一
数据导入并保存为 CSV 文件,最初:
ObjectName = 打开(“http://:url_name1.com”, HTML Table(#))<< 设置名称(“TableName1”) << 保存(dir||“FileName1.csv”);
方法二
数据直接导入 JMP 并保存:
对象名称 = 打开(“ http://url_name2.com” , HTML 表格(#)<< 设置名称(“TableName2”) << 保存(dir||“FileName2.jmp”);

细胞处理
当对脚本中的字符数据进行排序时,即使导入的字符串中的微小变化也可能会弄乱您的代码。在这种情况下,季后赛临近,为了表明新英格兰队已经赢得了分区冠军,他们的名字中插入了一个“z”。 值得庆幸的是,JMP 提供了多种命令来操作单元格内的字符串。

在以下脚本中,JMP 循环遍历“Team”名称列的每一行,并删除指定的字母(如果它们出现在字符串的开头)。“For Each Row”命令可以轻松循环,将进程应用于每一行。条件“if,then”短语告诉 JMP 在特定条件适用时要执行的操作。 “包含”命令返回字符串中指定项目的位置。“Substr”(子字符串)命令返回字符串的一部分:从指定位置开始,返回指定数量的字符。

组合表格
通过“表格”菜单可以轻松组合 JMP 中的表格。表格菜单提供了多个选项。一般来说,我使用“联接”来组合具有不同列但行标签相同的表。 当我组合具有不同行标签但相同列的表时,我使用“连接”。在本例中,我连接了多个表中的信息。为每个部门的团队创建了一张表。接下来,我按团队名称按字母顺序对结果文件的行进行排序,以确保稍后在加入过程中匹配类似的行。

创建一个新表
我发现在连接表之前创建一个新表很有用。JMP 允许用户通过多种方式创建新表。首先,它可以通过 GUI 来完成。也可以通过脚本来完成。在本例中,我使用“新建表”命令创建一个具有适当行数的新表:每个足球队一个。然后,我使用“新列”命令添加团队名称列,并使用列表设置值。

连接表
我发现如果没有 JMP,连接表是一项烦人的任务。值得庆幸的是,JMP 有一个很好的 GUI,用于在“表格”菜单中连接表格。 尽管命名约定始终很重要,但 JMP 会自动重命名来自共享相同名称的不同表的列。在本例中,我通过 GUI 连接表,然后只需将结果表的表脚本复制并粘贴到更大的自定义脚本中。否则,在加入表格之前,我需要进行大量输入(重命名列)。 我多次重复加入过程。

重命名和重新格式化列
一旦连接完成,我就有了很多听起来奇怪的列名。为了消除混乱,我重新命名了这些列。 为此,我首先创建了一个首选名称列表。然后,我使用循环和“设置名称”函数的组合重命名了列。

有时,JMP 将数据作为字符串导入,但用户需要不同的列格式,例如时间。 这在 JMP GUI 中很容易更改,但也可以在 JSL 脚本中完成。在本例中,我让 JMP 知道该列包含连续时间信息,而不是字符信息。
重新组织列
聚合数据并创建新列后,人们可能想要更改数据表中列的顺序。在 JSL 中使用“移动选定列”命令可以轻松完成此操作。

数据表视图
这是已完成的数据表的部分视图。

开发关联数组
完成数据汇总后,就该进行一些分析了。我想要比较的第一件事是不同球队的相对实力,基于他们在赛季中那个时刻的赛程强度。 我的目标是预测一支球队未来的表现有多强,不仅基于他们自己过去的表现,而且还相对于未来对手过去的表现。为此,我必须比较表中不同行和列的单元格中包含的信息。创建关联数组(又名字典或哈希映射)对于此任务非常有用。
在 JMP 中,可以在关联数组中使用列表、矩阵或列。在本例中,我使用了两列,并带有默认值(空)。 键列“TEAM”包含每个球队的城市名称缩写。价值列称为“强度”,是一个计算指数的公式列,结合了胜利和净得分。我使用 17 周比赛时间表的每周(一列)作为键来引用该周的关联数组值。
17 周时间表:关键

在脚本中,我定义了关联数组,然后创建了一个公式列来引用它。同样,该公式使用每周对手作为键,通过关联数组的下标引用正确的值。如果键列中的值不在关联数组中,则该函数返回空值(适用于时间表中的再见周)。

然后我每周创建一个新专栏来比较团队实力。这两个公式可以合并,但我更喜欢将它们分开,这样我就可以可视化数据表中的不同指标。

接下来,我统计了本赛季的预测获胜次数。对列结果进行计数的一种简单方法是创建一个新的公式列,其中包含 17 列中每一列的一系列“If-Then”条件的总和。在这种情况下,如果强度差异为正,则预测被视为胜利并有效。

创建预测模型
JMP 具有多种用于预测的建模技术。许多技术都可以通过“分析”菜单访问,包括“拟合模型”和“神经”平台。创建自定义脚本时,我建议首先在 JMP 平台中开发最佳模型。 然后,可以将模型脚本保存到数据表(通过 GUI),并将代码复制并粘贴到自定义脚本中。还可以使用 JSL 将模型脚本保存到数据表中。这使用户可以灵活地将模型设置为自动运行,或者使模型在自定义脚本创建的表的数据表脚本列表中可用。
这是一个例子。

JMP Pro 中的高级建模技术
JMP Pro 中提供了多种高级建模技术,而 JMP 标准版本中不提供这些技术。两个例子是神经网络的增强版本和弹性网络广义回归技术。JMP 的另一个优点是它能够按照用户指定的比例执行保留验证,自动从数据集中选择随机样本。这简化了验证和模型比较。
增强神经网络

弹性网

有时,多个模型预测的平均值可能优于单个模型的性能。
在这里,我在 JSL 中创建了一个公式列,用于计算两个预测公式的平均值。

JMP Pro有一个模型比较平台,用户可以在其中并排比较多个模型的相对有效性。模型比较平台还使用户只需点击几下即可对多个模型进行平均。
模型比较

在这种情况下,神经网络和弹性网络模型(带有抑制验证 [HB])的平均值比这两个单独模型中的任何一个模型的表现稍好。模型比较平台的另一个不错的功能是“实际预测”和“残差按行”图。
模型比较图

结论
借助 JMP 脚本语言 [JSL],JMP 可以从多个 Web 源抓取数据、处理数据、执行多个预测、比较并显示它们 - 所有这些都在单个脚本中完成。有效使用 JSL 可以节省大量时间,特别是当必须定期重复分析时。