《数据科学R语言实践:面向计算推理与问题求解的案例研究法》一一2.5 为跨年度的个人参赛选手构造记录...

本节书摘来自华章计算机《数据科学R语言实践:面向计算推理与问题求解的案例研究法》一书中的第2章,第2.5节,作者:[美] 德博拉·诺兰(Deborah Nolan)  邓肯·坦普·朗(Duncan Temple Lang)  更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.5 为跨年度的个人参赛选手构造记录

我们需要为参加过多次樱花赛的参赛选手进行记录匹配。由于每位选手的比赛结果没有唯一的标识,因此我们需要从每位参赛选手的信息中构造唯一标识。理想情况下,我们将使用记录的全部信息,即选手的姓名、居住地、年龄、跑步时间和比赛年份。然而,如果这些信息从某一个年份到下一个年份被记录的不一致,可能会减少匹配的条数。另一方面,即使使用全部的信息,我们可能也会错误地匹配来自两个不同运动员的记录。任何设计的方法都不可能完全准确,本节的目的是探讨几种可能的方法,然后确定其中我们认为合理的一个。
现在考虑下列问题:
14年里总共有多少参赛选手?
这些参赛选手中有多少不重复的姓名?
有多少姓名出现两次、三次、四次,等等,最常见的姓名是什么?
一年之内多次出现的姓名的出现频率是多少?
回答以上这些问题可以使我们体会到匹配问题的量级大小。此外,我们可以考虑如何通过清洗name和home的值来提高匹配率。例如,记得前面我们解析文本表格时,在字段末尾附加了一些空格,现在可能是消除它们的好时机。在前面我们也注意到大小写的不一致问题,可以证明匹配记录的不确定性。伴随我们开始进一步仔细检查记录,其他有关清洗字符串的问题也会随之涌现。在回答这些问题之前,我们先来清洗姓名。
任何出现在一个姓名前面或后面的空格都可以被舍弃。此外,如果出现多个空格,例如,在名字和姓氏之间有多个空格,我们可以把它们转换成一个。gsub()函数可以实现这些操作。下面我们创建一个帮助函数,trimBlanks()来完成该工作:

第一次替代消除所有开始的空格,第二次替代消除所有末尾的空格,第三次用一个空格替代多个连续的空格。注意我们使用元字符“[:blank:]”,这样可以找到所有形式的空格,包括制表符。清洗姓名如下:

现在可以开始回答关于姓名唯一性的问题了。我们通过检查概要统计和记录集合来完成该工作。
14次比赛中共有多少参赛选手呢?用length()函数进行查找:

回顾在前面的部分,我们舍弃了那些比赛用时少于30分钟和年龄低于16岁的记录。
那么有多少不重复的姓名呢?

有多少姓名出现一次、两次等?我们可以通过调用两次table()函数来进行判定,也就是

这个表格说明什么呢?我们可以看到14次比赛中有超过7000个姓名出现了两次。有一个姓名出现了30次,而我们知道这个姓名至少对应3个人,因为仅仅有14次的比赛结果。
哪个姓名出现了30次呢?我们可以用如下代码进行查找:

下面来检查关于30个Michael Smith的其他信息。我们从数据框中提取它们:

其居住地包括:

由于额外的空格,这里出现几个不同的Annapolis MD版本。显然我们也需要清洗home字段。
进一步考虑,我们可能会问:可以通过更多的清洗潜在地提高匹配的效率吗?我们已知列标题有大小写不一致的情况,毫无疑问,姓名也存在同样的问题。我们可以检查大小写,但也可以简单地将所有字符变为小写字母:

再次检查最常见的姓名:

通过这次额外清洗又多找到了3个Michael Smith。
此外,可以删除标点符号,例如某人中间名缩写的后面及任意零散的逗号,我们通过调用一次gsub()函数进行处理:

既然有如此多重复的姓名,下面我们计算一个姓名在相同年份中出现的次数。可以创建一个年份-姓名的组合表格:

然后调用max()函数来查找有最大计数值的表格单元,即

这又是Michael Smith吗?还需要通过一些处理找到与这个最大计数值关联的名字。这个存储在tabNameYr里的表格为table类,我们看到它是一个具有3个属性的数值向量:dim、dimnames和class。调用class()、mode()和attributes()函数,可以帮助我们得到以上信息,即

这个数据结构有多重含义。首先,一些矩阵函数可以在table类上进行处理,例如,我们可以调用dim()和colnames()函数进行查找:

注意我们发现了另一条混乱的数据!为了找出是哪个单元中的计数值为5,我们可以使用which()函数,但是要找到行和列的位置,需要在调用中包含arr.ind参数。也就是

最后,对姓名进行定位如下:

它是Michael Brown,不是Michael Smith!
现在我们有了一个清洗过的选手姓名的版本,下面将它添加到我们的数据框中:

我们使用这种格式的姓名去创建唯一的选手标识。
因为我们有选手的年龄和比赛的年份,所以也可以获得选手近似的出生年份。比赛是在每年4月的第一个星期日举行,因此这两者之间的差值是对年龄的一个近似。那些生日在4月开始七天内的参赛选手,有可能对他们年龄的记录在两个比赛年份中是不一致的。可以预知记录的哪些部分会出现这种问题吗?我们在数据框中创建一个新的变量yob:

另外,我们发现在居住地名里也有空格和大小写的问题。这里将对它们的处理留作练习,要求清洗home值,并将清洗过的home版本添加到cbMenSub为homeClean。
下面让我们更加仔细地查看在数据框中的这些新的、清洗过的关于Michael Brown的变量。代码如下:

针对以上各种不同的michael brown行可以得到怎样的观察结果呢?
出生于1953年的3条michael brown记录好像是同一个人,因为他们的居住地都是“north east md”。除此之外,他3场比赛的用时相差不到7分钟。
出生于1958年的4条michael brown记录参加比赛的时间分别是2008年、2009年、2010年和2012年。最近一条记录的居住地登记的是Reston VA,而其他的3个居住地显示为Ashburn VA。那么会有1、2、3或者4个不同的michael brown吗?2010年的该选手是4次比赛中跑得最慢的,差了约11分钟,其他3次更接近一些。互联网搜索显示,Reston和Ashburn相距不到22千米。可以猜想这4条记录属于同一个人,他可能在2010年4月到2012年4月间从Reston搬到了Ashburn,但对此我们并不能完全确定。
另外3条记录中michael brown都出生于1966年。除了在2006年的记录中州名MD没有提供外,3条记录的居住地都是Chevy Chase。当我们检查2006年其他的参赛选手时,发现他们中也没有人列出州名。3条michael brown记录中比赛时间之间也存在11分钟之差,其中在中间年份2010年跑得最快。因此这些记录很可能属于同一个人,但是我们发现2006年记录中的居住地和其他年份的不同。
接下来,还有4条michael brown的记录是出生于1984年,参加比赛的时间分别是2008年、2010年、2011年和2012年。其中,2010年记录中的选手似乎和其他三条记录中的选手不是同一个人,因为他的居住地是New York,NY,且他的跑步时间也比其他三条纪录慢了25~40分钟。其他三条记录的居住地同为Arlington,VA,他们的跑步时间也从2008年的84分钟提升到2012年的71分钟。因此认为这三条记录同属于一个人似乎是合理的,因为一个人随着年龄的增长,他训练和跑步的速度也会更快。而对此我们同样不能完全确定。
最后,我们注意到2012年注册的5条michael brown记录具有不同的出生年份(1953、1958、1966、1984和1988)和5个不同的居住地,因此这是5位不同的参赛选手。
我们总结各种不同的观察结果,并第一次尝试为个体选手创建标识符,然后可能将清洗后的姓名和推导出的出生年份粘合在一起。代码如下:

我们忽略居住地和跑步时间所提供的信息,因此创建了限制最少的标识符。
由于我们的目标是研究一个运动员跑步时间随着年龄增长的变化,下面让我们重点关注那些ID至少出现8次的选手。为了完成这个目标,我们首先判定每个ID在cbMenSub中出现的次数,代码如下:

然后选择那些ID至少出现8次的记录:

我们选择属于这些标识符的记录构建子集menRes:

最后,组织数据框使相同ID的记录相连,这样就使诸如手工检查记录等操作变得更加容易:

另一种数据组织方式是将races8中每一个ID的元素存储为一个列表。该列表中,每个元素是一个数据框且仅包含具有相同ID的记录结果。通过如下代码创建列表:

其中哪种数据结构更好呢?这将取决于我们想如何处理数据。接下来,我们将展示如何使用两种方法来完成一项任务,以便在这两种数据结构之间进行比较。在下一节中,我们会发现使用数据框中的列表进行处理是最容易的,因为我们常常需要将含有多个参数的函数应用于每个参赛选手的记录。
创建列表后还剩下多少个ID呢?

这和代码length(men8L)的功能是一样的。如果两年间的比赛成绩变化太大,我们可能就会放弃记录的匹配。那么多大的起伏变化会让我们认为是错误地连接了两个不同的选手呢?当然,我们不想通过消除跑步时间变化很大的个体而使结果产生偏见。下面让我们查看一些在相邻两年内跑步时间之差超过20分钟的记录。使用如下方法找出那些满足该约束的记录:

或者使用

有多少时间差超过20分钟的选手?

前两位运动员经过稍微重新格式化的显示结果如下:

姓名为abiy zewde的选手似乎非同寻常,很可能是同一个人参加了14次比赛中的12次,虽然有几年居住地改变了,且最近一次年龄为45岁的比赛结果与最快的一次相差了几乎40分钟。事实上,谷歌搜索定位了一个网页http://storage.athlinks.com/racer/results/65866776,发布了他在几次不同比赛中的跑步时间。网页截图如图2-16所示,可以清晰地看到这些记录是属于同一个人的。
image

图2-16 一个参赛选手比赛结果的网页截图。这个网址为http://storage.athlinks.com的网页包含一个选手在14年中的12次参加樱花公路赛的比赛结果数据。注意他最快的跑步时间是在最近的2012年,完成比赛的时间少于85分钟,那时他45岁。而他最慢的时间是2002年的123分钟,那时他35岁
想用同一个居住地来进一步约束我们的匹配项吗?这样可以消除诸如abiy zewde记录中的不同,尽管我们相当确定这些记录是属于同一个人的。我们可以识别不当匹配,并手动检查潜在的错误匹配结果。因为2006年的记录中没有州名,所以我们需要从那些记录项的末尾去除州名的缩写。可以用一个空字符串替换出现在字符串末尾的一个空格及后面跟着的两个字母。例如:

这可能会导致太过自由的匹配,例如,匹配Springfield IL和Springfield MA。在此我们将它留作练习,确定如何将匹配限制到那些具有相同居住地的记录中,并评估是否应该在匹配过程中添加额外的限制条件。
这里,我们考虑一个不太严格的匹配,仅仅匹配那些具有相同居住州的记录。为此,我们创建一个新的变量来保存州名的两个缩写字母。因为数据结构比较简单,我们返回去处理cbMenSub,并保持一致性。从每个居住地的字符串中提取最后2个字母。如果存在,它就是州名。我们知道在2006年的记录中没有出现州名,因此将其设置为NA。对于来自美国以外的运动员,提取国家或者省份的最后两个字母,但这些不应该显著地影响我们的匹配。
首先确定在每个home值中有多少个字母,代码如下:

然后使用如下代码提取最后两个字母,并将它们添加回数据框里:

并且将2006年的值设置为NA:

接下来,我们重新创建一个新的ID以使其包含state,代码如下:

然后,我们再次选择那些至少出现8次的ID。代码如下:

在下一节中,我们将单独使用列表结构来进行处理。
这次添加完选手的ID后,进一步减少了完成8次比赛的选手数量,即

现在有306名运动员具有相同的姓名、出生年份和州名,并且都完成了14次比赛中的8次。迄今为止我们一直在已获得的匹配集合上进行处理,在下一节,我们将研究参赛选手的成绩如何随着年龄增长而变化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/281591.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于 abp 微服务架构的开源低代码平台

你好,这里是 Dotnet 工具箱,定期分享 Dotnet 有趣,实用的工具或组件,希望对您有用!简介 ABP-MicroService是 一个基于ABP vNext微服务架构、vue-element-admin的后台管理框架,适用于大型分布式业务系统和企…

linux android sdk gengxinman,Android 实现增量更新

一、概述增量更新相较于全量更新的好处不言而喻,利用差分算法获得1.0版本到2.0版本的差分包,这样在安装了1.0的设备上只要下载这个差分包就能够完成由1.0-2.0的更新。比如:存在一个1.0版本的apkapk1.png然后需要升级到2.0版本,而2…

Pycharm上Django的使用 Day8

2019独角兽企业重金招聘Python工程师标准>>> 1.添加新条目 1>编写用于添加新条目的表单 在forms.py中创建一个与模型Entry相关联的表单 1处给字段text指定一个空标签 2处定义小部件widgets,widgets是一个HTML表单元素 2>定义new_entry的URL模式 在用于添加新条…

物联网创新领域的三大驱动性趋势

从设备对接到区块链,今天我们将介绍几项物联网开发者必须了解的最新技术趋势。 物联网正在快速改变着我们的工作与生活方式。过去十年以来,利用惟一IP地址实现联网早已不是难事,但传感器、处理器以及其它多种新兴技术的涌现真正让物联网走向了…

TensorFlow.NET 实战 -- 为.NET开发者开启机器学习之旅

在IT技术飞速发展的今天,云计算、人工智能、大数据和云原生应用等新兴技术的发展为我们带来一波又一波的浪潮,也对软件开发者提出了更高的要求,特别是人工智能开发领域,应运而生的新概念让人目不暇接。作为一个.NET开发者的你&…

Arduino I/O Expansion Shield V7.1

介绍: 传感器扩展板,目的是为初学者省去繁琐的面包板接线和故障排除,专注实现自己的创意想法。 扩展板V7.1不仅保留老版本的所有优点,改善了它的易用性,更重要的是它兼容Arduino新一代主控器DUE。现在V7.1以其强大的扩…

简单的单臂路由的配置实验 (思科)

实验名称:简单的单臂路由的 配置实验 (思科)实验拓扑: 实验需要:1、按图中所示配置设网络备vlan,IP地址2、能够使各pc互相ping通。 实验步骤: 1、配置终端设备:pc1-pc5按照拓扑图中所…

【Redis源码分析】Redis命令处理生命周期

运营研发团队 李乐 前言 本文主要讲解服务器处理客户端命令请求的整个流程,包括服务器启动监听,接收命令请求并解析,执行命令请求,返回命令回复等,这也是本文的主题“命令处理的生命周期”。 Redis服务器作为典型的事件…

GDB调试qemu-kvm

GDB调试qemu-kvm 前面几篇博文都是记录一些kvm相关包编译安装及使用,但都没深入去代码看看。看源码在配合上相关原理才能更好的理解kvm。但qemu-kvm的代码量很多,对我来讲直接看源码收获甚少,所以找了个调试工具——GDB来配合阅读代码。接下来…

用.NET设计一个假装黑客的屏幕保护程序

本文主要介绍屏幕保护程序的一些相关知识,以及其在安全方面的用途,同时介绍了如何使用 .NET 开发一款屏幕保护程序,并对核心功能做了介绍,案例代码开源:https://github.com/sangyuxiaowu/HackerScreenSaver背景前几天在…

【IntelliJ】IntelliJ IDEA常用设置及快捷键以及自定义Live templates

IntelliJ IDEA是一款非常优秀的JAVA编辑器,初学都可会对其中的一些做法感到很别扭,刚开始用的时候我也感到很不习惯,在参考了网上一些文章后在这里把我的一些经验写出来,希望初学者能快速适应它,不久你就会感觉到编程是…

c语言时钟报告,C语言图形时钟课程设计实验报告

C语言图形时钟课程设计实验报告 目录1.系统功能要求。2. 数据结构设计及说明。3.程序结构(画流程图) 。4.各模块的功能。5.试验结果(包括输入数据和输出结果) 。6.体会。7.参考文献。8.附录:程序清单及源程序。 系统功能要求:在屏幕上显示一个图形时钟…

微软发布 2023 财年第一季度财报:营收达 501 亿美元,同比增长 11%

北京时间 2022 年 10 月 26 日——微软发布 2023 财年第一季度财报。财报显示,截止到 2022 年 9 月 30 日:营收达到 501 亿美元,增长 11%(按固定汇率计算增长 16%)运营收入为 215 亿美元,增长 6%&#xff0…

《图解CSS3:核心技术与案例实战》——1.3节渐进增强

本节书摘来自华章社区《图解CSS3:核心技术与案例实战》一书中的第1章,第1.3节渐进增强,作者 大漠,更多章节内容可以访问云栖社区“华章社区”公众号查看 1.3 渐进增强第一次听到“渐进增强”(Progressive Enhancement…

阿里云云主机搭建网站攻略 - 云翼计划

阿里云服务器(云主机)搭建网站攻略 - 云翼计划 提示:此搭建攻略为2017版本,阿里云未跟新前。 最新搭建攻略请前往 Amaya丶夜雨博客 / 最新个人博客 https://www.amayaliu.cn 支持一下哦,谢谢。(9.5一…

记一次 .NET 某医疗器械 程序崩溃分析

一:背景 1.讲故事前段时间有位朋友在微信上找到我,说他的程序偶发性崩溃,让我帮忙看下怎么回事,上面给的压力比较大,对于这种偶发性崩溃,比较好的办法就是利用 AEDebug 在程序崩溃的时候自动抽一管血出来&a…

1251: 字母图形 [水题]

1251: 字母图形 [水题] 时间限制: 1 Sec 内存限制: 128 MB提交: 140 解决: 61 统计题目描述 利用字母可以组成一些美丽的图形,下面给出了一个例子: ABCDEFG BABCDEF CBABCDE DCBABCD EDCBABC 这是一个5行7列的图形,请找出这个图形的规律&…

WPF效果第二百零二篇之TreeView带连接线

前面文章中分享了TreeView支持多选;然而在项目上使用时,领导觉得不满意:体现不了真正的从属关系;既然领导都发话了;那就开整就行了;今天就再来个带有连接线的TreeView效果:1、来看看TreeViewItem的Template:2、展开和收缩动画:3、参考资料https://www.codeproject.com/tips/673…

ObjectTive C语言语法,[译]理解 Objective-C 运行时(下篇)

本文来自网易云社区作者:宋申易所以到底 objc_msgSend 发生了什么?很多事情。看一下这段代码:[self printMessageWithString:"Hello World!"];这实际上被编译器翻译成:objc_msgSend(self, selector(printMessageWithStr…

菜鸟学习MVC实录:弄清项目各类库的作用和用法

MVC模式即:模型(Model)-视图(View)-控制器(Controller) Model (模型):是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责数据库中存取数据View…