《数据科学R语言实践:面向计算推理与问题求解的案例研究法》一一2.5 为跨年度的个人参赛选手构造记录...
本節(jié)書摘來自華章計算機(jī)《數(shù)據(jù)科學(xué)R語言實踐:面向計算推理與問題求解的案例研究法》一書中的第2章,第2.5節(jié),作者:[美] 德博拉·諾蘭(Deborah Nolan) 鄧肯·坦普·朗(Duncan Temple Lang) 更多章節(jié)內(nèi)容可以訪問云棲社區(qū)“華章計算機(jī)”公眾號查看。
2.5 為跨年度的個人參賽選手構(gòu)造記錄
我們需要為參加過多次櫻花賽的參賽選手進(jìn)行記錄匹配。由于每位選手的比賽結(jié)果沒有唯一的標(biāo)識,因此我們需要從每位參賽選手的信息中構(gòu)造唯一標(biāo)識。理想情況下,我們將使用記錄的全部信息,即選手的姓名、居住地、年齡、跑步時間和比賽年份。然而,如果這些信息從某一個年份到下一個年份被記錄的不一致,可能會減少匹配的條數(shù)。另一方面,即使使用全部的信息,我們可能也會錯誤地匹配來自兩個不同運(yùn)動員的記錄。任何設(shè)計的方法都不可能完全準(zhǔn)確,本節(jié)的目的是探討幾種可能的方法,然后確定其中我們認(rèn)為合理的一個。
現(xiàn)在考慮下列問題:
14年里總共有多少參賽選手?
這些參賽選手中有多少不重復(fù)的姓名?
有多少姓名出現(xiàn)兩次、三次、四次,等等,最常見的姓名是什么?
一年之內(nèi)多次出現(xiàn)的姓名的出現(xiàn)頻率是多少?
回答以上這些問題可以使我們體會到匹配問題的量級大小。此外,我們可以考慮如何通過清洗name和home的值來提高匹配率。例如,記得前面我們解析文本表格時,在字段末尾附加了一些空格,現(xiàn)在可能是消除它們的好時機(jī)。在前面我們也注意到大小寫的不一致問題,可以證明匹配記錄的不確定性。伴隨我們開始進(jìn)一步仔細(xì)檢查記錄,其他有關(guān)清洗字符串的問題也會隨之涌現(xiàn)。在回答這些問題之前,我們先來清洗姓名。
任何出現(xiàn)在一個姓名前面或后面的空格都可以被舍棄。此外,如果出現(xiàn)多個空格,例如,在名字和姓氏之間有多個空格,我們可以把它們轉(zhuǎn)換成一個。gsub()函數(shù)可以實現(xiàn)這些操作。下面我們創(chuàng)建一個幫助函數(shù),trimBlanks()來完成該工作:
第一次替代消除所有開始的空格,第二次替代消除所有末尾的空格,第三次用一個空格替代多個連續(xù)的空格。注意我們使用元字符“[:blank:]”,這樣可以找到所有形式的空格,包括制表符。清洗姓名如下:
現(xiàn)在可以開始回答關(guān)于姓名唯一性的問題了。我們通過檢查概要統(tǒng)計和記錄集合來完成該工作。
14次比賽中共有多少參賽選手呢?用length()函數(shù)進(jìn)行查找:
回顧在前面的部分,我們舍棄了那些比賽用時少于30分鐘和年齡低于16歲的記錄。
那么有多少不重復(fù)的姓名呢?
有多少姓名出現(xiàn)一次、兩次等?我們可以通過調(diào)用兩次table()函數(shù)來進(jìn)行判定,也就是
這個表格說明什么呢?我們可以看到14次比賽中有超過7000個姓名出現(xiàn)了兩次。有一個姓名出現(xiàn)了30次,而我們知道這個姓名至少對應(yīng)3個人,因為僅僅有14次的比賽結(jié)果。
哪個姓名出現(xiàn)了30次呢?我們可以用如下代碼進(jìn)行查找:
下面來檢查關(guān)于30個Michael Smith的其他信息。我們從數(shù)據(jù)框中提取它們:
其居住地包括:
由于額外的空格,這里出現(xiàn)幾個不同的Annapolis MD版本。顯然我們也需要清洗home字段。
進(jìn)一步考慮,我們可能會問:可以通過更多的清洗潛在地提高匹配的效率嗎?我們已知列標(biāo)題有大小寫不一致的情況,毫無疑問,姓名也存在同樣的問題。我們可以檢查大小寫,但也可以簡單地將所有字符變?yōu)樾懽帜?#xff1a;
再次檢查最常見的姓名:
通過這次額外清洗又多找到了3個Michael Smith。
此外,可以刪除標(biāo)點符號,例如某人中間名縮寫的后面及任意零散的逗號,我們通過調(diào)用一次gsub()函數(shù)進(jìn)行處理:
既然有如此多重復(fù)的姓名,下面我們計算一個姓名在相同年份中出現(xiàn)的次數(shù)??梢詣?chuàng)建一個年份-姓名的組合表格:
然后調(diào)用max()函數(shù)來查找有最大計數(shù)值的表格單元,即
這又是Michael Smith嗎?還需要通過一些處理找到與這個最大計數(shù)值關(guān)聯(lián)的名字。這個存儲在tabNameYr里的表格為table類,我們看到它是一個具有3個屬性的數(shù)值向量:dim、dimnames和class。調(diào)用class()、mode()和attributes()函數(shù),可以幫助我們得到以上信息,即
這個數(shù)據(jù)結(jié)構(gòu)有多重含義。首先,一些矩陣函數(shù)可以在table類上進(jìn)行處理,例如,我們可以調(diào)用dim()和colnames()函數(shù)進(jìn)行查找:
注意我們發(fā)現(xiàn)了另一條混亂的數(shù)據(jù)!為了找出是哪個單元中的計數(shù)值為5,我們可以使用which()函數(shù),但是要找到行和列的位置,需要在調(diào)用中包含arr.ind參數(shù)。也就是
最后,對姓名進(jìn)行定位如下:
它是Michael Brown,不是Michael Smith!
現(xiàn)在我們有了一個清洗過的選手姓名的版本,下面將它添加到我們的數(shù)據(jù)框中:
我們使用這種格式的姓名去創(chuàng)建唯一的選手標(biāo)識。
因為我們有選手的年齡和比賽的年份,所以也可以獲得選手近似的出生年份。比賽是在每年4月的第一個星期日舉行,因此這兩者之間的差值是對年齡的一個近似。那些生日在4月開始七天內(nèi)的參賽選手,有可能對他們年齡的記錄在兩個比賽年份中是不一致的??梢灶A(yù)知記錄的哪些部分會出現(xiàn)這種問題嗎?我們在數(shù)據(jù)框中創(chuàng)建一個新的變量yob:
另外,我們發(fā)現(xiàn)在居住地名里也有空格和大小寫的問題。這里將對它們的處理留作練習(xí),要求清洗home值,并將清洗過的home版本添加到cbMenSub為homeClean。
下面讓我們更加仔細(xì)地查看在數(shù)據(jù)框中的這些新的、清洗過的關(guān)于Michael Brown的變量。代碼如下:
針對以上各種不同的michael brown行可以得到怎樣的觀察結(jié)果呢?
出生于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次更接近一些?;ヂ?lián)網(wǎng)搜索顯示,Reston和Ashburn相距不到22千米??梢圆孪脒@4條記錄屬于同一個人,他可能在2010年4月到2012年4月間從Reston搬到了Ashburn,但對此我們并不能完全確定。
另外3條記錄中michael brown都出生于1966年。除了在2006年的記錄中州名MD沒有提供外,3條記錄的居住地都是Chevy Chase。當(dāng)我們檢查2006年其他的參賽選手時,發(fā)現(xiàn)他們中也沒有人列出州名。3條michael brown記錄中比賽時間之間也存在11分鐘之差,其中在中間年份2010年跑得最快。因此這些記錄很可能屬于同一個人,但是我們發(fā)現(xiàn)2006年記錄中的居住地和其他年份的不同。
接下來,還有4條michael brown的記錄是出生于1984年,參加比賽的時間分別是2008年、2010年、2011年和2012年。其中,2010年記錄中的選手似乎和其他三條記錄中的選手不是同一個人,因為他的居住地是New York,NY,且他的跑步時間也比其他三條紀(jì)錄慢了25~40分鐘。其他三條記錄的居住地同為Arlington,VA,他們的跑步時間也從2008年的84分鐘提升到2012年的71分鐘。因此認(rèn)為這三條記錄同屬于一個人似乎是合理的,因為一個人隨著年齡的增長,他訓(xùn)練和跑步的速度也會更快。而對此我們同樣不能完全確定。
最后,我們注意到2012年注冊的5條michael brown記錄具有不同的出生年份(1953、1958、1966、1984和1988)和5個不同的居住地,因此這是5位不同的參賽選手。
我們總結(jié)各種不同的觀察結(jié)果,并第一次嘗試為個體選手創(chuàng)建標(biāo)識符,然后可能將清洗后的姓名和推導(dǎo)出的出生年份粘合在一起。代碼如下:
我們忽略居住地和跑步時間所提供的信息,因此創(chuàng)建了限制最少的標(biāo)識符。
由于我們的目標(biāo)是研究一個運(yùn)動員跑步時間隨著年齡增長的變化,下面讓我們重點關(guān)注那些ID至少出現(xiàn)8次的選手。為了完成這個目標(biāo),我們首先判定每個ID在cbMenSub中出現(xiàn)的次數(shù),代碼如下:
然后選擇那些ID至少出現(xiàn)8次的記錄:
我們選擇屬于這些標(biāo)識符的記錄構(gòu)建子集menRes:
最后,組織數(shù)據(jù)框使相同ID的記錄相連,這樣就使諸如手工檢查記錄等操作變得更加容易:
另一種數(shù)據(jù)組織方式是將races8中每一個ID的元素存儲為一個列表。該列表中,每個元素是一個數(shù)據(jù)框且僅包含具有相同ID的記錄結(jié)果。通過如下代碼創(chuàng)建列表:
其中哪種數(shù)據(jù)結(jié)構(gòu)更好呢?這將取決于我們想如何處理數(shù)據(jù)。接下來,我們將展示如何使用兩種方法來完成一項任務(wù),以便在這兩種數(shù)據(jù)結(jié)構(gòu)之間進(jìn)行比較。在下一節(jié)中,我們會發(fā)現(xiàn)使用數(shù)據(jù)框中的列表進(jìn)行處理是最容易的,因為我們常常需要將含有多個參數(shù)的函數(shù)應(yīng)用于每個參賽選手的記錄。
創(chuàng)建列表后還剩下多少個ID呢?
這和代碼length(men8L)的功能是一樣的。如果兩年間的比賽成績變化太大,我們可能就會放棄記錄的匹配。那么多大的起伏變化會讓我們認(rèn)為是錯誤地連接了兩個不同的選手呢?當(dāng)然,我們不想通過消除跑步時間變化很大的個體而使結(jié)果產(chǎn)生偏見。下面讓我們查看一些在相鄰兩年內(nèi)跑步時間之差超過20分鐘的記錄。使用如下方法找出那些滿足該約束的記錄:
或者使用
有多少時間差超過20分鐘的選手?
前兩位運(yùn)動員經(jīng)過稍微重新格式化的顯示結(jié)果如下:
姓名為abiy zewde的選手似乎非同尋常,很可能是同一個人參加了14次比賽中的12次,雖然有幾年居住地改變了,且最近一次年齡為45歲的比賽結(jié)果與最快的一次相差了幾乎40分鐘。事實上,谷歌搜索定位了一個網(wǎng)頁http://storage.athlinks.com/racer/results/65866776,發(fā)布了他在幾次不同比賽中的跑步時間。網(wǎng)頁截圖如圖2-16所示,可以清晰地看到這些記錄是屬于同一個人的。
圖2-16 一個參賽選手比賽結(jié)果的網(wǎng)頁截圖。這個網(wǎng)址為http://storage.athlinks.com的網(wǎng)頁包含一個選手在14年中的12次參加櫻花公路賽的比賽結(jié)果數(shù)據(jù)。注意他最快的跑步時間是在最近的2012年,完成比賽的時間少于85分鐘,那時他45歲。而他最慢的時間是2002年的123分鐘,那時他35歲
想用同一個居住地來進(jìn)一步約束我們的匹配項嗎?這樣可以消除諸如abiy zewde記錄中的不同,盡管我們相當(dāng)確定這些記錄是屬于同一個人的。我們可以識別不當(dāng)匹配,并手動檢查潛在的錯誤匹配結(jié)果。因為2006年的記錄中沒有州名,所以我們需要從那些記錄項的末尾去除州名的縮寫??梢杂靡粋€空字符串替換出現(xiàn)在字符串末尾的一個空格及后面跟著的兩個字母。例如:
這可能會導(dǎo)致太過自由的匹配,例如,匹配Springfield IL和Springfield MA。在此我們將它留作練習(xí),確定如何將匹配限制到那些具有相同居住地的記錄中,并評估是否應(yīng)該在匹配過程中添加額外的限制條件。
這里,我們考慮一個不太嚴(yán)格的匹配,僅僅匹配那些具有相同居住州的記錄。為此,我們創(chuàng)建一個新的變量來保存州名的兩個縮寫字母。因為數(shù)據(jù)結(jié)構(gòu)比較簡單,我們返回去處理cbMenSub,并保持一致性。從每個居住地的字符串中提取最后2個字母。如果存在,它就是州名。我們知道在2006年的記錄中沒有出現(xiàn)州名,因此將其設(shè)置為NA。對于來自美國以外的運(yùn)動員,提取國家或者省份的最后兩個字母,但這些不應(yīng)該顯著地影響我們的匹配。
首先確定在每個home值中有多少個字母,代碼如下:
然后使用如下代碼提取最后兩個字母,并將它們添加回數(shù)據(jù)框里:
并且將2006年的值設(shè)置為NA:
接下來,我們重新創(chuàng)建一個新的ID以使其包含state,代碼如下:
然后,我們再次選擇那些至少出現(xiàn)8次的ID。代碼如下:
在下一節(jié)中,我們將單獨(dú)使用列表結(jié)構(gòu)來進(jìn)行處理。
這次添加完選手的ID后,進(jìn)一步減少了完成8次比賽的選手?jǐn)?shù)量,即
現(xiàn)在有306名運(yùn)動員具有相同的姓名、出生年份和州名,并且都完成了14次比賽中的8次。迄今為止我們一直在已獲得的匹配集合上進(jìn)行處理,在下一節(jié),我們將研究參賽選手的成績?nèi)绾坞S著年齡增長而變化
總結(jié)
以上是生活随笔為你收集整理的《数据科学R语言实践:面向计算推理与问题求解的案例研究法》一一2.5 为跨年度的个人参赛选手构造记录...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bash删除文件中含指定内容的行
- 下一篇: GDB命令大全