本文是對(duì)R語言一個(gè)學(xué)習(xí)總結(jié),共包括如下章節(jié)內(nèi)容:
- 什么是R語言
- 開發(fā)環(huán)境搭建
- 基本語法
- 向量
- 列表和矩陣
- 讀寫數(shù)據(jù)
- 繪制圖形
- 函數(shù)式特性
- 小結(jié)
一、什么是R語言
顧名思義,R語言特石,它首先是一門計(jì)算機(jī)編程語言,就跟傳統(tǒng)的C語言鳖链,Java語言類似姆蘸。R語言是一門圖靈完備的語言,這意味著可以用R語言來進(jìn)行任何編程撒轮。
但是R語言天生為數(shù)據(jù)統(tǒng)計(jì)而生乞旦,所以,它做不到像C語言那般的普適题山,數(shù)據(jù)統(tǒng)計(jì)分析兰粉、統(tǒng)計(jì)建模、數(shù)據(jù)可視化才是它的舞臺(tái)顶瞳。
R語言最初是由新西蘭奧克蘭奧克蘭大學(xué)統(tǒng)計(jì)系的Ross Ihaka和Robert Gentleman寫的玖姑。 R語言于1993年首次亮相愕秫。2000年,第一版R.1.0.0正式發(fā)布焰络。目前最新的版本是R3.5.3戴甩。
R語言有如下特點(diǎn):
1、R是屬于GNU系統(tǒng)的一個(gè)自由闪彼、免費(fèi)甜孤、源代碼開放的軟件,R語言源代碼托管在github畏腕。
2缴川、R語言是一種腳本語言,源碼不需要編譯描馅,解釋執(zhí)行把夸。
3、R語言支持面向?qū)ο缶幊堂郏举|(zhì)上它是一種函數(shù)式編程語言恋日。
4、R語言存在大量的擴(kuò)展包嘹狞,它們提供了各種豐富的數(shù)據(jù)統(tǒng)計(jì)分析功能岂膳。
5、R語言是跨平臺(tái)的刁绒,可在各種操作系統(tǒng)下進(jìn)行開發(fā)和運(yùn)行闷营。
二烤黍、開發(fā)環(huán)境搭建
(一)下載安裝
R語言的官網(wǎng)地址是 https://www.r-project.org/知市。我們更多的是使用CRAN(The Comprehensive R Archive Network),地址是https://cran.r-project.org/mirrors.html。CRAN提供了提供了上百個(gè)鏡像網(wǎng)站速蕊,這些鏡像分布在世界各地嫂丙。R鏡像是為了方便世界各地的使用者下載R軟件及相關(guān)擴(kuò)展包。各地的鏡像都是R網(wǎng)站的備份文件规哲,完全一樣跟啤。所以,選擇離你最近的鏡像唉锌,你下載R軟件或R包的速度相對(duì)較快隅肥。
比如在國內(nèi)可以到https://mirrors.tuna.tsinghua.edu.cn/CRAN/去下載。
R語言提供了各種操作系統(tǒng)上可安裝的版本袄简。在本文中我們下載安裝windows下的版本腥放。我們下載的是基礎(chǔ)的Base版本,下載后得到一個(gè)可執(zhí)行程序R-3.5.3-win.exe绿语,大小80M左右秃症,可以看出R軟件是非常精簡的候址。我們直接雙擊該安裝程序進(jìn)行安裝。
安裝完成后种柑,安裝后的目錄結(jié)構(gòu)如下:
其中bin目錄下有兩個(gè)可執(zhí)行程序岗仑,R.exe和Rscript.exe,其中R.exe是一個(gè)命令行開發(fā)工具,可以交互式的執(zhí)行編寫和執(zhí)行R代碼聚请,可以很方便的用來學(xué)習(xí)R語言荠雕。但在實(shí)際開發(fā)環(huán)境下,我們會(huì)將編寫的源代碼保存到腳本文件中驶赏,這時(shí)可以用Rscript.exe來執(zhí)行R腳本舞虱,R語言源碼文件的擴(kuò)展名為R。
為了方便調(diào)用這兩個(gè)可執(zhí)行程序母市,我們可以把bin目錄加入到環(huán)境變量中矾兜。在linux下安裝的R語言環(huán)境,也有類似的可執(zhí)行程序患久。
(二)R命令行工具
我們運(yùn)行R.exe椅寺,會(huì)出現(xiàn)一個(gè)控制臺(tái)程序,顯示的信息如下:
R version 3.5.3 (2019-03-11) -- "Great Truth"
Copyright (C) 2019 The R Foundation for Statistical Computing
Platform: x86_64-w64-mingw32/x64 (64-bit)
R
'license()''licence()'
R.
'contributors()'
'citation()'RR
'demo()''help()'
'help.start()'HTML
'q()'R.
>
最后一行的>是個(gè)提示符蒋失,可以輸入R代碼返帕。我們來看一個(gè)最簡單例子,如下:
> print("hello,world")
[1] "hello,world"
>
我們輸入代碼print("hello,world")篙挽,回車后輸出[1] "hello,world"荆萤,這里實(shí)際是調(diào)用R語言基礎(chǔ)庫中的print函數(shù)。
輸入q()可退出命令行程序铣卡。
(三)查看幫助
R語言提供了豐富的幫助功能链韭,可以查看各種函數(shù)的功能。在命令行下只需調(diào)用help函數(shù)即可煮落。比如:
> help(print)
starting httpd help server ... done
我們輸入help(print)敞峭,回車后,會(huì)輸出信息starting httpd help server ... done蝉仇,然后會(huì)自動(dòng)彈出瀏覽器旋讹,在瀏覽器中顯示print函數(shù)的幫助信息。我們可以通過這種方式在命令行下邊練習(xí)轿衔、邊查看幫助绪颖。
(四)腳本執(zhí)行
下面我們看下屑咳,如何執(zhí)行R腳本莹菱」冻埽看一個(gè)簡單例子:
1、打開任何文本編輯器裙秋,新建一文本琅拌,文本中只有一行代碼缨伊,如:
print ( "hello,world")
2、保存文件為test.R
3进宝、調(diào)用Rscript.exe執(zhí)行腳本刻坊,如:
bin\Rscript.exe rexample\test.R
說明:實(shí)際練習(xí)時(shí)注意引用實(shí)際的路徑。
(五)RStudio開發(fā)環(huán)境
R語言提供的命令行開發(fā)工具R.exe功能比較簡單党晋。有一款第三方的開發(fā)工具RStudio谭胚,RStudio是一款可視化的R語言開發(fā)工具,功能很強(qiáng)大未玻,可以在各種操作系統(tǒng)下運(yùn)行灾而。
其官方網(wǎng)站是https://www.rstudio.com/。
本文不會(huì)使用RStudio扳剿,本文的例子使用交互式命令行或腳本文件來展示旁趟。
(六)擴(kuò)展包
R語言程序的編寫主要是使用R語言自身和第三方提供的函數(shù)來實(shí)現(xiàn)。這些函數(shù)按照功能分類存儲(chǔ)在一個(gè)個(gè)的包中庇绽。這些包物理上位于安裝后目錄的library目錄下锡搜,每個(gè)包對(duì)應(yīng)一個(gè)子目錄(其中包含了R代碼、幫助文件瞧掺、數(shù)據(jù)集等)耕餐,如下面界面:
R語言發(fā)行版中已經(jīng)提供了很多有用的功能包,如上面界面所顯示的辟狈。
但R語言社區(qū)也提供大量的可擴(kuò)展包肠缔,可供我們選擇使用。擴(kuò)展包中也包含了R代碼哼转、幫助文件明未、數(shù)據(jù)集等。
有很多網(wǎng)站都提供R擴(kuò)展包的下載释簿,不過最重要的是CRAN亚隅,https://cran.r-project.org這個(gè)網(wǎng)站硼莽。
要使用擴(kuò)展包庶溶,首先需要安裝擴(kuò)展包到本地的R語言的安裝目錄下。R語言所有的標(biāo)準(zhǔn)包和第三方擴(kuò)展包都位于安裝后目錄的library目錄下懂鸵,每個(gè)包對(duì)應(yīng)一個(gè)子目錄偏螺。
我們有兩種方式可以下載安裝擴(kuò)展包,一種是可以在R命令行程序下運(yùn)行命令來在線安裝匆光;第二種是下載擴(kuò)展包文件套像,離線安裝。
本文我們介紹離線安裝的方式终息,比如我們想安裝fortunes擴(kuò)展包(該擴(kuò)展包包含了很多從R社區(qū)摘錄下來的言論)夺巩。在國內(nèi)贞让,我們可以到https://mirrors.tuna.tsinghua.edu.cn/CRAN/網(wǎng)站上找到該擴(kuò)展包,下載二進(jìn)制的版本柳譬,我們這里是windows系統(tǒng)喳张,所以下載的是fortunes_1.5-4.zip文件。把fortunes_1.5-4.zip文件解壓到library目錄下美澳,會(huì)生成一個(gè)fortunes目錄销部,fortunes目錄的目錄結(jié)構(gòu)如下,這是一個(gè)擴(kuò)展包的典型結(jié)構(gòu):
(七)導(dǎo)入包
要使用包中的函數(shù)制跟,需要先使用library函數(shù)將擴(kuò)展包加載進(jìn)來才能使用(類似java中的import)舅桩,然后就可以調(diào)用擴(kuò)展包中提供的各種函數(shù)。如下面例子:
> library(fortunes)
> fortune("This is R")
Evelyn Hall: I would like to know how (if) I can extract some of the
information from the summary of my nlme.
Simon Blomberg: This is R. There is no if. Only how.
-- Evelyn Hall and Simon 'Yoda' Blomberg
R-help (April 2005)
在上面例子中雨膨,我們?cè)赗命令行程序下先輸入執(zhí)行l(wèi)ibrary(fortunes)擂涛,即調(diào)用library函數(shù)將fortunes包加載到當(dāng)前執(zhí)行環(huán)境中,包名fortunes可以不用引號(hào)括起來聊记。然后我們調(diào)用fortune函數(shù)歼指,傳入?yún)?shù)"This is R",執(zhí)行后返回一段文字甥雕。我們也可以不帶參數(shù)調(diào)用fortune函數(shù)踩身,如fortune(),這時(shí)會(huì)隨機(jī)返回一段文字社露。我們一樣可以調(diào)用help函數(shù)查看第三方包提供的函數(shù)的幫助信息挟阻,如help(fortune),這時(shí)會(huì)打開瀏覽器顯示fortune函數(shù)的幫助信息峭弟。
需要說明的是附鸽,不僅對(duì)于第三方擴(kuò)展包,對(duì)于R版本自帶的包瞒瘸,除位于基礎(chǔ)包中的函數(shù)被調(diào)用前不需要導(dǎo)入包(如print函數(shù)所在的包)坷备,其它包也需要先用library函數(shù)導(dǎo)入后才能使用其中中的函數(shù)。
三情臭、基本語法
(一)風(fēng)格
R語言程序源碼程序有如下的風(fēng)格:
1省撑、每條語句不需要有分號(hào)結(jié)尾。
2俯在、區(qū)分大小寫竟秫,如變量命名、函數(shù)命名跷乐。
3肥败、單行注釋采用 # ,#后面的內(nèi)容都被忽略。不支持多行注釋馒稍。
4皿哨、點(diǎn)號(hào)可以是標(biāo)識(shí)符的一部分,如 age.of.tom 可以是一個(gè)變量名纽谒,不是如java,python等編程語言中的對(duì)對(duì)象成員的引用往史。
5、聲明變量和賦值采用<-運(yùn)算符佛舱,而不是傳統(tǒng)的=運(yùn)算符椎例。
6、字符串既可以用單引號(hào)请祖、也可以用雙引號(hào)括起來订歪。
(二)數(shù)據(jù)類型
同其它編程語言一樣,R語言的數(shù)據(jù)也是有類型的肆捕,基本的數(shù)據(jù)類型有如下幾種:
數(shù)值型
布爾型:常量只有兩個(gè)TRUE 和 FALSE 刷晋,分別表示真和假
字符串:可以用單引號(hào)或雙信號(hào)括起,如 “a”慎陵,“abc”, ‘xy’
同樣眼虱,R語言也有變量的概念,舉個(gè)例子席纽,在R命令行下運(yùn)行:
> v<-12
> print(v)
[1] 12
上面代碼定義了一個(gè)變量捏悬,變量名為v,變量的值為整數(shù)12润梯。在R語言中过牙,不需要顯示的聲明數(shù)據(jù)的類型。
說明:R語言實(shí)際并不存在一個(gè)基本類型的變量纺铭,R語言中的單個(gè)值(如整數(shù)12)本質(zhì)是一個(gè)只包含一個(gè)元素的向量對(duì)象寇钉,關(guān)于向量的詳細(xì)含義在后面的章節(jié)會(huì)介紹。
需要特別注意的是舶赔,字符串與字符串的連接不能用+號(hào)扫倡,如:
“hello”+”,world”
上面的寫法是錯(cuò)誤的,執(zhí)行會(huì)報(bào)錯(cuò)竟纳。
可以用內(nèi)置的函數(shù)paste將字符串連在一起撵溃,如:
> re<-paste("hello","world")
> print(re)
[1] "hello world"
R語言提供了豐富的針對(duì)字符串的操作,包括查找蚁袭、正則表達(dá)式等征懈,本文對(duì)這些不做詳細(xì)介紹。
(三)函數(shù)
在編寫R語言程序時(shí)揩悄,我們可以提供R語言自帶的包和第三方包提供的各種函數(shù),也可以定義自己的函數(shù)鬼悠。
在R語言中删性,定義函數(shù)使用function關(guān)鍵字亏娜,其基本語法如下:
函數(shù)名 <- function(參數(shù)列表) {
函數(shù)體
}
下面我們看一個(gè)簡單例子:
plus <- function(a,b){
print(a)
print(b)
return(a*2+b)
}
re<-plus(3,5)
print(re)
上面代碼定義了一個(gè)函數(shù)plus,然后調(diào)用了這個(gè)函數(shù)蹬挺。使用RScript執(zhí)行上面腳本维贺,輸出信息如下:
[1] 3
[1] 5
[1] 11
R語言的函數(shù)除上面的標(biāo)準(zhǔn)定義和調(diào)用外,還有如下一些特點(diǎn)巴帮,如:
1溯泣、函數(shù)調(diào)用的參數(shù)可以按照函數(shù)中定義的順序提供,也可以以不同的順序提供榕茧,但需要指定參數(shù)名垃沦,如下面例子:
re<-plus(b=5,a=3)
上面代碼調(diào)用了plus函數(shù),傳入的參數(shù)指定參數(shù)名用押,不是按順序傳入肢簿。
2、在定義函數(shù)時(shí)設(shè)置參數(shù)的值蜻拨,這樣在調(diào)用函數(shù)時(shí)池充,如果不傳入值,這些設(shè)置的值就作為參數(shù)的默認(rèn)值缎讼。如下面腳本:
plus <- function(a=1,b=2){
print(a)
print(b)
return(a*2+b)
}
re<-plus()
print(re)
可以看出收夸,定義plus方法,給參數(shù)設(shè)置了值血崭,在調(diào)用函數(shù)時(shí)咱圆,可以不傳入值。執(zhí)行上面腳本功氨,輸出信息如下:
[1] 1
[1] 2
[1] 4
3序苏、省略return語句
定義函數(shù)時(shí),可以省略return語句捷凄,這樣函數(shù)體最后一行代碼作為表達(dá)式的值就作為函數(shù)的返回值忱详,如下面腳本代碼:
plus <- function(a,b){
a*2+b
}
re<-plus(3,5)
print(re)
執(zhí)行上面腳本,輸出信息是:
[1] 11
4跺涤、省略{}:如果函數(shù)體只有一行代碼匈睁,則可以省略{},該行代碼可以直接放在參數(shù)列表的后面桶错。如下面函數(shù)定義也是正確的:
plus <- function(a,b) a*2+b
5航唆、變參:R語言也支持任意數(shù)量參數(shù)傳入,用....表示院刁,放在參數(shù)列表的最后糯钙,如下面例子:
show <- function(a,...){
args = list(...)
print(args)
}
show(12,"hello",TRUE,20)
上面代碼中的show函數(shù),有兩個(gè)參數(shù),第一個(gè)參數(shù)是a任岸,第二參數(shù)是用...表示再榄,表示可以傳入任意個(gè)值。在函數(shù)體中利用 list(...)可以獲取到傳入的這些變參值享潜,是一個(gè)列表困鸥。執(zhí)行上面腳本,輸出信息如下:
[[1]]
[1] "hello"
[[2]]
[1] TRUE
[[3]]
[1] 20
說明剑按,關(guān)于R語言中列表疾就,可以理解成包含一些列元素的集合。
(四)if條件語句
同c語言艺蝴,java等語言類似猬腰,R語言也支持if條件語句,用法和c語言吴趴,java類似漆诽。下面簡單介紹下。
1锣枝、if語句
if語句由一個(gè)布爾表達(dá)式后跟一個(gè)語句塊(含1條或多條語句)組成厢拭。其語法格式如下:
if(boolean_expression) {
一條或多條語句
}
如果布爾表達(dá)式的計(jì)算結(jié)果為true,那么if語句中的代碼塊將被執(zhí)行撇叁。 如果布爾表達(dá)式的計(jì)算結(jié)果為false供鸠,則語句塊中代碼不被執(zhí)行。
舉例:
if(1==1){
print(2)
print(3)
}
如果if的語句塊只有一個(gè)語句陨闹,則可以省略{}楞捂,該語句可直接跟在布爾表達(dá)式后面,如:
if(1==2) print(2)
print(3)
2趋厉、if...else...語句
if語句后面可以跟一個(gè)可選的else語句寨闹,當(dāng)布爾表達(dá)式為false時(shí)執(zhí)行。其語法格式如下:
if(boolean_expression) {
語句塊(當(dāng)布爾表達(dá)式為true時(shí)執(zhí)行)
} else {
語句塊(當(dāng)布爾表達(dá)式為false時(shí)執(zhí)行)
}
3君账、if ... else if ... else語句
if語句后面可以跟可選的else if 及else語句繁堡,其語法格式如下:
if(boolean_expression 1) {
// Executes when the boolean expression 1 is true.
} else if( boolean_expression 2) {
// Executes when the boolean expression 2 is true.
} else if( boolean_expression 3) {
// Executes when the boolean expression 3 is true.
} else {
// executes when none of the above condition is true.
}
有幾點(diǎn)需要注意的:
1)可以有1個(gè)或多個(gè)else if語句
2)可以沒有else語句
3)從上往下匹配,一旦if后的布爾表達(dá)式或某個(gè)else if后的布爾表達(dá)式被匹配乡数,剩余的條件不會(huì)被測(cè)試椭蹄。
(五)for循環(huán)語句
R語言提供了for語句可以對(duì)向量、列表等集合對(duì)象中的值進(jìn)行逐一遍歷净赴,其語法格式如下:
for (item in values){
語句塊
}
其中values是集合對(duì)象绳矩,item是對(duì)其中元素的引用。如下面例子:
for(i in 1:5){
print(i)
}
說明玖翅,1:5 代表包含了5個(gè)元素的向量翼馆,關(guān)于向量的含義割以,后面章節(jié)會(huì)詳細(xì)介紹,這里把它理解成一個(gè)數(shù)組(或集合)即可写妥。
執(zhí)行上面腳本拳球,輸出信息是
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
說明审姓,如果{}中的語句塊只有一個(gè)語句珍特,則{}可省略,這點(diǎn)同c語言魔吐,java的語法扎筒。
R語言也支持break語句,可以設(shè)置提前跳出循環(huán)酬姆,如下面例子:
for(i in 1:5){
print(i)
if(i==3)
break
}
運(yùn)行上面腳本嗜桌,輸出信息如下:
[1] 1
[1] 2
[1] 3
說明,R語言的循環(huán)中不支持continue語句辞色。
四骨宠、向量
向量是R語言中最重要的一個(gè)特性,是R語言數(shù)據(jù)統(tǒng)計(jì)分析的基礎(chǔ)相满。R語言的向量是一種對(duì)象(數(shù)據(jù)結(jié)構(gòu))层亿,它是一組一維的數(shù)據(jù),其中每個(gè)元素的類型是相同的立美,類似其它語言中的一維數(shù)組(或列表)匿又。
與其它編程語言不同的是,單個(gè)值建蹄,如整數(shù) 12碌更,字符串 “hello”,布爾類型值TRUE 等也是一個(gè)向量洞慎,只不過該向量只包含一個(gè)元素痛单。這是R語言的一個(gè)重要特點(diǎn)。在前面的章節(jié)劲腿,我們只涉及到單個(gè)類型的值旭绒,其實(shí)它們都是向量。
在絕大部分運(yùn)算中谆棱,能使用單個(gè)元素向量(如12快压,”hello”,TRUE)的地方,也能使用包含多個(gè)元素的向量垃瞧。但也有特列蔫劣,比如if語句后面的邏輯表達(dá)式,表達(dá)式的值只能是一個(gè)只包含單個(gè)布爾值的布爾向量个从。
下面我們來詳細(xì)介紹如何在R語言中使用向量脉幢。
(一)創(chuàng)建向量
上面提到歪沃,在R語言中單個(gè)值就是一個(gè)向量,顯然嫌松,最簡單的向量沪曙,如 12, TRUE, “hello”這些常量萎羔。我們可以定義向量變量液走,如:
v<-12
v<-TRUE
另外我們可以通過冒號(hào)運(yùn)算符:來定義連續(xù)值的整型向量,如 1:3 是個(gè)整型向量贾陷,其中含1~3這三個(gè)元素缘眶。如下面例子:
> 1:3
[1] 1 2 3
> 2:8
[1] 2 3 4 5 6 7 8
> 12:15
[1] 12 13 14 15
> v<-20:22
> print(v)
[1] 20 21 22
我們可以通過R語言的標(biāo)準(zhǔn)函數(shù)c來連接向量,如下面例子:
> v<-c(2,3)
> print(v)
[1] 2 3
上面的函數(shù)c將兩個(gè)單元素向量連接一起髓废,生成一個(gè)含兩個(gè)元素的向量巷懈。
再看一個(gè)例子:
> v<-c(c(2,3),c(6,7))
> print(v)
[1] 2 3 6 7
可以看出,函數(shù)是c把各個(gè)向量中的單個(gè)元素抽取出(扁平化)組成新的向量慌洪。
data<- c(“hello”,”world”,”yes”)
上面語句聲明了一個(gè)變量data顶燕,并創(chuàng)建了一個(gè)字符向量對(duì)象賦值給該變量。
需要說明的是NULL表示一個(gè)空向量冈爹,如:
v<-NULL
上面語句聲明了一個(gè)向量變量涌攻,初始內(nèi)容為空。
(二)向量的運(yùn)算
從數(shù)據(jù)結(jié)構(gòu)的角度看犯助,和其它編程語言相比癣漆,向量并沒有特別的地方,就是一個(gè)數(shù)組剂买、或者列表之類的數(shù)據(jù)結(jié)構(gòu)惠爽,是個(gè)集合對(duì)象。
對(duì)于集合數(shù)據(jù)的運(yùn)算瞬哼,傳統(tǒng)的編程語言往往有兩種方式:一是利用循環(huán)遍歷集合中的元素婚肆;二是采用高階函數(shù)+Lambda表達(dá)式(需要支持函數(shù)式編程的語言)。關(guān)于對(duì)集合數(shù)據(jù)的操作坐慰,可參看文檔《函數(shù)式編程之集合操作》较性。
而R語言的向量運(yùn)算在傳統(tǒng)語言的基礎(chǔ)上,還提供了更簡潔和強(qiáng)大的功能结胀,我們先看一個(gè)簡單例子感受下赞咙,先定義一個(gè)向量如下:
v<-c(3,5,8,10)
如果我們希望通過向量v生成一個(gè)新的向量,新向量中每個(gè)元素的的值是原向量中元素的兩倍糟港。熟悉函數(shù)式編程語言的會(huì)立即想到攀操,這就是一個(gè)map操作,比如在scala語言(其它語言操作類似)中我們可以這么實(shí)現(xiàn):
var data =List(2,4,5)
var newdata = data.map(item=>item*2)
上述代碼執(zhí)行后 newdata 變量指向的集合內(nèi)容為 List(4, 8, 10)。
對(duì)于不支持函數(shù)式編程的語言门扇,我們要實(shí)現(xiàn)上述功能,可采用傳統(tǒng)的for循環(huán)方式來實(shí)現(xiàn)梧疲,比如在R語言中我們也可以用for循環(huán)來實(shí)現(xiàn)颠放,如下面代碼:
data<-NULL
for(i in c(2,5,7))
data[length(data)+1]<-i*2
print(data)
運(yùn)行上面代碼排惨,輸出的信息是 [1] 4 10 14
但是在R語言中實(shí)現(xiàn)這個(gè)功能有一種更簡單方式,即直接通過運(yùn)算符來實(shí)現(xiàn)碰凶,如下面代碼:
> v<-c(2,5,7)*2
> print(v)
[1] 4 10 14
可以看出暮芭,我們直接使用基本的算數(shù)運(yùn)算符*就可以實(shí)現(xiàn)。
在其它編程語言中痒留,一般算術(shù)運(yùn)算符只能針對(duì)單個(gè)值進(jìn)行操作谴麦,但因?yàn)镽語言中蠢沿,單個(gè)值也是一個(gè)向量伸头,所以R語言中的運(yùn)算符可以針對(duì)向量進(jìn)行運(yùn)算,即R語言中的運(yùn)算符都是向量化的舷蟀。
(三)數(shù)學(xué)運(yùn)算符
同別的語言一樣恤磷,R語言也支持各種算術(shù)運(yùn)算符,如+ 野宜,-扫步,*,/等匈子。但與別的語言不同的是河胎,R語言的算術(shù)運(yùn)算符都支持對(duì)向量的運(yùn)算。下面我們以最常見的+運(yùn)算符來說明虎敦。
對(duì)于 x+y 這個(gè)加法運(yùn)算游岳,其含義如下:
1、如果x和y都是單元素向量其徙,則就如普通的數(shù)學(xué)運(yùn)算胚迫,如 3+5 ,結(jié)果是8唾那。
2访锻、如果x和y有一個(gè)是單元素向量,另一個(gè)是多元素向量闹获,則結(jié)果就是該單元素向量中的元素值和多元素向量中的每個(gè)元素相加期犬,返回的是相加后的多元素向量。如 c(2,3,4) +2 結(jié)果是 (4,5,6)避诽。
3龟虎、如果x和y都是多元素向量,且元素?cái)?shù)量相同茎用,則會(huì)按照元素順序各元素相加遣总,返回相加后的向量睬罗。如 c(1,2) +c (4,5) 結(jié)果是 (5,7)。
4旭斥、如果x和y都是多元素向量容达,但元素?cái)?shù)量不相同,比如x的元素?cái)?shù)量是m個(gè)垂券,y的數(shù)量是m+n個(gè)花盐,則結(jié)果向量的元素個(gè)數(shù)是m+n個(gè),前m個(gè)元素的值是x和y的前m個(gè)元素一一相加的結(jié)果菇爪,后n元素的值是x向量的第1個(gè)元素和y向量的后n個(gè)元素的一一相加的結(jié)果算芯。如 c(1,2)+c(4,5,6) 結(jié)果是 (5,7,7)。需要說明的是凳宙,這種情況運(yùn)行時(shí)會(huì)出現(xiàn)警告提示熙揍,但不影響上面說的結(jié)果輸出。
上面是以+運(yùn)算符為例來說明向量運(yùn)算的規(guī)則氏涩,其它數(shù)學(xué)運(yùn)算規(guī)則類似届囚,這里就不一一介紹。
(四)向量的屬性
使用str函數(shù)可以查看向量的結(jié)構(gòu)是尖,如下面例子:
> str(12)
num 12
> str(c(12,16) )
num [1:2] 12 16
> str(c(2,4,6))
num [1:3] 2 4 6
> str(c("hello","world"))
chr [1:2] "hello" "world"
使用length函數(shù)可以獲取到向量中元素的個(gè)數(shù)意系,如下面例子:
> length(12)
[1] 1
> length(c(12,16) )
[1] 2
> length(c(2,4,6))
[1] 3
(五)向量值的獲取
我們可以通過位置索引獲取向量中的元素,因?yàn)閱蝹€(gè)值也是個(gè)向量饺汹,實(shí)際是返回包含一個(gè)元素的子向量蛔添。如下面例子:
> x<-c(2,4,5)[1]
> print(x)
[1] 2
> x<-c(2,4,5)[3]
> print(x)
[1] 5
可以看出,向量的位置索引是從1開始的兜辞,即第一個(gè)元素的索引是1迎瞧,這點(diǎn)與其它語言的數(shù)組(列表)等數(shù)據(jù)結(jié)構(gòu)的索引從0開始是不同的。
(六)向量修改
反過來弦疮,我們還可以通過索引給向量增加元素或修改某個(gè)元素的值夹攒,下面舉例介紹。我們先看一段代碼:
> x<-NULL
> x[1]<-12
> x[2]<-20
> x[4]<-30
> print(x)
[1] 12 20 NA 30
首先通過x<-NULL聲明一個(gè)空的向量胁塞,NULL表示空向量咏尝。
x[1]<-12 是往向量的第1個(gè)位置添加元素。上面代碼我們直接越過了索引3往第4個(gè)索引添加元素啸罢,R語言也是允許的编检,因?yàn)榈?個(gè)索引沒有設(shè)置元素,可以看出當(dāng)調(diào)用print函數(shù)顯示向量的內(nèi)容時(shí)扰才,第三個(gè)元素顯示NA允懂,即值不存在。
在上面代碼的基礎(chǔ)上衩匣,我們繼續(xù)執(zhí)行:
> x[2]<-33
> x[3]<-5
> print(x)
[1] 12 33 5 30
可以看出蕾总,第2個(gè)元素的內(nèi)容發(fā)生了變化粥航,第3個(gè)元素也有了內(nèi)容。
五生百、列表和矩陣
R語言除了提供了最基本的向量對(duì)象递雀,還有列表、矩陣蚀浆、數(shù)組缀程、因子、數(shù)據(jù)幀等對(duì)象市俊。在本文中杨凑,我們只對(duì)列表、矩陣進(jìn)行介紹摆昧。
(一)列表
列表是R語言對(duì)象撩满,它可以包含不同類型的元素,如數(shù)字据忘,字符串鹦牛,向量和其中的另一個(gè)列表。 列表還可以包含矩陣或函數(shù)作為其元素勇吊。 列表是使用list()函數(shù)創(chuàng)建的。如下面例子:
list_data <- list("Red", "Green", c(21,32,11), TRUE, 51.23, 119.1)
print(list_data)
可以看出窍仰,上面創(chuàng)建的列表包含各種類型的元素汉规,這點(diǎn)與向量不同,向量中的元素要求是同類型的驹吮。
列表還有一個(gè)特點(diǎn)時(shí)针史,可以給列表中的元素命名,如下面例子:
data<-list(1,"tom",20)
names(data)<-c("id","name","age")
上面的第二行代碼通過names函數(shù)給列表中的每個(gè)元素設(shè)定了一個(gè)名稱碟狞。
下面就可以通過名稱來引用到列表中的元素啄枕,格式是 列表變量$元素名稱,如下面例子:
> data$id
[1] 1
> data$name
[1] "tom"
> data$age
[1] 20
上面代碼演示了如何通過名稱來獲取列表中的元素族沃。
同向量一樣频祝,列表也支持通過索引來獲取列表中的元素,如下面例子:
> data[1]
$id
[1] 1
> data[2]
$name
[1] "tom"
針對(duì)列表脆淹,R語言還有很多豐富的操作常空,本文不再詳細(xì)介紹。
(二)矩陣
矩陣是其中元素以二維矩形布局布置的R對(duì)象盖溺,其包含相同原子類型的元素漓糙。 雖然我們可以創(chuàng)建一個(gè)只包含字符或只包含邏輯值的矩陣,但它們沒有太多用處烘嘱。 大部分場(chǎng)景下使用包含數(shù)字元素的矩陣用于數(shù)學(xué)計(jì)算昆禽。
使用matrix()函數(shù)創(chuàng)建一個(gè)矩陣蝗蛙,其語法格式如下:
matrix(data, nrow, ncol, byrow, dimnames)
各個(gè)參數(shù)的含義如下:
1)data參數(shù)是矩陣的數(shù)據(jù)元素的輸入向量
2)nrow是要?jiǎng)?chuàng)建的矩陣的行數(shù)
3)ncol是要?jiǎng)?chuàng)建的矩陣的列數(shù)
4)byrow是一個(gè)邏輯線索。 如果為TRUE醉鳖,則輸入向量元素按行排列歼郭。默認(rèn)為FALSE,輸入向量元素按列排列辐棒。
5)dimname是分配給行和列的名稱病曾。
下面我們通過例子來說明:
> data<-matrix(1:6,3,2)
> print(data)
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
上面代碼的第一行語句創(chuàng)建了一個(gè)3行2列的矩陣,向量1:6中的數(shù)據(jù)正好填滿整個(gè)矩陣漾根,因?yàn)閎yrow參數(shù)是默認(rèn)值為FALSE,所以向量中的數(shù)據(jù)按照列來排列泰涂。如果我們傳入TRUE,效果如下:
> data<-matrix(1:6,3,2,TRUE)
> print(data)
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
可以看出,向量中數(shù)據(jù)在矩陣中按行排列辐怕。
如果我們給定的向量中的元素個(gè)數(shù)少于矩陣的單元格數(shù)據(jù)逼蒙,來看下有什么效果,代碼如下:
> data<-matrix(1:4,3,2)
Warning message:
In matrix(1:4, 3, 2) : [4][3]
> print(data)
[,1] [,2]
[1,] 1 4
[2,] 2 1
[3,] 3 2
我們會(huì)發(fā)現(xiàn)寄疏,R語言會(huì)重復(fù)用向量中的元素來填充矩陣是牢,這時(shí)運(yùn)行時(shí)會(huì)給出了警告。
在創(chuàng)建矩陣時(shí)陕截,可以只給出行的數(shù)量驳棱,R語言會(huì)自動(dòng)根據(jù)向量中的元素個(gè)數(shù)計(jì)算出矩陣的列的數(shù)量,如下面代碼:
> data<-matrix(1:6,3)
> print(data)
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
上面代碼农曲,我們只指定了矩陣的行數(shù)為3社搅,沒有指定列的數(shù)量。但因?yàn)橄蛄恐械脑貫?乳规,R語言自動(dòng)計(jì)算出矩陣的列為2形葬,所以最后創(chuàng)建的是3行2列的矩陣。
下面我們來看下如何設(shè)置矩陣的行和列的名稱暮的,舉例如下:
> rownames = c("row1", "row2", "row3")
> colnames = c("col1", "col2")
> data<-matrix(1:6,3,dimnames = list(rownames, colnames))
> print(data)
col1 col2
row1 1 4
row2 2 5
row3 3 6
可以看出笙以,可以通過dimnames 參數(shù)來設(shè)置行和列的名稱。
可以通過使用元素的列和行索引來訪問矩陣的元素冻辩,針對(duì)上面創(chuàng)建的矩陣猖腕,我們可以如此獲取其中的元素,如:
> print(data[1,2])
[1] 4
可以看出微猖,data[1,2]就獲取了第1行谈息,第2列的元素。
再比如我們要獲取第3行第1的元素凛剥,可以如下:
> print(data[3,1])
[1] 3
矩陣在數(shù)學(xué)中是個(gè)非常重要的工具侠仇,會(huì)有各種矩陣的運(yùn)算,R語言也支持矩陣的豐富運(yùn)算,很多運(yùn)算符都支持矩陣的操作逻炊,我們下面看一個(gè)簡單例子:
> data1<-matrix(1:6,3)
> data2<-matrix(1:6,3)
> data<-data1+data2
> print(data)
[,1] [,2]
[1,] 2 8
[2,] 4 10
[3,] 6 12
可以看出互亮,+運(yùn)算符作用在矩陣上,最后的結(jié)果也是一個(gè)矩陣余素,新矩陣中的每個(gè)元素是運(yùn)算的兩個(gè)矩陣的各個(gè)元素的和豹休。
我們?cè)倏匆粋€(gè)乘法運(yùn)算,如下面例子:
> data1<-matrix(1:6,3)
> data2<-matrix(1:6,3)
> data<-data1*data2
> print(data)
[,1] [,2]
[1,] 1 16
[2,] 4 25
[3,] 9 36
可以看出桨吊,計(jì)算機(jī)制和加法類似威根,只不過元素之前由相加變成了相乘。
上面只是針對(duì)R語言矩陣的最基本運(yùn)算视乐,R語言還有針對(duì)矩陣的更多操作洛搀,本文不再詳細(xì)介紹。
六佑淀、讀寫數(shù)據(jù)
在R語言中留美,我們可以從存儲(chǔ)在R語言環(huán)境外的文件、數(shù)據(jù)庫中讀取數(shù)據(jù)伸刃, 我們還可以將數(shù)據(jù)寫入將外部的文件和數(shù)據(jù)庫中谎砾。 R語言可以讀取和寫入各種文件格式,如csv捧颅,excel景图,xml等。
對(duì)于文本文件(csv是文本文件的一種)隘道,R語言基礎(chǔ)庫中提供了函數(shù)進(jìn)行支持症歇。對(duì)于excel,xml,外部數(shù)據(jù)庫需要下載擴(kuò)展包來支持。
下面我們來以讀取csv文件中的內(nèi)容舉例進(jìn)行說明谭梗。
假設(shè)某個(gè)person.csv的內(nèi)容如下:
id,name,age
1,tom,20
2,mike,30
我們可以通過如下代碼讀取文件中信息,如下:
data <- read.csv("person.csv")
print(data)
需要說明的是宛蚓,如果不指定文件路徑激捏,該文件必須處于當(dāng)前工作環(huán)境目錄下,在R語言中凄吏,可以通過函數(shù)getwd()來獲取當(dāng)前的工作目錄远舅,可以通過setwd()來設(shè)置當(dāng)前的工作目錄。
因?yàn)閏sv文件的列之前以逗號(hào)分隔痕钢,對(duì)于讀取更通用的文本文件图柏,如列之間以tab鍵分隔,可以使用更通用的函數(shù)read.table來讀取任连,該函數(shù)提供了更多可選的參數(shù)設(shè)置蚤吹。
關(guān)于對(duì)其它文件和數(shù)據(jù)庫的訪問,本文不再介紹。
七裁着、繪制圖形
R語言提供了非常強(qiáng)大的圖形功能繁涂,能夠快速的實(shí)現(xiàn)數(shù)據(jù)可視化。R語言發(fā)行版中提供了很多很多包支持圖形功能二驰,比如graphics包提供了基本的圖形功能扔罪,該包不需要導(dǎo)入即可使用。發(fā)行版中還提供了lattic包桶雀,該包可以用于繪制切片圖矿酵。我們還可以下載強(qiáng)大的第三方圖形包ggplot2,利用該包可以方便的實(shí)現(xiàn)各種圖形功能矗积。
下面我們使用基本圖形庫graphics來實(shí)現(xiàn)一個(gè)簡單的圖形功能全肮,我們編寫一個(gè)腳本文件,文件名如test.R漠魏,代碼如下:
H <- c(5,10,40,20)
png(file = "my.png")
barplot(H)
dev.off()
然后我們調(diào)用RScript.exe執(zhí)行該腳本倔矾。這時(shí)會(huì)發(fā)現(xiàn)當(dāng)前目錄下有了一個(gè)my.png圖片文件,圖片的內(nèi)容如:
可以看出柱锹,這是一個(gè)簡單的條形圖哪自。下面我們來看下生成這個(gè)圖片的代碼的含義:
1)第一條語句 H <- c(5,10,40,20) 用來定義一個(gè)向量,有4個(gè)元素
2)第二條語句png(file = "my.png")表示將生成一個(gè)png格式的圖片文件禁熏,file參數(shù)值是指定生成的圖片文件名壤巷。
3)第三條語句barplot(H)是進(jìn)行數(shù)據(jù)圖的生成
3)第四條語句dev.off()是關(guān)閉操作,用于釋放IO資源瞧毙。
我們可以在調(diào)用barplot函數(shù)時(shí)傳入更多參數(shù)來豐富圖形胧华,比如增加添加標(biāo)題,設(shè)置顏色等宙彪,代碼如:
H <- c(5,10,40,20)
M <- c("Mar","Apr","May","Jun")
png(file = "my.png")
barplot(H,names.arg = M,xlab = "Month",ylab = "Revenue",col = "blue",
main = "Revenue chart",border = "red")
dev.off()
執(zhí)行該腳本矩动,查看生成的圖片,圖片如下:
限于篇幅释漆,本文只舉這一個(gè)簡單例子悲没,但可以看出, R語言的圖形功能非常強(qiáng)大,簡單幾行代碼男图,就能生成一個(gè)實(shí)用的圖片示姿。
八、函數(shù)式特性
R語言是一種函數(shù)式編程語言逊笆,函數(shù)是一等公民栈戳。下面介紹R語言函數(shù)式編程的一些基本特性。
(一)函數(shù)作為一個(gè)變量
從R語言函數(shù)的定義就可以看出难裆,R函數(shù)天生就可以作為一個(gè)變量子檀,如下面例子:
> plus<-function(a,b)a+b
> plus(3,5)
[1] 8
> f=plus
> f(3,5)
8
可以看出,第一行定義了一個(gè)函數(shù)plus,可以將plus賦值給另一個(gè)變量f命锄,這樣f也是一個(gè)函數(shù)堰乔,可以被調(diào)用。
同樣函數(shù)也可以作為參數(shù)傳遞脐恩,作為函數(shù)的返回值镐侯,這是高階函數(shù)的特點(diǎn),下面會(huì)接著介紹驶冒。
(二)高階函數(shù)
所謂高階函數(shù)苟翻,指如果一個(gè)函數(shù)中的參數(shù)、或函數(shù)的返回值是個(gè)函數(shù)骗污,則該函數(shù)就稱為高階函數(shù)崇猫。
下面舉例來說明:
f<-function(call,a,b){
call(a,b)
}
上面定義了一個(gè)函數(shù)f,有三個(gè)參數(shù)需忿,第一個(gè)參數(shù)是個(gè)函數(shù)诅炉,所以該f函數(shù)是高階函數(shù)。下面再定義兩個(gè)函數(shù)屋厘,如:
plus<-function(a,b)a+b
muti<-function(a,b)a*b
我們?cè)僬{(diào)用函數(shù)f,如下:
> v<-f(plus,3,5)
> print(v)
[1] 8
> v<-f(muti,3,5)
> print(v)
[1] 15
(三)匿名函數(shù)
上面高階函數(shù)的例子中涕烧,可以看到,為了調(diào)用高階函數(shù)汗洒,還需要先顯示的聲明一個(gè)函數(shù)议纯,這比較麻煩。同其它語言一樣溢谤,R語言也支持匿名函數(shù)瞻凤,這樣可以簡化代碼的編寫,如下面例子:
> v<-f((function(a,b)a+b),3,5)
> print(v)
[1] 8
同樣調(diào)用上面定義的高階函數(shù)f世杀,我們沒有再獨(dú)立定義plus函數(shù)阀参,而是直接將函數(shù)實(shí)現(xiàn)作為參數(shù)傳入。再舉例:
> v<-f((function(a,b)a*b),3,5)
> print(v)
[1] 15
函數(shù)式編程的特點(diǎn)很多瞻坝,在本文中只是介紹了最基本的幾個(gè)特點(diǎn)结笨,更多的信息本文不再介紹。
九湿镀、小結(jié)
本文是對(duì)R語言的一個(gè)學(xué)習(xí)總結(jié),包括R語言的基本概念伐憾、開發(fā)環(huán)境搭建勉痴、基本語法、核心數(shù)據(jù)結(jié)構(gòu)向量的使用树肃、以及讀寫數(shù)據(jù)蒸矛、繪制圖形、函數(shù)式編程等功能。學(xué)習(xí)R語言雏掠,除了要掌握它的語法知識(shí)外斩祭,很關(guān)鍵的一點(diǎn)是要熟悉R語言自帶的和一些第三方擴(kuò)展包中提供的各種函數(shù)。