在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本节书摘来自华章计算机《数据科学R语言实践:面向计算推理与问题求解的案例研究法》一书中的第2章,第2.2节,作者:[美] 德博拉·诺兰(Deborah Nolan) 邓肯·坦普·朗(Duncan Temple Lang) 更多章节内容可以访问云栖社区“华章计算机”公众号查看。 2.2 将比赛结果表读入R中我们在这一节的目标是将比赛结果的原始文本表转换成可以在R中分析的数据。这些表已经从网站上被下载下来,并被存储到以1999.txt,…,2012.txt命名的文件中,男子组成绩的存储目录名为MenTxt,女子组成绩的存储目录名为WomenTxt。从网页上下载并抽取表格的任务在2.7节中处理。如果你想从“起始点”开始这个项目,可以先跳到那一节,然后从互联网中获得文本文件之后再返回来。 注意跳过文件中前8行的原因是,我们在图2-2中观察到这些都是文件的头部。 2012年男子组成绩表的前10行是 图2-2 2012年男子组比赛结果截图。该截图按比赛顺序显示了2012年樱花10英里公路赛男子组的比赛结果。注意到表中有5英里时间和净时间,通过表头的说明我们知道Time列是净时间 图2-3 男子组2011年比赛结果截图。该截图按比赛顺序显示了2011年樱花公路赛男子组的比赛结果。注意在2011年,记录了三个时间—完成前5英里的时间、全程的比赛时间和净时间。相比之下,2012年的结果中没有提供比赛时间 同时我们读入并显示2011年男子组比赛结果的前10行,这样就有了另一个可以与2012年进行对比的表。我们发现如下结果: 通过这个简单的检查可以发现什么? 注意一种对正则表达式和grep()函数的替代方法是使用substr()从每一行中提取前3个字符,并与字符串“===”比较。方法如下: 选择3个‘=’字符在某种程度上有些武断。如果等号标识没有在文档的其他地方出现,我们就可以仅使用一个等号。 我们的下一个任务是从body中的每个字符串提取各种信息,也就是表的内容。如何能够提取参赛选手的年龄?通过检查我们知道,一个选手的年龄出现在标签为Ag或AG的列,所以首先要把列名称转换为小写,这样就不必分别搜索Ag和AG。我们使用tolower()来实现它: 可以通过如下方法在headerRow中搜索这两个字母的序列: regexpr()的返回值告诉我们在字符串的第49个位置上发现了一个匹配项。如果没有找到匹配项,regexpr()将返回-1。现在我们知道有关参赛选手年龄的位置信息:它始于表中每一行的第49位,并在第50个位置结束。利用这些信息,我们使用substr()函数提取每位参赛选手的年龄如下: 现在看来我们已经正确定位了选手的年龄。在2012年男子组参赛选手中最年轻的为9岁,最年长的为89岁,并且有一位选手没有年龄记录。 这里gregexpr()中的g代表“全局”,它是指函数在字符串中搜索多个匹配,而不仅仅是第一个匹配。我们在第6行、18行、25行、48行、51行等位置都找到了空格。 我们可以使用substr()函数提取出所有的列: 我们把查找列的开始和结束位置的任务封装到一个函数中,将函数命名为findCol-Locs()。在该函数中,为了防止‘=’字符行中的最后一个字符不是空格,我们在位置向量的末尾处附加一个元素,该元素在字符串长度加1的位置。该函数如下: 我们可以从2012年文件中提取全部10个数据列的值,但是需要保存所有的这些变量吗?需要保存14年文件中的所有变量合集吗?还是只需要使用其中的一个子集呢?现在,我们提取姓名、年龄、居住地和全部3个时间,即比赛时间、净时间和终场时间,而忽略其余变量,如地点、区段、5英里跑步时间等。我们把提取所需列位置的代码封装成一个函数,我们需要所要提取列的名称、包含这些列名的首行和分隔符行中的空格位置,作为函数输入。该函数如下: 注意以上函数是一个调用sapply()的简单封装。而该封装可以使我们很容易地使用单独的列名来测试代码,并提取列的一个子集。例如,我们可以使用下面的代码找到年龄变量: 相较之前的方法,这是一个更通用的提取方法。 另外,如果文件中没有某个想要的变量,那么就将该变量的值赋值为NA。可以提前预判这种情况,因为我们已经注意到在2011年的文件中有比赛时间和净时间,但是没有终场时间,而在2012年的文件中,有被标记为时间的列,但是没有比赛时间或净时间。 下面检查返回值。首先我们用如下方式检查返回值的类型: 输出结果形成一个字符串矩阵(我们还没有转换任何值,例如将年龄转换为数值型)。我们看到矩阵的前几行如下: 2012年的表中有时间的列但是没有比赛时间和净时间,所以比赛时间和净时间的值都是NA。另外检查最后的几行: 这里看到一个参赛选手没有年龄记录。以上结果表明我们已经成功地从MenTxt/2012.txt的表中获取了信息。 我们准备为每年的数据创建数据框,但是extractVariables()函数希望传递给它的待抽取文件是一个字符向量。因此首先必须把表中的行读到R中,操作如下: 类似地,我们可以将女子组的比赛结果读到womenFiles中。这两个对象,menFiles和womenFiles是两个列表,每个列表包含14个字符向量,每个向量表示一年的结果。每个字符向量都包含对应文件中所有行的字符串。 可以看出我们得到了矩阵中行数的合理取值。我们的下一个任务是将这些特征矩阵转换成便于分析的格式。在完成这一任务的过程中,我们使用统计的方法检查结果,并发现额外的数据清洗是必要的。这便是下一节的主题。 |
请发表评论