機(jī)器學(xué)習(xí)案例解析(上部)_第1頁
機(jī)器學(xué)習(xí)案例解析(上部)_第2頁
機(jī)器學(xué)習(xí)案例解析(上部)_第3頁
機(jī)器學(xué)習(xí)案例解析(上部)_第4頁
機(jī)器學(xué)習(xí)案例解析(上部)_第5頁
已閱讀5頁,還剩113頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

機(jī)器學(xué)習(xí)實(shí)用案例解析(上部1-5章)目錄\h第1章使用R語言\hR與機(jī)器學(xué)習(xí)\h下載和安裝R\h集成開發(fā)環(huán)境和文本編輯器\h安裝和加載R程序包\h機(jī)器學(xué)習(xí)中的R基礎(chǔ)\h深入學(xué)習(xí)R的參考書目\h第2章數(shù)據(jù)分析\h分析與驗(yàn)證\h什么是數(shù)據(jù)\h推斷數(shù)據(jù)的類型\h推斷數(shù)據(jù)的含義\h數(shù)值摘要表\h均值、中位數(shù)、眾數(shù)\h分位數(shù)\h標(biāo)準(zhǔn)差和方差\h可視化分析數(shù)據(jù)\h列相關(guān)的可視化\h第3章分類:垃圾過濾\h非此即彼:二分類\h漫談條件概率\h試寫第一個(gè)貝葉斯垃圾分類器\h定義分類器并用不易識(shí)別的正常郵件進(jìn)行測(cè)試\h用所有郵件類型測(cè)試分類器\h效果改進(jìn)\h第4章排序:智能收件箱\h次序未知時(shí)該如何排序\h按優(yōu)先級(jí)給郵件排序\h郵件優(yōu)先級(jí)的特征\h實(shí)現(xiàn)一個(gè)智能收件箱\h用于抽取特征集合的函數(shù)\h設(shè)計(jì)用于排序的權(quán)重計(jì)算策略\h郵件線程活躍度的權(quán)重計(jì)算\h訓(xùn)練和測(cè)試排序算法\h第5章回歸模型:預(yù)測(cè)網(wǎng)頁訪問量\h回歸模型簡(jiǎn)介\h基準(zhǔn)模型\h使用虛擬變量的回歸模型\h線性回歸簡(jiǎn)介\h預(yù)測(cè)網(wǎng)頁流量\h定義相關(guān)性第1章使用R語言機(jī)器學(xué)習(xí)是由軟件工程、計(jì)算機(jī)科學(xué)這樣的新興學(xué)科與數(shù)學(xué)、統(tǒng)計(jì)學(xué)這樣的傳統(tǒng)學(xué)科交叉形成的一門學(xué)科。在本書中,我們會(huì)介紹統(tǒng)計(jì)學(xué)領(lǐng)域的一些有助于人們認(rèn)識(shí)世界的工具。統(tǒng)計(jì)學(xué)一直在研究如何從數(shù)據(jù)中得到可解釋的東西,而機(jī)器學(xué)習(xí)則關(guān)注如何將數(shù)據(jù)變成一些實(shí)用的東西。對(duì)兩者做出如下對(duì)比更有助于理解“機(jī)器學(xué)習(xí)”這個(gè)術(shù)語:機(jī)器學(xué)習(xí)研究的內(nèi)容是教給計(jì)算機(jī)一些知識(shí),再讓計(jì)算機(jī)利用這些知識(shí)完成其他的任務(wù)。相比之下,統(tǒng)計(jì)學(xué)則更傾向于開發(fā)一些工具來幫助人類認(rèn)識(shí)世界,以便人類可以更加清晰地思考,從而做出更佳的決策。在機(jī)器學(xué)習(xí)中,學(xué)習(xí)指的是采用一些算法來分析數(shù)據(jù)的基本結(jié)構(gòu),并且辨別其中的信號(hào)和噪聲,從而提取出盡可能多的(或者盡可能合理的)信息的過程。在算法發(fā)現(xiàn)信號(hào)或者說模式之后,其余的所有東西都將被簡(jiǎn)單判斷為噪聲。因此,機(jī)器學(xué)習(xí)技術(shù)也稱為模式識(shí)別算法。我們可以“訓(xùn)練”機(jī)器去學(xué)習(xí)數(shù)據(jù)是如何在特定情境中產(chǎn)生的,從而使用這些算法將許多有用的任務(wù)實(shí)現(xiàn)自動(dòng)化。這就引出了訓(xùn)練集(trainingset)這一術(shù)語,它指的是構(gòu)建機(jī)器學(xué)習(xí)過程所用到的數(shù)據(jù)集。觀測(cè)數(shù)據(jù)、從中學(xué)習(xí)、自動(dòng)化識(shí)別過程,這三個(gè)概念是機(jī)器學(xué)習(xí)的核心,同時(shí)也是本書的主線。本書的核心問題包含兩個(gè)特別重要的模式:分類問題和回歸問題,這兩類問題在書中會(huì)不斷出現(xiàn),當(dāng)然我們也會(huì)教給大家解決方法。在本書中,我們假設(shè)讀者具備相對(duì)較高水平的基本編程技能和算法知識(shí)。R語言一直是一門相當(dāng)小眾的編程語言,甚至對(duì)于許多資深程序員來說亦是如此。為了盡量讓每一個(gè)讀者都處于同一起點(diǎn),本章將介紹一些R語言的入門基礎(chǔ)知識(shí)。稍后還將介紹一個(gè)使用R語言來處理數(shù)據(jù)的延伸案例研究。警告:本章并非要完整地介紹R編程語言。況且僅用一個(gè)章節(jié)來完整地介紹R也根本不可能。相反,這一章是為了讓讀者做好相關(guān)知識(shí)準(zhǔn)備,進(jìn)而用R來完成機(jī)器學(xué)習(xí)任務(wù),尤其是用R來加載、探索、清洗以及分析數(shù)據(jù)等。已有許多不錯(cuò)的資源專注于R基礎(chǔ)知識(shí),包括數(shù)據(jù)類型、算術(shù)運(yùn)算概念以及最佳編碼實(shí)踐。本章要展示的案例研究與上述這些R基礎(chǔ)概念都有關(guān)聯(lián)。雖然我們會(huì)談及上述每個(gè)問題,但都不會(huì)太深入。若讀者有興趣對(duì)這些知識(shí)點(diǎn)進(jìn)行回顧,表1-3列出了可供參考的資源。如果你此前從未接觸過R及其語法,我們強(qiáng)烈建議你通過閱讀本章來掃掃盲。R不像其他高層次腳本語言,如Python和Ruby,它的語法獨(dú)特且晦澀,往往不如其他編程語言容易上手。如果你此前用過R,但不是用于機(jī)器學(xué)習(xí),那么在進(jìn)行案例研究之前也有必要花時(shí)間看看以下綜述。R與機(jī)器學(xué)習(xí)R是用于統(tǒng)計(jì)計(jì)算、繪圖的語言和操作環(huán)境……R提供了豐富多樣的統(tǒng)計(jì)功能(線性和非線性建模、經(jīng)典統(tǒng)計(jì)學(xué)實(shí)驗(yàn)、時(shí)間序列分析、分類、聚類……)和繪圖技術(shù),并且具有高度可擴(kuò)展性。在統(tǒng)計(jì)方法學(xué)研究中,S語言是一種常用的工具,而R則以開源的方式躋身其中。——用于統(tǒng)計(jì)計(jì)算的R項(xiàng)目,/R最大的優(yōu)勢(shì)是:它是由統(tǒng)計(jì)學(xué)家們開發(fā)的。R最大的劣勢(shì)是……它是由統(tǒng)計(jì)學(xué)家們開發(fā)的?!狟oCowgill,Google公司在處理和分析數(shù)據(jù)方面,R是一門非常強(qiáng)大的語言。它在數(shù)據(jù)科學(xué)界以及機(jī)器學(xué)習(xí)界的迅速流行已經(jīng)使它成為分析學(xué)領(lǐng)域?qū)嶋H上的通用語言。R在數(shù)據(jù)分析界的成功源于上述引文中提到的兩個(gè)因素:首先,R內(nèi)置了統(tǒng)計(jì)學(xué)家們所需的技術(shù);其次,R備受統(tǒng)計(jì)學(xué)界開源貢獻(xiàn)者們的支持與推崇。專門為統(tǒng)計(jì)計(jì)算設(shè)計(jì)的編程語言具有很多技術(shù)上的優(yōu)勢(shì)。正如R項(xiàng)目所述,這門語言提供了一座通往S的開源橋梁,而S中所包含的許多基礎(chǔ)函數(shù)都是高度專業(yè)化的統(tǒng)計(jì)操作。例如,用R來執(zhí)行一個(gè)基本的線性回歸操作,你只需簡(jiǎn)單地把數(shù)據(jù)傳入lm函數(shù),然后函數(shù)返回一個(gè)包含了詳細(xì)回歸信息(回歸系數(shù)、標(biāo)準(zhǔn)誤差、殘差等)的對(duì)象。然后,這個(gè)數(shù)據(jù)可以用plot函數(shù)進(jìn)行可視化,plot函數(shù)是專用于對(duì)分析結(jié)果進(jìn)行可視化的函數(shù)。與科學(xué)計(jì)算相關(guān)的其他大眾編程語言,比如Python,要實(shí)現(xiàn)和lm函數(shù)相同的功能,需要若干第三方庫(kù)分別來完成數(shù)據(jù)表達(dá)(NumPy)、進(jìn)行分析(SciPy)、將結(jié)果可視化(matplotlib)等過程。這樣復(fù)雜的分析步驟,R只需一行代碼就可完成,我們將在接下來的幾個(gè)章節(jié)中見識(shí)到這些。此外,和其他科學(xué)計(jì)算環(huán)境一樣,R的基本數(shù)據(jù)類型也是向量。在本質(zhì)上,R語言里的所有的數(shù)據(jù)都是向量,盡管它們有不同的聚合和組織方式。盡管這種數(shù)據(jù)結(jié)構(gòu)理念比較僵化,但考慮到R的應(yīng)用,這種觀點(diǎn)還算合乎邏輯。R中最常用到的數(shù)據(jù)結(jié)構(gòu)就是數(shù)據(jù)框(dataframe),可以把它看做R內(nèi)核中一種帶屬性的矩陣、一種內(nèi)部定義的數(shù)據(jù)表結(jié)構(gòu),或者一種關(guān)系型數(shù)據(jù)庫(kù)式結(jié)構(gòu)。從根本上講,數(shù)據(jù)框就是將向量簡(jiǎn)單地按列聚合的結(jié)果,同時(shí)R為其提供一些特別的功能,這樣一來,數(shù)據(jù)框就成為適用于任何形式數(shù)據(jù)的理想結(jié)構(gòu)。警告:正因其有所長(zhǎng),R也有短板——R并不能很好地處理大數(shù)據(jù)。盡管已有很多人在努力解決,但這仍然是一個(gè)嚴(yán)重的問題。然而,對(duì)于我們將要探討的案例研究來說,這不是個(gè)問題。我們使用的數(shù)據(jù)集相對(duì)較小,要搭建的系統(tǒng)也都只是原型系統(tǒng)或概念驗(yàn)證模型。這個(gè)區(qū)別很重要,因?yàn)槿绻阋罱℅oogle或Facebook那樣規(guī)模的企業(yè)級(jí)機(jī)器學(xué)習(xí)系統(tǒng),選擇R并不合適。事實(shí)上,像Google或Facebook這些公司通常把R作為“數(shù)據(jù)沙箱”,用于處理數(shù)據(jù)以及實(shí)驗(yàn)新的機(jī)器學(xué)習(xí)方法。如果某個(gè)實(shí)驗(yàn)有了成果,那么工程師就會(huì)把R中的相關(guān)功能用更適合的語言復(fù)現(xiàn)出來,比如C語言。這種實(shí)驗(yàn)精神也孕育出了R用戶群的一種集體感。R的社會(huì)優(yōu)勢(shì)依賴于這個(gè)巨大且不斷成長(zhǎng)的專家圈,是他們堅(jiān)持使用并不斷豐富這一語言的。正如BoCowgill所言,統(tǒng)計(jì)學(xué)家強(qiáng)烈希望有一種計(jì)算環(huán)境能夠滿足他們的特殊需求,R才得以誕生。因此,很多R用戶都是各自領(lǐng)域的專家,這包括一些完全不同的學(xué)科,比如數(shù)學(xué)、統(tǒng)計(jì)學(xué)、生物學(xué)、化學(xué)、物理學(xué)、心理學(xué)、經(jīng)濟(jì)學(xué)以及政治學(xué)等。這個(gè)專家圈用R大量的基礎(chǔ)函數(shù)打造了許許多多的程序包。在本書寫作之時(shí),R的程序包資源庫(kù)CRAN中就已包含2800多個(gè)程序包。在接下來的案例研究中,我們會(huì)用到許多最流行的程序包,但這也僅僅是R的皮毛而已。雖然Cowgill的話后半句有些言重,但是這進(jìn)一步強(qiáng)調(diào)了R用戶群的力量之大。隨后我們會(huì)發(fā)現(xiàn),R古怪的語法常常讓代碼“錯(cuò)誤百出”,這足以讓許多資深程序員敬而遠(yuǎn)之。但是,在一門語言中,所有的語法難題最終都可以攻克,尤其對(duì)于那些持之以恒的黑客們而言。對(duì)于非統(tǒng)計(jì)學(xué)出身的人而言,更大的困難是不熟悉R中內(nèi)置的數(shù)學(xué)和統(tǒng)計(jì)函數(shù)。比如,使用lm函數(shù)時(shí),如果你從未接觸過線性回歸,你可能就不知道結(jié)果里面已經(jīng)包含了回歸系數(shù)、標(biāo)準(zhǔn)誤差和殘差,你也不知道結(jié)果該怎么解釋。因?yàn)檫@門語言是開源的,所以你可以隨時(shí)查看函數(shù)的源代碼,看看內(nèi)部是怎么運(yùn)行的。本書的目的之一就是要探索這些函數(shù)在機(jī)器學(xué)習(xí)的情境下怎么使用,但這最終也只能讓你窺見R所有功能的冰山一角。值得慶幸的是,在R社區(qū)中,很多人不僅樂于幫助你理解這門語言,而且樂于幫助你了解其內(nèi)部的實(shí)現(xiàn)。表1-1列出了一些最佳的R社區(qū)。本章余下的內(nèi)容專門教你如何配置好R環(huán)境并且使用它,包括下載和安裝R,以及下載R程序包。本章以一個(gè)小型的案例研究作為結(jié)束,該案例研究將介紹一些我們?cè)谥笳鹿?jié)常常用到的R知識(shí),包括加載、清洗、組織以及分析數(shù)據(jù)等問題。下載和安裝R和其他開源項(xiàng)目一樣,R有若干個(gè)不同地區(qū)的鏡像下載站點(diǎn)。如果你的電腦上還沒安裝R,第一步就是要下載R。登錄/mirrors.html,選擇離你最近的CRAN鏡像站點(diǎn),選擇了鏡像站點(diǎn)后,根據(jù)你所用的操作系統(tǒng)下載適當(dāng)?shù)陌姹?。R依賴一些用C或Fortran編譯的庫(kù)。因此,你可以安裝編譯好的二進(jìn)制版本,也可以選擇用源代碼安裝,這既取決于你的操作系統(tǒng),又取決于你用源代碼安裝軟件的熟練程度。接下來我們一一演示如何在Windows、MacOSX以及Linux環(huán)境下安裝R,并配有用源代碼安裝和二進(jìn)制安裝的說明。最后要說明一點(diǎn),R既有32位版本,也有64位版本。依據(jù)硬件和操作系統(tǒng)的配置,你可以選擇合適的版本進(jìn)行安裝。Windows網(wǎng)站上有兩個(gè)子目錄可提供Windows上的R安裝文件:base和contrib。后者是一個(gè)包含了所有擴(kuò)展包的Windows二進(jìn)制版本,而前者僅僅是包含基本功能的二進(jìn)制安裝文件。選擇base目錄,然后下載最新編譯的二進(jìn)制文件即可進(jìn)行安裝。在R上安裝程序包也不難,而且不受語言的限制,因此沒必要用contrib目錄下的安裝文件進(jìn)行安裝。只要一步步跟著屏幕上的安裝說明即可完成安裝。安裝成功之后,在你的開始菜單中就有R應(yīng)用程序的圖標(biāo),可以用這些圖標(biāo)打開R圖形用戶界面(RGui)和R控制臺(tái)(RConsole),見圖1-1。圖1-1Windows系統(tǒng)下RGui與RConsole對(duì)于Windows系統(tǒng)下的大多數(shù)標(biāo)準(zhǔn)安裝,這個(gè)過程不會(huì)出什么問題。如果你選擇了自定義安裝或者在安裝過程中遇到了一些問題,你可以在你所選擇的鏡像站點(diǎn)上找到RforWindowsFAQ頁面,查詢問題。MacOSXMacOSX用戶就幸運(yùn)得多了,因?yàn)椴僮飨到y(tǒng)已經(jīng)預(yù)裝了R。你可以打開Terminal.app,然后在命令行中輸入"R"確認(rèn)是否已安裝R。這樣你就萬事俱備了!然而,對(duì)部分用戶來說,需要安裝GUI應(yīng)用程序來與RConsole進(jìn)行交互,如此就得再安裝一個(gè)軟件。在MacOSX下,你也可以選擇安裝編譯好的二進(jìn)制版本,或者用源代碼安裝。對(duì)于沒用過Linux命令行的用戶,我們推薦使用二進(jìn)制版本安裝。只需在/mirrors.html上選擇鏡像站點(diǎn),下載最新版本,然后按照屏幕說明操作就可以了。安裝完成后,在你的Applications文件夾下有兩個(gè)文件:R.app(32位版本)和R64.app(64位版本)。你可根據(jù)硬件的配置和MacOSX的版本選擇其中一個(gè)版本。與Windows系統(tǒng)下的安裝過程一樣,如果你在MacOSX下用二進(jìn)制版本安裝,那么整個(gè)過程都不會(huì)有什么問題。打開剛安裝好的R應(yīng)用程序,出現(xiàn)的console界面和圖1-2差不多。圖1-2MacOSX系統(tǒng)下64位版本的R控制臺(tái)界面注意:如果你的MacOSX是自定義安裝的,或者你想根據(jù)自己的配置自定義安裝R,那么建議使用源代碼安裝。在MacOSX系統(tǒng)下用源代碼安裝R同時(shí)需要C和Fortran兩種語言的編譯器,而該操作系統(tǒng)的標(biāo)準(zhǔn)安裝中沒有這兩個(gè)編譯器。你可以使用MacOsX開發(fā)者工具盤(DVD)來安裝這兩個(gè)編譯器,這個(gè)盤在MacOsX原始安裝盤中。你也可以從鏡像站點(diǎn)上的tools目錄下找到必需的編譯器然后進(jìn)行安裝。具備源代碼安裝所需的編譯器之后,其安裝過程就與大多數(shù)使用命令行安裝的軟件一樣,經(jīng)典的三個(gè)步驟:configure、make和install。用Terminal.app進(jìn)入放源代碼的路徑,執(zhí)行以下命令:$./configure$make$makeinstall由于操作系統(tǒng)中用戶權(quán)限的不同,在執(zhí)行第一步之前,你可能需要輸入系統(tǒng)密碼來激活sudo權(quán)限。如果在二進(jìn)制安裝和源代碼安裝過程中遇到了任何問題,都可以到鏡像站點(diǎn)的RforMacOSXFAQ頁面查詢?cè)?。Linux許多版本的linux和MACOSX一樣,都預(yù)裝了R。只需在命令行敲入"R",就可以加載R控制臺(tái)。接著,你就可以開始編程了!CRAN上也有Debian、RedHat、SUSE以及Ubuntu這些不同linux版本相應(yīng)的R安裝文件及安裝說明。如果你使用其中一個(gè)版本進(jìn)行安裝,我們建議參考針對(duì)你的操作系統(tǒng)的安裝說明,因?yàn)椴煌姹镜腖inux操作系統(tǒng),其最佳實(shí)踐存在的差異相當(dāng)大。集成開發(fā)環(huán)境和文本編輯器由于R是一種腳本語言,因此在接下來的案例研究中大部分的工作都要用集成開發(fā)環(huán)境(IDE)或者文本編輯器來完成,而不是直接在R控制臺(tái)上輸入程序。從下一節(jié)的內(nèi)容里,你會(huì)發(fā)現(xiàn)有些工作適合直接在控制臺(tái)上完成,比如安裝程序包,但是大多數(shù)時(shí)候你還是愿意在IDE或者文本編輯器中寫程序。在Windows或者M(jìn)acOSX環(huán)境里運(yùn)行的R圖形用戶界面,程序中都有一個(gè)基本的文本編輯器。如果你想新建一個(gè)空白文檔,你可以在菜單上依次選擇File→NewDocument(文件→新建程序腳本),也可以直接單擊窗口頂部的空白文檔圖標(biāo)(圖1-3中高亮處)。作為一個(gè)黑客,你應(yīng)該已經(jīng)有一個(gè)IDE或者文本編輯器了,我們建議你在本書的案例研究過程中從這兩者中選擇最熟悉的環(huán)境來開發(fā)。界面上還有很多選項(xiàng),在此不再一一列舉,我們也不想卷入Emacs和Vim之爭(zhēng)。圖1-3R圖形用戶界面上的文本編輯器圖標(biāo)安裝和加載R程序包目前已有很多精心設(shè)計(jì)、維護(hù)良好且廣泛支持的與機(jī)器學(xué)習(xí)相關(guān)的R程序包。在我們要進(jìn)行的案例研究中,涉及的程序包主要用于:處理空間數(shù)據(jù)、進(jìn)行文本分析、分析網(wǎng)絡(luò)拓?fù)涞龋€有些程序包用于與網(wǎng)絡(luò)API進(jìn)行交互,當(dāng)然還有其他很多功能,不勝枚舉。因此,我們的任務(wù)很大程度上會(huì)依賴內(nèi)置在這些程序包的函數(shù)功能。加載R程序包很簡(jiǎn)單。實(shí)現(xiàn)加載的兩個(gè)函數(shù)是:library和require。兩者之間存在細(xì)微差別,在本書中,主要差別是:后者會(huì)返回一個(gè)布爾值(TRUE或FALSE)來表示是否加載成功。例如,在第6章中,我們會(huì)用到tm程序包來分詞。要加載該程序包,我們既可以用library也可以用require。在下面所舉例子中,我們用library來加載tm包,用require來加載XML包,再用print函數(shù)來顯示require函數(shù)的返回值??梢钥吹剑祷氐牟紶栔凳?TRUE",可見XML包加載成功了。library(tm)print(require(XML))#[1]TRUE假如XML包還未安裝成功,即require函數(shù)返回值為"FALSE",那么我們?cè)谡{(diào)用之前仍需先安裝成功這個(gè)包。注意:如果你剛安裝成功R環(huán)境,那么你還需要安裝較多的程序包才能完成本書的所有案例研究。在R環(huán)境中安裝程序包有兩種方法:可以用圖形用戶界面進(jìn)行安裝,也可以用R控制臺(tái)中的install.packages函數(shù)來安裝。考慮到本書目標(biāo)讀者的水平,我們?cè)诒緯陌咐芯恐袝?huì)全部采用R控制臺(tái)進(jìn)行交互,但還是有必要介紹一下怎么用圖形用戶界面安裝程序包。在R應(yīng)用程序的菜單欄上,找到Packages&Data→PackageInstaller(程序包→安裝程序包),點(diǎn)擊之后彈出如圖1-4所示的窗口。從程序包資源庫(kù)的下拉列表中選擇CRAN(binaries)(CRAN(二進(jìn)制))或者CRAN(sources)(CRAN(源代碼)),點(diǎn)擊GetList(獲取列表)按鈕,加載所有可安裝的程序包,最新的程序包版本可以從CRAN(sources)(CRAN(源代碼))資源庫(kù)中獲取。如果你的計(jì)算機(jī)上已經(jīng)安裝了所需的編譯器,我們推薦用源代碼安裝。接著,選擇要安裝的包,然后點(diǎn)擊InstallSelected(安裝所選包),即可安裝。圖1-4用圖形用戶界面安裝R程序包相比而言,用install.packages函數(shù)來安裝是一種更佳的方法,因?yàn)樗诎惭b方式和安裝路徑上更為靈活。這種方法的主要優(yōu)勢(shì)之一就是既可以用本地的源代碼,也可以用CRAN上的源代碼來安裝。雖然以下這種情況不太常見,但仍然有可能會(huì)需要。有時(shí)你可能要安裝一些CRAN上還未發(fā)布的程序包,比如你要將程序包更新到測(cè)試版本,那么你必須用源代碼進(jìn)行安裝:install.packages("tm",dependencies=TRUE)setwd("~/Downloads/")install.packages("RCurl_1.5-0.tar.gz",repos=NULL,type="source")第一行代碼中,我們用默認(rèn)參數(shù)從CRAN上安裝了tm程序包。tm程序包用于文本挖掘,在第3章將用它來對(duì)電子郵件文本進(jìn)行分類。install.packages中一個(gè)很有用的參數(shù)是suggests,這個(gè)參數(shù)默認(rèn)值是FALSE,如果設(shè)置為TRUE,就會(huì)在安裝過程中通知install.packages函數(shù)下載并安裝初始安裝過程所依賴的程序包。為了得到最佳實(shí)踐,我們推薦將此參數(shù)值一直設(shè)置為TRUE,當(dāng)R應(yīng)用程序上沒有任何程序包的情況下更要如此。同樣還有另一種安裝方法,那就是直接使用源代碼的壓縮文件進(jìn)行安裝。在上一個(gè)例子中,我們用作者網(wǎng)站上的源代碼安裝了RCurl程序包。用setwd函數(shù)確保R的工作路徑已設(shè)置為保存源代碼的目錄,然后就可以簡(jiǎn)單地執(zhí)行前面的命令從源代碼安裝了。注意,這里需要改動(dòng)兩個(gè)參數(shù)。首先,我們必須設(shè)置repos=NULL來告訴函數(shù)不要使用CRAN中任意一個(gè)資源庫(kù),然后要設(shè)置type="source"來告訴函數(shù)使用源代碼安裝。前文已經(jīng)提到過,在本書中我們會(huì)使用一些程序包。表1-2列出了本書的案例研究所用到的所有程序包,包括對(duì)其用途的簡(jiǎn)單介紹,以及查看每個(gè)包詳細(xì)信息的鏈接。安裝所需程序包的數(shù)量不少,為了加快安裝過程,我們創(chuàng)建了一個(gè)簡(jiǎn)短的腳本來檢查每個(gè)必需的程序包是否已安裝,若沒有安裝,它會(huì)通過CRAN進(jìn)行安裝。要運(yùn)行該腳本,先用setwd函數(shù)將工作目錄設(shè)置為本章代碼所在的文件夾,再執(zhí)行source命令,如下所示:source("package_installer.R")如果你還沒有安裝過程序包,系統(tǒng)可能要求你選擇一個(gè)CRAN的庫(kù)。一旦設(shè)置完成,腳本就開始運(yùn)行,你就可以看到所有需要安裝的程序包的安裝進(jìn)度?,F(xiàn)在,我們就要用R開始機(jī)器學(xué)習(xí)之旅了!在我們開始案例分析之前,我們?nèi)孕枰仡櫼恍┏S玫腞相關(guān)的函數(shù)與操作。機(jī)器學(xué)習(xí)中的R基礎(chǔ)在本書開篇,我們就提出,學(xué)習(xí)新技術(shù)的最好方式是從你渴望解決的問題或你渴望解答的疑問入手。對(duì)任務(wù)的較高層次愿景滿懷激情,這會(huì)讓你從案例中有效地學(xué)到知識(shí)。這里我們要介紹的R基礎(chǔ)知識(shí)并不會(huì)涉及機(jī)器學(xué)習(xí)問題,但是我們將遇到一些R中數(shù)據(jù)處理和管理相關(guān)的問題。在案例研究中可以發(fā)現(xiàn),常常要花很多時(shí)間來規(guī)整數(shù)據(jù),使其格式統(tǒng)一、組織合理以便分析。而花在編寫代碼、運(yùn)行分析的時(shí)間常常較少。在接下來這個(gè)案例中,我們提出的問題純屬為了好玩。最近,數(shù)據(jù)服務(wù)商I發(fā)布了一個(gè)數(shù)據(jù)集,其中含有60000多條不明飛行物(UFO)的目擊記錄和報(bào)道。這份數(shù)據(jù)時(shí)間跨度幾百年,地域覆蓋全世界。雖然數(shù)據(jù)涵蓋全球,但是主要的目擊記錄都發(fā)生在美國(guó)。面對(duì)這份數(shù)據(jù)的時(shí)空維度,我們可能會(huì)有以下疑問:UFO的出現(xiàn)是否有周期性規(guī)律?美國(guó)的不同州出現(xiàn)的UFO記錄如果有區(qū)別,有哪些區(qū)別?我們要探索的是一個(gè)很棒的數(shù)據(jù)集,因?yàn)樗鼣?shù)量巨大、高度結(jié)構(gòu)化,同時(shí)也很有趣。因?yàn)樗莻€(gè)大文本文件,而且我們?cè)诒緯幸幚淼臄?shù)據(jù)都屬于這一類型,所以練習(xí)一下很有用。在這樣的文本文件中,常常有一些雜亂的記錄,我們會(huì)用R中的基本函數(shù)和擴(kuò)展庫(kù)來清洗和組織原始數(shù)據(jù)。本節(jié)我們會(huì)帶你一步一步地了解整個(gè)簡(jiǎn)單分析的過程,并試圖回答前文提到的兩個(gè)問題。在本章的code文件夾下有一個(gè)文件:ufo_sightings.R,這是本章所用的腳本源代碼。我們首先從加載數(shù)據(jù)和所需的庫(kù)開始。加載程序包和數(shù)據(jù)首先,加載的是ggplot2程序包,我們會(huì)在最后一步——可視化分析的時(shí)候用到它。library(ggplot2)加載ggplot2的過程中,你會(huì)注意到這個(gè)包還加載了另外兩個(gè)所需的程序包:plyr和reshape。這些包在R中用于處理和組織數(shù)據(jù),同時(shí)我們也會(huì)在本例中用plyr程序包來完成數(shù)據(jù)的聚合和組織。其次,從文本文件ufo_awesome.tsv加載數(shù)據(jù),文件在本章目錄下的data/ufo/中。注意一點(diǎn),該文件字段是制表符分隔的(因此擴(kuò)展名是.tsv),這意味著我們要用read.delim函數(shù)來加載數(shù)據(jù)。因?yàn)镽直接使用默認(rèn)值的地方很多,因此我們?cè)谀_本中使用函數(shù)時(shí)要特別注意默認(rèn)參數(shù)的設(shè)置。假設(shè)我們此前從未用過read.delim函數(shù),為了更好地了解R中參數(shù)的意義,則需要閱讀幫助文檔?;蛘?,假設(shè)我們不知道read.delim這個(gè)函數(shù)的存在,但需要用一個(gè)函數(shù)將分隔字段的數(shù)據(jù)讀到一個(gè)數(shù)據(jù)框中。R提供了一些有用的函數(shù)來解決這些問題:?read.delim#讀取一個(gè)函數(shù)的幫助文檔??base:delim#在所有base包的幫助文檔中搜索'delim'help.search("delimited")#在所有的幫助文檔中搜索"delimited"RSiteSearch("parsingtext")#在R官方網(wǎng)站上搜索"parsingtext"在第一個(gè)例子中,我們?cè)诤瘮?shù)名前面加了個(gè)問號(hào)。這樣就會(huì)打開這個(gè)函數(shù)的幫助文檔,這是R中很有用的一個(gè)快捷方式。我們也可以在一個(gè)程序包中搜索一個(gè)特定詞,這需要??和:結(jié)合使用。雙問號(hào)表示搜索一個(gè)指定的詞。在這個(gè)例子中,我們用雙冒號(hào)表示在所有base包的函數(shù)中搜索指定詞delim。R也允許你進(jìn)行半結(jié)構(gòu)化的幫助搜索,這會(huì)用到help.search和RSiteSearch。help.search能在所有已安裝的程序包中搜索指定的詞,如上述例子中的delimited。另外,還可以用RSiteSearch搜索R網(wǎng)站上的幫助文檔和郵件列表。請(qǐng)注意,千萬別以為我們已經(jīng)把這章要用的函數(shù)或者所有R相關(guān)的知識(shí)都回顧完了。我們極力推薦你自己獨(dú)立地用這些搜索函數(shù)去研究R的其他基本函數(shù)。回到UFO的數(shù)據(jù)處理上,為了正確地讀取數(shù)據(jù),我們得給read.delim函數(shù)手動(dòng)設(shè)置一些參數(shù)。首先,需要告訴函數(shù)數(shù)據(jù)字段是怎么分隔的。我們知道這個(gè)文件是制表符分隔文件,所以把sep設(shè)置為制表符。然后,read.delim函數(shù)在讀取數(shù)據(jù)的過程中會(huì)用一些啟發(fā)式規(guī)則把每一行轉(zhuǎn)換成R的數(shù)據(jù)類型。在本例中,每一行的數(shù)據(jù)類型都是strings(字符串),但是所有read.*函數(shù)都默認(rèn)把字符串轉(zhuǎn)換為factor類型,這個(gè)類型是用來表示分類變量(categoricalvariable)的,并不是我們想要的。因此,我們需要設(shè)置stringsAsFactors=FALSE來防止其轉(zhuǎn)換。實(shí)際上,把這個(gè)默認(rèn)值設(shè)置為FALSE一般都不會(huì)錯(cuò),尤其是處理不熟悉的數(shù)據(jù)時(shí)。此外,這份數(shù)據(jù)第一行并沒有表頭,因此還需要把表頭的參數(shù)設(shè)置為FALSE,以防止R默認(rèn)把第一行當(dāng)做表頭。最后,數(shù)據(jù)中有許多空元素,我們想把這些空元素設(shè)置為R中的特殊值NA,為此,我們顯式地定義空字符串為na.string:ufo<-read.delim("data/ufo/ufo_awesome.tsv",sep="\t",stringsAsFactors=FALSE,header=FALSE,na.strings="")注意:上文提到的術(shù)語“分類變量”指的是R中的一種數(shù)據(jù)類型,它表示在一個(gè)分類體系中觀察到的一個(gè)類別成員。在統(tǒng)計(jì)學(xué)中,分類變量是一個(gè)很重要的概念,因?yàn)槲覀儠?huì)關(guān)心:對(duì)于一定的類型,它由哪些特定觀察值構(gòu)成。在R中,用factor(因子)類型表示分類變量,其本質(zhì)上是給每一個(gè)字符串標(biāo)簽賦予一個(gè)數(shù)值。在本例中,我們用as.factor把某些字符串(比如說州的縮寫)轉(zhuǎn)換成分類變量,它會(huì)給數(shù)據(jù)集中每個(gè)縮寫州名賦予一個(gè)獨(dú)一無二的數(shù)值ID。這個(gè)過程我們今后會(huì)多次碰到?,F(xiàn)在,我們已有一個(gè)裝著所有UFO數(shù)據(jù)的數(shù)據(jù)框了。無論何時(shí),只要你操作數(shù)據(jù)框,尤其當(dāng)數(shù)據(jù)是從外部數(shù)據(jù)源讀入時(shí),我們都推薦你手工查看一下數(shù)據(jù)。關(guān)于手工查看數(shù)據(jù),兩個(gè)比較好用的函數(shù)是head和tail。這兩個(gè)函數(shù)會(huì)分別打印出數(shù)據(jù)框中的前六條和后六條數(shù)據(jù)記錄:head(ufo)V1V2V3V4V5V611995100919951009IowaCity,IA<NA><NA>Manrepts.witnessing"flash..21995101019951011Milwaukee,WI<NA>2min.ManonHwy43SWofMilwauk..31995010119950103Shelton,WA<NA><NA>TelephonedReport:CAwomanv..41995051019950510Columbia,MO<NA>2min.Manrepts.son'sbizarresig..51995061119950614Seattle,WA<NA><NA>Anonymouscallerrepts.sigh..61995102519951024BrunswickCounty,ND<NA>30min.Sheriff'sofficecallstore..這個(gè)數(shù)據(jù)框最明顯的特點(diǎn)是每一列的名字沒有實(shí)際意義。參考一下這份數(shù)據(jù)的文檔,我們可以賦予每一列更有意義的標(biāo)簽。給數(shù)據(jù)框每一列賦予有意義的名稱很重要。這樣一來,不管對(duì)自己還是其他人,代碼和輸出都有更強(qiáng)的可讀性。我們會(huì)用到names函數(shù),這個(gè)函數(shù)既能讀取列名,又能寫入列名。我們要根據(jù)數(shù)據(jù)文檔創(chuàng)建一個(gè)與數(shù)據(jù)集的列名相應(yīng)的字符串向量,然后把它作為names函數(shù)唯一的參數(shù)傳入:names(ufo)<-c("DateOccurred","DateReported","Location","ShortDescription","Duration","LongDescription")從head函數(shù)的輸出以及用于創(chuàng)建列標(biāo)簽的文檔可知,數(shù)據(jù)的前兩列是日期。R中的日期是一種特殊的數(shù)據(jù)類型,這和其他編程語言沒什么不同,因此我們想把日期字符串轉(zhuǎn)換為這種真正的日期數(shù)據(jù)類型。這需要用到as.Date函數(shù),給它輸入日期字符串,它會(huì)嘗試將其轉(zhuǎn)換為Date對(duì)象。在這份數(shù)據(jù)中,字符串的日期格式是不太常見的YYYYMMDD。因此,需要給as.Date指定一個(gè)日期格式字符串,這樣它才知道該怎么轉(zhuǎn)換。我們從第一列DateOccurred開始轉(zhuǎn)換:ufo$DateOccurred<-as.Date(ufo$DateOccurred,format="%Y%m%d")Errorinstrptime(x,format,tz="GMT"):inputstringistoolong我們?cè)庥隽说谝粋€(gè)錯(cuò)誤!盡管不知道錯(cuò)在哪,但是這個(gè)錯(cuò)誤提到了"inputstringistoolong"(輸入字符串過長(zhǎng)),這說明DateOccurred列中某些數(shù)據(jù)太長(zhǎng)導(dǎo)致日期格式字符串無法匹配。為什么會(huì)出現(xiàn)這種情況呢?我們正在處理的是一個(gè)很大的文本文件,因此可能有些數(shù)據(jù)在原始數(shù)據(jù)集就是畸形的。如果出現(xiàn)了這種情況,這些畸形的數(shù)據(jù)就不能被read.delim函數(shù)正確地解析,從而就導(dǎo)致了如上所示的錯(cuò)誤。因?yàn)槲覀兲幚淼氖钦鎸?shí)世界的數(shù)據(jù),所以必須手工清理數(shù)據(jù)。轉(zhuǎn)換日期字符串及處理畸形數(shù)據(jù)要解決這個(gè)問題首先必須準(zhǔn)確定位這些有缺陷的數(shù)據(jù),然后再?zèng)Q定怎么處理。還好我們能從這個(gè)提示信息中知道錯(cuò)誤的原因是數(shù)據(jù)“過長(zhǎng)”。能夠被正確解析的字符串肯定都是8個(gè)字符,也就是"YYYYMMDD"這種格式的。為找出有問題的數(shù)據(jù)行,我們只需要找出那些長(zhǎng)度在8個(gè)字符以上的字符串。作為一項(xiàng)最佳實(shí)踐,我們首先要查看畸形數(shù)據(jù)到底是什么樣的,以便對(duì)錯(cuò)誤原因有更深的理解。在這個(gè)例子中,我們還是像之前那樣用head函數(shù)來檢查由邏輯運(yùn)算返回的結(jié)果數(shù)據(jù)。然后,為了移除錯(cuò)誤的數(shù)據(jù)行,我們需要用到ifelse函數(shù)來構(gòu)建一個(gè)布爾值向量,以便標(biāo)識(shí)出哪些是8個(gè)字符的字符串(TRUE),哪些不是(FALSE)。ifelse函數(shù)是一個(gè)典型的邏輯開關(guān),用于布爾測(cè)試,而此處用到的是其向量化版本。我們還會(huì)在R中遇到很多向量化操作的例子。這種機(jī)制在用于處理數(shù)據(jù)循環(huán)迭代時(shí)更占優(yōu)勢(shì),因?yàn)檫@通常(但并非總是)比直接對(duì)向量進(jìn)行循環(huán)更有效:head(ufo[which(nchar(ufo$DateOccurred)!=8|nchar(ufo$DateReported)!=8),1])[1]"ler@"[2]"0000"[3]"Callersreportsightinganumberofsoftwhiteballsoflightsheadinginaneasterlydirectingthenchangingdirectiontothewestbeforespeedingofftothenorthwest."[4]"0000"[5]"0000"[6]"0000"good.rows<-ifelse(nchar(ufo$DateOccurred)!=8|nchar(ufo$DateReported)!=8,FALSE,TRUE)length(which(!good.rows))[1]371ufo<-ufo[good.rows,]在這個(gè)搜索過程中,我們用到了一些有用的R函數(shù)。我們需要知道DateOccurred和DateReported這兩列中每一行字符串的長(zhǎng)度,所以用到了nchar函數(shù)。如果長(zhǎng)度不等于8,則返回FALSE。得到了布爾值向量之后,我們想知道數(shù)據(jù)集中有多少畸形數(shù)據(jù)。這樣就用到了which函數(shù),它返回一個(gè)包含F(xiàn)ALSE值的向量。接下來,用length函數(shù)計(jì)算這個(gè)向量的長(zhǎng)度就可以知道畸形數(shù)據(jù)的條數(shù)。僅僅371條數(shù)據(jù)不規(guī)范,最簡(jiǎn)單的辦法就是移除并忽略它們。一開始我們可能會(huì)擔(dān)心丟棄這371條畸形數(shù)據(jù)會(huì)不會(huì)帶來什么后果,但是總共有60000多條數(shù)據(jù),因此簡(jiǎn)單地忽略它們?nèi)缓罄^續(xù)轉(zhuǎn)換其他數(shù)據(jù),不會(huì)有什么影響:ufo$DateOccurred<-as.Date(ufo$DateOccurred,format="%Y%m%d")ufo$DateReported<-as.Date(ufo$DateReported,format="%Y%m%d")接下來,我們需要清洗、組織目擊地點(diǎn)數(shù)據(jù)?;貞浺幌挛覀冎坝胔ead函數(shù)查看到的美國(guó)UFO目擊數(shù)據(jù),地點(diǎn)數(shù)據(jù)的形式是"City,State"(城市,州)。我們可以通過R中集成的正則表達(dá)式,將字符串拆分成兩列,并識(shí)別出不規(guī)范的數(shù)據(jù)行。其中識(shí)別出不規(guī)范數(shù)據(jù)尤為重要,因?yàn)槲覀冎粚?duì)在美國(guó)的UFO目擊數(shù)據(jù)變化趨勢(shì)有興趣,而且用這一步的信息也能把美國(guó)的數(shù)據(jù)單獨(dú)挑出來。組織目擊地點(diǎn)數(shù)據(jù)為了繼續(xù)用上述方式處理數(shù)據(jù),首先要定義一個(gè)輸入為字符串的函數(shù),然后執(zhí)行數(shù)據(jù)清洗工作。接下來用apply函數(shù)的向量化版本將這個(gè)函數(shù)應(yīng)用到地點(diǎn)數(shù)據(jù)列上:get.location<-function(l){split.location<-tryCatch(strsplit(l,",")[[1]],error=function(e)return(c(NA,NA)))clean.location<-gsub("^","",split.location)if(length(clean.location)>2){return(c(NA,NA))}else{return(clean.location)}}上述函數(shù)中有一些細(xì)節(jié)需要注意。首先,strsplit函數(shù)被R的異常處理函數(shù)tryCatch所包圍。其次,并非所有地點(diǎn)都是"City,State"(城市,州)這種格式,甚至有的數(shù)據(jù)連逗號(hào)也沒有。strsplit函數(shù)在遇到不符合格式的數(shù)據(jù)會(huì)拋出一個(gè)異常,因此我們需要捕獲(catch)這個(gè)異常。在本例中,對(duì)于不包含逗號(hào)的數(shù)據(jù),我們會(huì)返回一個(gè)NA向量來表明這條數(shù)據(jù)無效。接下來,由于原始數(shù)據(jù)的開頭有一個(gè)空格,因此用gsub函數(shù)(R的正則表達(dá)式相關(guān)函數(shù)之一)移除每個(gè)字符串開頭的空格。最后,增加一步檢查,確保每個(gè)返回向量的長(zhǎng)度是2。許多非美國(guó)地名中會(huì)有多個(gè)逗號(hào),導(dǎo)致strsplit函數(shù)返回的向量長(zhǎng)度大于2。在這種情形下,我們依然返回NA向量。有了定義好的函數(shù)之后,我們要用到lapply函數(shù)了,它是"list-apply"(應(yīng)用后返回list鏈表)的簡(jiǎn)寫,用來對(duì)Location列的每一條字符串循環(huán)迭代地應(yīng)用我們定義的函數(shù)。前文提到過,R中的apply函數(shù)家族相當(dāng)有用。這些函數(shù)的形式都是apply(vector,function),它們?cè)谥鹨粦?yīng)用到向量元素上之后,返回特定形式的結(jié)果。在本例中,我們用到的是lapply,它返回一個(gè)list鏈表:city.state<-lapply(ufo$Location,get.location)head(city.state)[[1]][1]"IowaCity""IA"[[2]][1]"Milwaukee""WI"[[3]][1]"Shelton""WA"[[4]][1]"Columbia""MO"[[5]][1]"Seattle""WA"[[6]][1]"BrunswickCounty""ND"從例子中可以看出,R中的list是一個(gè)“鍵-值”對(duì)形式的數(shù)據(jù)結(jié)構(gòu)。鍵由雙方括號(hào)索引,值則包含在單方括號(hào)中。在本例中,鍵就是簡(jiǎn)單的整數(shù),但是lists也允許用字符串作為鍵]。雖然把數(shù)據(jù)存儲(chǔ)在list中比較方便,但是卻并不是我們想要的,因?yàn)槲覀兿氚殉鞘泻椭莸男畔⒆鳛椴煌膬闪屑尤氲綌?shù)據(jù)框中。為此,需要把這個(gè)較長(zhǎng)的list轉(zhuǎn)換成一個(gè)兩列的矩陣(matrix),其中city(城市)數(shù)據(jù)作為其首列:location.matrix<-do.call(rbind,city.state)ufo<-transform(ufo,USCity=location.matrix[,1],USState=tolower(location.matrix[,2]),stringsAsFactors=FALSE)為從list構(gòu)造一個(gè)矩陣,我們用到了do.call函數(shù)。和apply函數(shù)類似,do.call函數(shù)是在一個(gè)list上執(zhí)行一個(gè)函數(shù)調(diào)用。我們還會(huì)經(jīng)常把lapply和do.call函數(shù)結(jié)合起來用于處理數(shù)據(jù)。在上述例子中,傳入的函數(shù)是rbind,這個(gè)函數(shù)會(huì)把city.state鏈表中的所有向量一行一行地合并起來,從而創(chuàng)建一個(gè)矩陣。要把這個(gè)矩陣并入數(shù)據(jù)框中,還要用到transform函數(shù)。分別用location.matrix的第一列和第二列創(chuàng)建兩個(gè)新列:USCity和USState。最后,由于州名字的縮寫形式不一致,有的采用大寫形式,有的采用小寫形式,因此我們用tolower函數(shù)把所有的州名字的縮寫都變成小寫形式。處理非美國(guó)境內(nèi)的數(shù)據(jù)數(shù)據(jù)清洗要解決的最后一個(gè)問題就是處理那些形式上符合"City,State",但是實(shí)際上并不在美國(guó)境內(nèi)的數(shù)據(jù)。具體來說,有些UFO目擊地點(diǎn)在加拿大,而這些數(shù)據(jù)同樣符合這樣的形式。幸好加拿大各省的縮寫和美國(guó)各州的縮寫并不匹配。利用這一點(diǎn),我們可以構(gòu)造一個(gè)美國(guó)各州縮寫的向量,讓USState列數(shù)據(jù)來匹配這個(gè)向量,把匹配上的保留下來,從而識(shí)別出非美國(guó)地名:us.states<-c("ak","al","ar","az","ca","co","ct","de","fl","ga","hi","ia","id","il","in","ks","ky","la","ma","md","me","mi","mn","mo","ms","mt","nc","nd","ne","nh","nj","nm","nv","ny","oh","ok","or","pa","ri","sc","sd","tn","tx","ut","va","vt","wa","wi","wv","wy")ufo$USState<-us.states[match(ufo$USState,us.states)]ufo$USCity[is.na(ufo$USState)]<-NA為了找到USState列中不匹配美國(guó)州名縮寫的數(shù)據(jù),我們用到了match函數(shù)。這個(gè)函數(shù)有兩個(gè)參數(shù):第一個(gè)參數(shù)是待匹配的值,第二個(gè)是用于匹配的數(shù)據(jù)。函數(shù)返回值是一個(gè)長(zhǎng)度與第一個(gè)參數(shù)相同的向量,向量中的值是其在第二個(gè)參數(shù)中所匹配的值的索引。如果沒有在第二個(gè)參數(shù)中找到匹配的值,函數(shù)默認(rèn)返回NA。在我們的案例中,我們只關(guān)心哪些數(shù)據(jù)返回值為NA,因?yàn)檫@表明它們沒有匹配上美國(guó)州名。然后,用is.na函數(shù)找出這些不是美國(guó)州名的數(shù)據(jù),并且將其在USState列中的值重置為NA。最后,我們還要把USCity列中對(duì)應(yīng)位置也設(shè)置為NA?,F(xiàn)在原始數(shù)據(jù)框已經(jīng)處理到位,可以從中只抽取出我們感興趣的數(shù)據(jù)了。準(zhǔn)確地說,我們想要的數(shù)據(jù)只是其中發(fā)生在美國(guó)的UFO記錄子集。通過替換前面幾步中不符合條件的數(shù)據(jù),我們用subset命令創(chuàng)建一個(gè)新數(shù)據(jù)框,只保留發(fā)生在美國(guó)的數(shù)據(jù)記錄:ufo.us<-subset(ufo,!is.na(USState))head(ufo.us)DateOccurredDateReportedLocationShortDescriptionDuration11995-10-091995-10-09IowaCity,IA<NA><NA>21995-10-101995-10-11Milwaukee,WI<NA>2min.31995-01-011995-01-03Shelton,WA<NA><NA>41995-05-101995-05-10Columbia,MO<NA>2min.51995-06-111995-06-14Seattle,WA<NA><NA>61995-10-251995-10-24BrunswickCounty,ND<NA>30min.LongDescriptionUSCityUSState1Manrepts.witnessing"flash...IowaCityia2ManonHwy43SWofMilwauk...Milwaukeewi3TelephonedReport:CAwomanv...Sheltonwa4Manrepts.son'sbizarresig...Columbiamo5Anonymouscallerrepts.sigh...Seattlewa6Sheriff'sofficecallstore...BrunswickCountynd聚合并組織數(shù)據(jù)到目前為止,我們已經(jīng)把數(shù)據(jù)組織成可以開始分析的程度了。上一節(jié)專注于規(guī)范數(shù)據(jù)的格式,并篩選出要分析的相關(guān)數(shù)據(jù)。本節(jié)將繼續(xù)探索數(shù)據(jù),以期進(jìn)一步縮小我們需要關(guān)注的范圍。這份數(shù)據(jù)有兩個(gè)基本的維度:空間維度(目擊事件發(fā)生地點(diǎn))和時(shí)間維度(目擊事件發(fā)生時(shí)間)。上一節(jié)我們關(guān)注空間維度,這一節(jié)將關(guān)注時(shí)間維度。首先,我們要對(duì)DateOccured這列數(shù)據(jù)應(yīng)用summary函數(shù),從而對(duì)數(shù)據(jù)的年代范圍有個(gè)基本認(rèn)識(shí):summary(ufo.us$DateOccurred)Min.1stQu.MedianMean3rdQu.Max."1400-06-30""1999-09-06""2004-01-10""2001-02-13""2007-07-26""2010-08-30"令人稱奇的是,這份數(shù)據(jù)時(shí)間跨度很長(zhǎng),最古老的UFO目擊記錄可追溯到1400年前!看到這個(gè)異常的年份數(shù)據(jù),我們不禁要問的是:這份數(shù)據(jù)在時(shí)間上到底是如何分布的?是否值得分析整個(gè)時(shí)間序列?進(jìn)行直觀判斷最快的方法就是構(gòu)建一個(gè)直方圖。我們將在第2章詳細(xì)討論直方圖,不過現(xiàn)在你需要知道的是:直方圖就是讓你在某個(gè)維度上把數(shù)據(jù)劃分成不同的區(qū)間,然后觀察數(shù)據(jù)落入每個(gè)區(qū)間的頻度。此處我們感興趣的維度是時(shí)間,因此構(gòu)建一個(gè)直方圖,把數(shù)據(jù)按照時(shí)間進(jìn)行區(qū)間劃分:quick.hist<-ggplot(ufo.us,aes(x=DateOccurred))+geom_histogram()+scale_x_date(major="50years")ggsave(plot=quick.hist,filename="../images/quick_hist.png",height=6,width=8)stat_bin:binwidthdefaultedtorange/30.Use'binwidth=x'toadjustthis.這里要注意幾點(diǎn)。這是我們第一次用到ggplot2程序包,并將在本書所有需要可視化數(shù)據(jù)的地方用到。在這個(gè)例子中,我們構(gòu)建了一個(gè)非常簡(jiǎn)單的直方圖,它只用了一行代碼。首先,用UFO數(shù)據(jù)框作為初始化參數(shù)創(chuàng)建一個(gè)ggplot對(duì)象。接下來,為了美觀,把x軸設(shè)定為DateOccurred列,因?yàn)檫@一列的頻數(shù)才是我們所感興趣的。ggplot2操作對(duì)象必須是數(shù)據(jù)框,而且創(chuàng)建ggplot2對(duì)象的第一個(gè)參數(shù)也必須是一個(gè)數(shù)據(jù)框。ggplot2是對(duì)LelandWilkinson的圖語法(GrammarofGraphics)[Wil05]的一種R實(shí)現(xiàn)。這說明ggplot2程序包與這種特別的數(shù)據(jù)可視化哲學(xué)是一脈相承的,所有的可視化都是通過一系列的層構(gòu)建而成的。在圖1-5所示的直方圖中,初始層便是x軸的數(shù)據(jù),即UFO的目擊日期。接著用geom_histogram函數(shù)添加一個(gè)直方圖層。在這個(gè)例子中,調(diào)用geom_histogram函數(shù)時(shí)使用了其默認(rèn)參數(shù),而我們?cè)诮窈髸?huì)意識(shí)到,這樣并不是好的選擇。最后,由于數(shù)據(jù)的時(shí)間跨度太大,我們用scale_x_date函數(shù)將x軸標(biāo)簽的時(shí)間周期改為50年。圖1-5UFO數(shù)據(jù)隨時(shí)間變化的直方圖ggplot對(duì)象創(chuàng)建完畢之后,用ggsave函數(shù)可以把可視化結(jié)果輸出到文件里。也可以用print(quick.hist)把可視化結(jié)果輸出到屏幕上。請(qǐng)注意,在輸出可視化結(jié)果時(shí)會(huì)出現(xiàn)警告信息。在直方圖中給數(shù)據(jù)劃分區(qū)間的方式有很多種,在第2章中我們會(huì)詳細(xì)討論,而這里輸出的警告信息清楚地顯示了ggplot2在默認(rèn)情形下是如何給數(shù)據(jù)劃分區(qū)間的。我們現(xiàn)在就用這份可視化結(jié)果對(duì)數(shù)據(jù)一探究竟。從圖1-5可以看出來,結(jié)論顯而易見。絕大部分的目擊事件發(fā)生在1960~2010年,而其中最主要的又發(fā)生在過去20年間。考慮到我們的目的,只需要關(guān)注1990~2010年的數(shù)據(jù)即可。這樣我們就能夠在分析過程中排除異常值,只比較相近時(shí)間區(qū)間的數(shù)據(jù)。和之前一樣,用subset函數(shù)把符合條件的數(shù)據(jù)挑出來以構(gòu)建一個(gè)新的數(shù)據(jù)框:ufo.us<-subset(ufo.us,DateOccurred>=as.Date("1990-01-01"))nrow(ufo.us)#[1]46347雖然這次移除的數(shù)據(jù)比我們之前清洗數(shù)據(jù)時(shí)丟棄的還要多,但是留下來可供分析使用的樣本還有46000多個(gè)。為了看清差異,我們重新對(duì)這個(gè)子集生成直方圖,如圖1-6所示。我們注意到這次樣本差異更加顯著。然后,我們開始組織數(shù)據(jù),希望能回答我們的中心問題:美國(guó)境內(nèi)UFO目擊記錄如果存在周期性規(guī)律,會(huì)是什么規(guī)律?為解答這個(gè)問題,我們首先要問的是:所謂“周期性”是什么?有很多方式可以把時(shí)間序列按照一定周期聚合:按周、按月、按季度、按年,等等。那么這里用哪種方式來聚合數(shù)據(jù)最合適呢?DateOccurred列的數(shù)據(jù)是精確到天的,但是整個(gè)數(shù)據(jù)集的覆蓋面上又存在大量的不一致。我們所需的聚合方式應(yīng)該能讓各個(gè)州的數(shù)據(jù)量分布相對(duì)均勻。此例中,按year-month(年-月)的聚合方式是最佳選擇。這種聚合方式也最能回答我們所提問題的核心,因?yàn)榘茨?月聚合比較容易看出周期性變化。圖1-6UFO子集數(shù)據(jù)隨時(shí)間變化的直方圖(1990~2010)我們需要統(tǒng)計(jì)1990~2010年每個(gè)州每年-月的UFO目擊次數(shù)。首先,我們要在數(shù)據(jù)中新建一個(gè)列,這個(gè)列用于保存和當(dāng)前數(shù)據(jù)中一樣的年和月。用strftime函數(shù)把日期對(duì)象轉(zhuǎn)換成一個(gè)"YYYY-MM"格式的字符串。我們照舊要設(shè)置一個(gè)format參數(shù)來完成轉(zhuǎn)換:ufo.us$YearMonth<-strftime(ufo.us$DateOccurred,format="%Y-%m")需要注意的是,我們沒有用transform函數(shù)給數(shù)據(jù)框添加一個(gè)新列。相反,我們簡(jiǎn)單地引用了一個(gè)并不存在的列名,R就自動(dòng)增加了這個(gè)列。這兩種給數(shù)據(jù)框添加新列的方法都有效,而我們會(huì)根據(jù)具體情況選擇使用其中一種方法。接下來我們需要統(tǒng)計(jì)每個(gè)州在每個(gè)年-月期間目擊UFO的次數(shù)。這里首次用到了ddply函數(shù),此函數(shù)是plyr庫(kù)中的一員,而plyr庫(kù)在處理數(shù)據(jù)方面非常有用。plyr函數(shù)家族的作用有點(diǎn)像前幾年流行起來的map-reduce風(fēng)格的數(shù)據(jù)聚合工具。它們把數(shù)據(jù)按照一定方式分成不同的組,劃分方式對(duì)每一條數(shù)據(jù)都是有意義的,然后對(duì)每個(gè)組進(jìn)行計(jì)算并返回結(jié)果。在本案例中,我們要做的是用“州名縮寫”和“年-月”這一新增加的列來給數(shù)據(jù)分組。數(shù)據(jù)按照這種方式分好組之后,可以對(duì)每個(gè)組進(jìn)行數(shù)據(jù)統(tǒng)計(jì)并把統(tǒng)計(jì)結(jié)果以一個(gè)新列的形式返回。在這里,我們只是簡(jiǎn)單地用nrow函數(shù)按照行數(shù)來化簡(jiǎn)(reduce)每組數(shù)據(jù):sightings.counts<-ddply(ufo.us,.(USState,YearMonth),nrow)head(sightings.counts)USStateYearMonthV11ak1990-0112ak1990-0313ak1990-0514ak1993-1115ak1994-1116ak1995-011現(xiàn)在,我們得到了每個(gè)州在每個(gè)“年-月”里的UFO目擊次數(shù)。不過從調(diào)用head函數(shù)的結(jié)果來看,如果直接使用這份統(tǒng)計(jì)數(shù)據(jù)可能存在一些問題,因?yàn)槠渲杏写罅康闹等笔Я恕1热纾覀兛吹皆诎⒗辜又荩ˋlaska),1990年的1月、3月、5月各有一次目擊記錄,但是沒有2月和4月的記錄。估計(jì)在這期間并沒有UFO的目擊記錄,但是在數(shù)據(jù)集中的這些位置處也沒有包含無UFO目擊事件發(fā)生的記錄,因此,我們得把這些時(shí)間記錄加上,目擊次數(shù)就是0。我們需要一個(gè)覆蓋整個(gè)數(shù)據(jù)集的“年-月”向量。用這個(gè)向量可以檢查哪些“年-月”已經(jīng)存在于數(shù)據(jù)集中,如果不存在就補(bǔ)上,并把次數(shù)設(shè)置為0。為此我們要用seq.Date函數(shù)創(chuàng)建一個(gè)日期序列,然后把格式設(shè)定為數(shù)據(jù)框中的日期格式:date.range<-seq.Date(from=as.Date(min(ufo.us$DateOccurred)),to=as.Date(max(ufo.us$DateOccurred)),by="month")date.strings<-strftime(date.range,"%Y-%m")有了date.strings這個(gè)新的向量,我們還需要新建一個(gè)包含所有年-月和州的數(shù)據(jù)框,然后用這個(gè)數(shù)據(jù)框去匹配UFO目擊數(shù)據(jù)。我們依舊先用lapply函數(shù)創(chuàng)建列,再用do.call函數(shù)將其轉(zhuǎn)換成矩陣并最終轉(zhuǎn)換成數(shù)據(jù)框:states.dates<-lapply(us.states,function(s)cbind(s,date.strings))states.dates<-data.frame(do.call(rbind,states.dates),stringsAsFactors=FALSE)head(states.dates)sdate.strings1ak1990-012ak1990-023ak1990-034ak1990-045ak1990-056ak1990-06現(xiàn)在,數(shù)據(jù)框states.dates包含了每一年、每個(gè)月和每個(gè)州所有組合所對(duì)應(yīng)的所有目擊記錄。請(qǐng)注意,現(xiàn)在已經(jīng)有了阿拉斯加州(Alaska)在1990年2月和3月的記錄了。要給UFO目擊記錄數(shù)據(jù)中的缺失值補(bǔ)上0,我們還需要把這個(gè)新數(shù)據(jù)框和原來的數(shù)據(jù)框合并。為此,需要用到merge函數(shù),給這個(gè)函數(shù)輸入兩個(gè)有序數(shù)據(jù)框,然后它將數(shù)據(jù)框中相同的列合并。在我們的案例中,兩個(gè)數(shù)據(jù)框分別是按照州名的字母順序以及年-月的時(shí)間順序排序的。還要告訴函數(shù)將數(shù)據(jù)框中的哪些列進(jìn)行合并,這就得給參數(shù)by.x和參數(shù)by.y指定每個(gè)數(shù)據(jù)框中對(duì)應(yīng)的列名。最后,把參數(shù)all設(shè)置為TRUE,以告訴函數(shù)要把沒匹配上的數(shù)據(jù)也包含進(jìn)來并填充為NA。以下V1列中的值為NA的記錄即為沒有UFO目擊數(shù)據(jù)的記錄:all.sightings<-merge(states.dates,sightings.counts,by.x=c("s","date.strings"),by.y=c("USState","YearMonth"),all=TRUE)head(all.sightings)sdate.stringsV11ak1990-0112ak1990-02NA3ak1990-0314ak1990-04NA5ak1990-0516ak1990-06NA數(shù)據(jù)聚合的最后一步只是一些簡(jiǎn)單的修修補(bǔ)補(bǔ)。首先,我們要把a(bǔ)ll.sightings數(shù)據(jù)框的列名改成有意義的名稱。方法和本案例一開始的改列名一樣。接下來,要把NA值改為0,這里又要用到is.na函數(shù)。最后要把YearMonth和State列的數(shù)據(jù)轉(zhuǎn)換為合適的類型。用前面創(chuàng)建的date.range向量和rep函數(shù)創(chuàng)建一個(gè)和date.range一模一樣的向量,并把年-月字符串轉(zhuǎn)換為Date對(duì)象。再?gòu)?qiáng)調(diào)一次,把日期保存成Date對(duì)象要比字符串好,因?yàn)榍罢呖梢杂脭?shù)學(xué)方法進(jìn)行比較,而后者卻不容易辦到。同樣,州名縮寫最好用分類變量表示而不用字符串,因此將其轉(zhuǎn)換為factor類型。下一章會(huì)詳細(xì)講解factor及其他R數(shù)據(jù)類型:names(all.sightings)<-c("State","YearMonth","Sightings")all.sightings$Sightings[is.na(all.sightings$Sightings)]<-0all.sightings$YearMonth<-as.Date(rep(date.range,length(us.states)))all.sightings$State<-as.factor(toupper(all.sightings$State))現(xiàn)在,要用可視化方法分析數(shù)據(jù)了!分析數(shù)據(jù)對(duì)于這份數(shù)據(jù),我們只用可視化的方式回答前面提出的核心問題。在本書的其余部分,我們會(huì)結(jié)合數(shù)值分析和可視化分析,但由于本案例僅用作介紹R編程的核心范例,因此只需要用可視化分析即可。和之前的直方圖可視化不同的是,這里我們要更為深入地使用ggplot2程序包來明明白白地構(gòu)建一個(gè)個(gè)的圖層。按照這種方式,我們就可以構(gòu)建這樣一個(gè)可視化結(jié)果:它可以直接回答每個(gè)州UFO目擊記錄隨時(shí)間變化的周期性規(guī)律問題,而且看上去也更加專業(yè)。下面的例子一次性構(gòu)建好了所有的可視化結(jié)果,接下來將分別介紹其中每個(gè)圖層的意義:state.plot<-ggplot(all.sightings,aes(x=YearMonth,y=Sightings))+geom_line(aes(color="darkblue"))+facet_wrap(~State,nrow=10,ncol=5)+theme_bw()+scale_color_manual(values=c("darkblue"="darkblue"),legend=FALSE)+scale_x_date(breaks="10years")+xlab("Time")+ylab("NumberofSightings")+opts(title="NumberofUFOsightingsbyMonth-YearandU.S.State(1990-2010)")ggsave(plot=state.plot,filename=file.path("images","ufo_sightings.pdf"),width=14,height=8.5)依照慣例,第一步還是用一個(gè)數(shù)據(jù)框作為第一個(gè)參數(shù)來創(chuàng)建一個(gè)ggplot對(duì)象。這里我們用到了前面所創(chuàng)建的數(shù)據(jù)框all.sightings。在這里,照樣為了繪圖的美觀,先要?jiǎng)?chuàng)建一個(gè)圖層,x軸是YearMonth列,y軸是Sightings數(shù)據(jù)。然后,為了表現(xiàn)各州的周期性變化,我們給每一個(gè)州繪制一幅曲線圖。這樣就方便觀察每個(gè)州UFO目擊數(shù)隨時(shí)間變化的峰值、平緩區(qū)、波動(dòng)區(qū)。為此,我們要用到geom_line函數(shù),并將color的值設(shè)置為"darkblue"(深藍(lán)色)以便讓圖形更顯眼。通過整個(gè)例子我們看到UFO目擊數(shù)據(jù)相當(dāng)大,覆蓋了相當(dāng)長(zhǎng)一段時(shí)期內(nèi)美國(guó)所有州的記錄。有鑒于此,我們需要設(shè)計(jì)一種方法,將可視化結(jié)果進(jìn)行拆分,從而既能觀察到每個(gè)州的數(shù)據(jù),又能比較不同州之間的數(shù)據(jù)。如果我們把所有數(shù)據(jù)繪制在一個(gè)圖板中,那很難觀察到差別。為了確認(rèn)這種方式的確不可行,將上面代碼塊的前兩行[3]中的color="darkblue"替換為color=State,并在控制臺(tái)輸入>print(state.plot),然后運(yùn)行。更好的方法是把每個(gè)州的數(shù)據(jù)單獨(dú)繪制圖形,并將圖形在網(wǎng)格中按順序放好,這樣易于進(jìn)行比較。為了創(chuàng)建出一個(gè)分塊繪制的圖形,我們用到facet_wrap函數(shù),并指明圖形面板的構(gòu)造使用了變量State,它是一個(gè)factor類型,即分類變量。我們也要明確定義網(wǎng)格的行列數(shù),這個(gè)比較容易,因?yàn)槲覀円呀?jīng)知道了一共有50個(gè)不同的圖形。ggplot2程序包有很多不同的圖形繪制主題。默認(rèn)的繪制主題就是我們?cè)诘谝粋€(gè)繪制例子中用到的:灰色背景、深灰色網(wǎng)格線。嚴(yán)格來講,這只是個(gè)人喜好問題,但是在這里我們傾向用白色背景,因?yàn)檫@樣可以在可視化結(jié)果中更容易看到數(shù)據(jù)之間的不同之處。我們添加了theme_bw層,這個(gè)圖層會(huì)用白色背景和黑色網(wǎng)格線繪制圖形。在操作ggplot2更熟練之后,我們推薦你多嘗試不同的繪制主題,然后找到自己最鐘愛的一個(gè)。其余圖層的創(chuàng)建只是為了錦上添花,讓可視化結(jié)果在視覺和感覺上都更專業(yè)一些。雖然無人對(duì)此苛求,但正是這些細(xì)節(jié)讓繪制的可視化數(shù)據(jù)更貼近專業(yè)性而非業(yè)余。scale_color_manual函數(shù)用來指明字符串"darkblue"相當(dāng)于網(wǎng)頁安全色"darkblue"。雖然這樣看上去有些重復(fù)、多余,但這正是ggplot2的設(shè)計(jì)核心,它需要明確定義諸如顏色這樣的細(xì)節(jié)。事實(shí)上,ggplot2傾向于用顏色來區(qū)別不同的數(shù)據(jù)類型或分類,因此它偏向于用factor類型來指明顏色。在前面的案例中,我們明確將顏色定義成了一個(gè)字符串類型,因此還要用scale_color_manual函數(shù)定義這個(gè)字符串的值。我們同樣用scale_x_date函數(shù)指明可視化結(jié)果中主要的網(wǎng)格線。因?yàn)檫@份數(shù)據(jù)時(shí)間跨度是20年,所以要將其間隔設(shè)置為5年,然后,將四位數(shù)格式的年份作為坐標(biāo)系的刻度標(biāo)簽。接著用xlab和ylab函數(shù)分別將x軸的名稱定為Time(目擊時(shí)間),y軸的名稱設(shè)置為NumberofSightings(目擊次數(shù))。最后,用opts函數(shù)給整幅圖賦予一個(gè)標(biāo)題。opts函數(shù)還有很多的選項(xiàng)可設(shè)置,在后面的章節(jié)中我們也會(huì)用到其中一些,但是還有更多的功能本書沒有涉及。所有圖層都已經(jīng)完成,現(xiàn)在用ggsave函數(shù)把結(jié)果渲染成圖像并分析數(shù)據(jù)。分析之后,可以發(fā)現(xiàn)很多有趣的現(xiàn)象(見圖1-7)。我們看到加利福尼亞州(California)和華盛頓州(Washington)的UFO目擊次數(shù)明顯多于其他各州。而這兩個(gè)州之間也有一些有趣的區(qū)別,加利福尼亞州UFO目擊次數(shù)在時(shí)間分布上比較隨機(jī),但在1995年之后又穩(wěn)步增長(zhǎng),然而華盛頓州的UFO目擊次數(shù)隨時(shí)間的周期性變化則始終如一,自1995年開始,其曲線的波峰和波谷都比較有規(guī)律。圖1-7美國(guó)各州每年-月UFO目擊次數(shù)(1990~2010年)我們也觀察到,許多州的UFO目擊次數(shù)都出現(xiàn)過突增情況。例如,亞利桑那州(Arizona)、佛羅里達(dá)州(Florida)、伊利諾伊州(Illinois)以及蒙大拿州(Montana)在1997年出現(xiàn)過次數(shù)突增,密歇根州(Michigan)、俄亥俄州(Ohio)以及俄勒岡州(Oregon)在1999年末出現(xiàn)過相似的突增情況。但是在這些州中,只有密歇根州(Michigan)和俄亥俄州(Ohio)在地理上鄰近。如果我們不相信這些是天外來客造訪的結(jié)果,那有沒有其他可能的解釋呢?興許美國(guó)人在世紀(jì)之交對(duì)天空很警覺,常常仰望天空,因此才有了比以前多的錯(cuò)誤目擊記錄。然而,如果你贊同外太空訪客真的經(jīng)常造訪地球這種說法,的確有證據(jù)可以激發(fā)你想繼續(xù)探究的好奇心。實(shí)際上,通過對(duì)地區(qū)聚類,也能得到證據(jù)發(fā)現(xiàn)在美國(guó)許多州都有令人稱奇的、穩(wěn)定的周期性目擊記錄。這些目擊記錄似乎真的包含了一些有意義的模式。深入學(xué)習(xí)R的參考書目學(xué)習(xí)完這個(gè)入門案例絕不能說明我們已經(jīng)把這門語言完全介紹給大家了。我們只是用這個(gè)案例介紹了一些R中加載、清洗、組織以及分析數(shù)據(jù)所用到的模式。在接下來的其他章節(jié)里,我們不僅會(huì)多次重復(fù)用到其中的許多函數(shù)、處理過程,我們還會(huì)介紹一些在這個(gè)案例里還沒涉及的知識(shí)。在繼續(xù)學(xué)習(xí)之前,對(duì)于那些希望獲得更多實(shí)踐機(jī)會(huì)以增強(qiáng)對(duì)R熟悉程度的讀者而言,有很多很棒的學(xué)習(xí)資源可供參考。這些資源大體上可以分為參考書、文獻(xiàn)以及網(wǎng)上資源,如表1-3所示。在第2章我們將介紹探索性數(shù)據(jù)分析。本章的案例包含了較多的數(shù)據(jù)探索,但是我們處理得比較簡(jiǎn)單快速。下一章我們會(huì)更加慎重地對(duì)待數(shù)據(jù)探索的過程。第2章數(shù)據(jù)分析分析與驗(yàn)證在數(shù)據(jù)處理方面,一個(gè)屢試不爽的方法就是:把任務(wù)清晰地分解成分析和驗(yàn)證兩步。把數(shù)據(jù)處理分為分析和驗(yàn)證由著名的JohnTukey首先提出,他強(qiáng)調(diào)要為實(shí)際數(shù)據(jù)分析設(shè)計(jì)簡(jiǎn)單的工具。在JohnTukey看來,數(shù)據(jù)分析這一步要做的就是用摘要表(summarytable)和基本可視化方法從數(shù)據(jù)中尋找隱含的模式。本章揭示如何用R中的基本方法來建立數(shù)據(jù)的摘要表,然后再講解怎樣從這個(gè)表中看出門道。之后,將列舉R中一些用于可視化數(shù)據(jù)的工具和方法,同時(shí),還會(huì)簡(jiǎn)要介紹基本可視化模式。在開始第一次數(shù)據(jù)集分析之旅前,我們得提醒,一個(gè)真實(shí)存在的危險(xiǎn)在時(shí)時(shí)窺伺你:你找到的模式也許并不存在。人類的大腦天生就能發(fā)現(xiàn)宇宙中的模式,甚至在不太可能出現(xiàn)模式的地方也能發(fā)現(xiàn)??匆谎郯自?,眨眼間就能發(fā)現(xiàn)云的形狀,這跟知道多少統(tǒng)計(jì)學(xué)知識(shí)無關(guān)。很多人都深信自己可以在普通的字里行間,比如莎翁的戲劇,發(fā)現(xiàn)隱藏的信息。因?yàn)槿祟惡苋菀装l(fā)現(xiàn)一些經(jīng)不起仔細(xì)推敲的模式,所以就不能只有數(shù)據(jù)分析這一步,必須還要有驗(yàn)證過程??梢赃@樣來看待數(shù)據(jù)驗(yàn)證:數(shù)據(jù)分析階段的可視化結(jié)果雜亂——有時(shí)甚至是毫無章法,這種情況讓我們處理起來有些吃力,需要厘清思路,此時(shí)數(shù)據(jù)驗(yàn)證就會(huì)發(fā)揮作用。數(shù)據(jù)驗(yàn)證通常有兩種方法:·如果你認(rèn)為自己在一個(gè)新的數(shù)據(jù)集上發(fā)現(xiàn)了模式,那就用另一批數(shù)據(jù)來測(cè)試這個(gè)模式的正規(guī)模型。·利用概率論來測(cè)試你在原始數(shù)據(jù)集中發(fā)現(xiàn)的模式是否只是巧合。相比數(shù)據(jù)分析,因?yàn)閿?shù)據(jù)驗(yàn)證對(duì)數(shù)學(xué)水平要求較高,所以本章只涉及數(shù)據(jù)的分析方法。也就是說在具體的案例中我們只關(guān)注數(shù)據(jù)的數(shù)值摘要(numericsummary)和一些標(biāo)準(zhǔn)的可視化方法。我們講到的數(shù)值摘要就是一些基本的統(tǒng)計(jì)項(xiàng)目:均值(mean)和眾數(shù)(mode)、百分位數(shù)(percentile)和中位數(shù)(median)、標(biāo)準(zhǔn)差(standarddeviation)和方差(variance)。我們要用到的可視化工具也是最基本的,你可能在統(tǒng)計(jì)學(xué)入門課程上已經(jīng)學(xué)過了:直方圖、核密度估計(jì)以及散點(diǎn)圖。這些簡(jiǎn)單的可視化方法可能一度得不到重視,但是我們會(huì)讓你相信,僅用這些基本的方法也能從數(shù)據(jù)中挖掘出有用的信息。本書后面的章節(jié)才會(huì)涉及許多較高深的技術(shù),但是,要訓(xùn)練數(shù)據(jù)分析的直覺,最好就是用簡(jiǎn)單的方法去操作數(shù)據(jù)。什么是數(shù)據(jù)在介紹數(shù)據(jù)分析的基本方法之前,我們需要對(duì)“數(shù)據(jù)”這個(gè)概念統(tǒng)一認(rèn)識(shí)。對(duì)“數(shù)據(jù)”這個(gè)概念所有可能的定義可以用一整書來論述,因?yàn)閷?duì)任何所謂的“數(shù)據(jù)集”你都可能有一堆重要的問題要問。例如,你可能經(jīng)常想知道你手中的數(shù)據(jù)是如何產(chǎn)生的,你也想知道這些數(shù)據(jù)能否代表真正要研究的數(shù)據(jù)總體。通過研究亞馬遜印第安人婚史,你可能已經(jīng)掌握了關(guān)于他們社會(huì)結(jié)構(gòu)的很多知識(shí),但是能否從中得到一些適用于其他文明的知識(shí)卻不得而知。對(duì)數(shù)據(jù)進(jìn)行解釋需要對(duì)數(shù)據(jù)來源有一定的了解。通常,唯一能區(qū)別因果關(guān)系和相關(guān)關(guān)系的方法就是要知道數(shù)據(jù)由何而來:是從實(shí)驗(yàn)中得

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論