基礎知識
其優(yōu)點
- 有大量統(tǒng)計建模凯楔,機器學習锦募,可視化的相關包,快速實現(xiàn)你的想法
- 很前沿鸥拧,因為統(tǒng)計學和機器學習的研究人員會為最新的研究成果而開發(fā)一個包
- 對函數(shù)式編程很支持
缺點:
- 使用者大多數(shù)不是程序員党远,很多是為了解決一些問題而編寫的沟娱,代碼可能存在很多缺點腕柜。
- 在各種包中,甚至基礎 R 語言中砰蠢,都存在不一致的情況唉铜。 你面對的是已經(jīng)進化了超過 20 年的 R 語言。 R 語言的學習很困難竞惋,因為我們需要記住很多特殊的情況。
- R 語言不是特別快的編程語言拆宛,寫得很差 R 語言代碼可以變得非常緩慢讼撒。 R語言也非常消耗內(nèi)存。
讀完你會獲得什么:
- 生產(chǎn)高質(zhì)量代碼的能力
- 了解原理钳幅,理解復雜的數(shù)據(jù)類型炎滞,并且學習對他們進行操作的做好方法。對函數(shù)的工作有更好的理解,認識和使用R語言的四種面向?qū)ο笙到y(tǒng)丽惭。
- 理解什么是函數(shù)式編程,以及為什么函數(shù)式編程是數(shù)據(jù)分析有利的工具柜砾,
- 理解元編程
- R語言那些操作很慢换衬,那些操作很消耗內(nèi)存证芭,能夠有很好的直覺废士,你將知道如何使用分析工具來確定性能的瓶頸,以及學習足夠的C++知識官硝,以便將R語言轉(zhuǎn)化為等價的C++代碼短蜕。
- 輕松閱讀大多數(shù)R語言代碼,熟悉術語岖研,并且能夠評判別人的代碼警检。
元技術
有兩種元技術(Meta-techniques)非常有利于提高R語言程序員的能力,閱讀源代碼以及采取科學的思路赃磨。
閱讀你經(jīng)常使用的函數(shù)和包的源代碼洼裤。發(fā)現(xiàn)一些有價值的內(nèi)容,可以嘗試模仿值骇。
科學的思維方式就是移国,如果你不理解某種事物,那就首先提出一個假設迹缀,然后設計一些實驗,接著運行他們票摇,最后記錄結(jié)果砚蓬。
推薦閱讀:
《Structure and Interpretation of Computer Programs》
《Concepts, Techniques and Models of Computer Programming》
《The Pragmatic Programmer》
數(shù)據(jù)結(jié)構
五種數(shù)據(jù)結(jié)構
使用str()
可以查看數(shù)據(jù)結(jié)構
幾個問題:
- 除了包含的數(shù)據(jù)以外,向量的三個性質(zhì)是什么隔躲?
- 四種常見的原子向量類型是什么?兩種罕見的是什么
- 屬性是什么宣旱,如何存儲屬性
- 原子向量與列表有什么不同教届?矩陣和數(shù)據(jù)框有什么不同
- 列表也可以是矩陣嗎?數(shù)據(jù)框能把矩陣作為一列數(shù)據(jù)嗎买置?
向量
最基本的結(jié)構是向量强霎,其有兩種形式,原子向量與列表城舞。他們有三種相同的屬性。
類型:typeof
他是什么
長度:length
它包含多少元素
屬性:attributes
額外的任意元素
他們的不同在于元素類型脱柱,原子向量中的元素必須是同一類型的拉馋,列表的元素可以是不同類型的。
注:is.vector()并不能測試一個對象是不是向量随闺。 相反蔓腐,僅當對象是除了名字以
外,不包含其它屬性時回论,它才返回 TRUE。 所以笨使,請使用 is.atomic(x) || is.list(x)來
測試一個對象是不是向量僚害。
原子向量
四種常見的原子向量類型:邏輯,整數(shù)靶草,雙精度岳遥,字符類型。不討論兩種罕見類型派继,復數(shù)類型捻艳,raw類型
原子箱里那個通常使用c()
來建立。其是單詞combine 的縮寫
type_of來測試類型或者使用is開頭的一系列函數(shù)绅络。
強制轉(zhuǎn)換嘁字,因為原子向量都必須是同一類型的,當你試圖合并不同類型的數(shù)據(jù)時纪蜒,將向最靈活的類型進行強制轉(zhuǎn)換。 以靈活程度排序随珠,從小到大依次為:邏輯杆烁、整數(shù)、雙精度浮點數(shù)和字符烤芦。
當邏輯向量被強制轉(zhuǎn)換為整數(shù)或者雙精度浮點數(shù)類型時析校,TRUE 將變成 1,F(xiàn)ALSE
將變成 0遂唧。 這項特性使得邏輯向量與 sum()和 mean()函數(shù)結(jié)合使用時吊奢,變得非常
方便。
列表
創(chuàng)建列表用list
列表有時被稱為遞歸向量,因為一個列表可以包含其它列表: 這使得它們從根本
上不同于原子向量铺呵。
對列表調(diào)用 typeof()函數(shù)隧熙,得到的結(jié)果是列表。 你可以用 is.list()來測試列表音念,或
者使用 as.list()來強制轉(zhuǎn)換成列表躏敢。 你可以使用 unlist()把一個列表轉(zhuǎn)換為原子向
量。 如果列表中的元素具有不同的類型肝谭,那么 unlist()將使用與 c()相同的強制轉(zhuǎn)
換規(guī)則蛾扇。
列表用來建立 R 語言中的許多更加復雜的數(shù)據(jù)結(jié)構。 比如镀首,數(shù)據(jù)框和線性模型對象都是列表:
屬性
所有向量可以擁有任意多個附加屬性,附加屬性用來存取與該對象相關的元數(shù)據(jù)芋齿。屬性可以看作是已經(jīng)命名的列表成翩。
屬性可以通過strr
進行一個個訪問,也可以使用attributes
函數(shù)一次性進行訪問栅炒。
structure()函數(shù)返回一個帶有被修改了屬性的新對象:
structure(1:10, my_attribute = "This is a vector")
#> [1] 1 2 3 4 5 6 7 8 9 10
#> attr(,"my_attribute")
#> [1] "This is a vector"
但是术羔,有三種重要的屬性不會丟失:
- 名字(name),一個字符向量级历,用來為每一個元素賦予一個名字,將在第
2.2.0.1 節(jié)介紹玩讳。 - 維度(dimension),用來將向量轉(zhuǎn)換成矩陣和數(shù)組熏纯,將在第 2.3 節(jié)介紹。
- 類(class),用于實現(xiàn) S3 對象系統(tǒng)掐场,在第 7.2 節(jié)介紹。
這些屬性中的每一個都有特定的訪問函數(shù)來存取它們的屬性值萍膛。 當訪問這些屬性
時嚷堡,請使用 names(x)、class(x)和 dim(x)串塑,而不是 attr(x, "names")北苟、attr(x, "class")
和 attr(x, "dim")。
你可以使用 unname(x)創(chuàng)建沒有名字的新向量友鼻,或者使用 names(x) <- NULL 去掉名字。
因子
因子構建與整數(shù)向量之上妆档,虫碉,并帶有了兩個屬性:
- 類(class)
- 水平(level)
有時,當從文件里直接讀取數(shù)據(jù)框時纤虽,你認為某列應該產(chǎn)生數(shù)值向量绞惦,但是卻變
成了因子。 這是由于這一列中有非數(shù)值數(shù)據(jù)造成的杰刽,通常菠发,缺失值使用.或者-這樣
的特殊符號來表示滓鸠。 為了避免這個情況第喳,可以先把因子向量轉(zhuǎn)換成字符向量,然
后再從字符向量轉(zhuǎn)換到雙精度浮點數(shù)向量(這個過程之后曲饱,務必檢查缺失值!)楔敌。
當然驻谆,一個更好的方法是從一開始就積極尋找出現(xiàn)問題的原因,并予以修改勺卢;在
read.csv()中使用 na.strings 參數(shù)來解析缺失值字符区端,通常會更好。
矩陣與數(shù)組
為原子向量添加一個dim屬性杨何,可以讓它變成多維數(shù)組沥邻。 數(shù)組的一種特例是矩陣,即二維數(shù)組唐全。 矩陣在統(tǒng)計學中使用得非常廣泛。 高維數(shù)組則用得少多了弥雹,但是也需要一定的了解延届。 矩陣和數(shù)組是由 matrix()和 array()函數(shù)創(chuàng)建的,或者通過使用 dim()函數(shù)對維度(dimension)屬性進行設置來得到厕吉。
length()和 names()在任何維度上都可以使用,而對于矩陣和數(shù)組头朱,則有更細分的
函數(shù):
- length(): 對于矩陣,nrow()和 ncol()分別獲取行數(shù)和列數(shù)班眯;對于數(shù)組烁巫,dim()
獲取每個維度。 - names(): 對于矩陣程拭,rownames()和 colnames()分別獲取行名和列名恃鞋;對于數(shù)
組亦歉,dimnames()獲取每個維度的名字。
cbind()和 rbind()函數(shù)是 c()函數(shù)對矩陣的推廣水由;abind()函數(shù)是 c()函數(shù)對數(shù)組的推
廣(由 abind 包提供)赛蔫。 你可以使用 t()轉(zhuǎn)置一個矩陣;它對數(shù)組的推廣鞠值,則是
aperm()函數(shù)渗钉。 你可以使用 is.matrix()和 is.array()來測試一個對象是不是矩陣或者
數(shù)組,或者查看 dim()函數(shù)返回的維度值声离。 as.matrix()和 as.array()使向量轉(zhuǎn)化為
矩陣或數(shù)組變得簡單瘫怜。 向量不是僅有的一維數(shù)據(jù)結(jié)構。 你可以創(chuàng)建單行或者單列
矩陣宝磨,也可以創(chuàng)建單維數(shù)組盅安。 它們看起來很像别瞭,但是行為是不同的株憾。 它們的區(qū)別
并不是那么重要,但是當你運行某些函數(shù)(比如 tapply()函數(shù)常出現(xiàn)這個情況)得到
了奇怪的輸出時墙歪,你要能想到它們的存在贝奇。 同樣地,使用 str()可以查看它們的區(qū)
別掉瞳。
數(shù)據(jù)框
數(shù)據(jù)框是 R 語言中最常用的存儲數(shù)據(jù)的方式,如果使用得當霎褐,可以使數(shù)據(jù)分析工作變得更輕松 數(shù)據(jù)框是由等長向量
構成的列表该镣。 它也是二維結(jié)構,所以它具有矩陣和列表雙重屬性省艳。 也就是說嫁审,數(shù)據(jù)框擁有 names()、colnames()和rownames()枣购,盡管 names()和 colnames()對數(shù)據(jù)框來說是一樣的擦耀。 數(shù)據(jù)框的 length()是列表的長度,所以和 ncol()相同眷蜓;nrow()則得到行數(shù)。
使用data.frame
來創(chuàng)建數(shù)據(jù)框.
測試和強制轉(zhuǎn)換
由于數(shù)據(jù)框是 S3 類德召,它是由向量構建而成,所以它的類型反映出向量的特性:它
是列表上岗。 要檢查一個對象是不是數(shù)據(jù)框,可以使用 class()函數(shù)或者is.data.frame()
函數(shù):
#> [1] "list"
class(df)
#> [1] "data.frame"
is.data.frame(df)
#> [1] TRUE
你可以使用 as.data.frame()
把一個對象轉(zhuǎn)換成數(shù)據(jù)框:
- 一個原子向量會創(chuàng)建單列數(shù)據(jù)框肴掷。
- 列表中的每個元素會成為數(shù)據(jù)框的一列;如果元素的長度不同台夺,則會發(fā)生錯
誤痴脾。 - n 行 m 列的矩陣會轉(zhuǎn)換為 n 行 m 列數(shù)據(jù)框
####### 特殊列
由于數(shù)據(jù)框是一個包含向量的列表,所以數(shù)據(jù)框的某個是列表類型是有可能的:
df <- data.frame(x = 1:3)
df$y <- list(1:2, 1:3, 1:4)
df
#> x y
#> 1 1 1, 2
#> 2 2 1, 2, 3
#> 3 3 1, 2, 3, 4
然而,當把列表傳入 data.frame()函數(shù)時钝鸽,該函數(shù)將試圖把列表的每一個元素都放
到單獨的一列中瞳购,所以学赛,下面的代碼會失敗:
data.frame(x = 1:3, y = list(1:2, 1:3, 1:4))
#> Error: arguments imply differing number of rows: 2, 3, 4
一種繞開的方法是使用 I()函數(shù),它使得 data.frame()把列表看成一個整體單元: