R语言学习笔记

本文是对R语言一个学习总结,共包括如下章节内容:

  • 什么是R语言
  • 开发环境搭建
  • 基本语法
  • 向量
  • 列表和矩阵
  • 读写数据
  • 绘制图形
  • 函数式特性
  • 小结

一、什么是R语言

顾名思义,R语言,它首先是一门计算机编程语言,就跟传统的C语言,Java语言类似。R语言是一门图灵完备的语言,这意味着可以用R语言来进行任何编程。

但是R语言天生为数据统计而生,所以,它做不到像C语言那般的普适,数据统计分析、统计建模、数据可视化才是它的舞台。

R语言最初是由新西兰奥克兰奥克兰大学统计系的Ross Ihaka和Robert Gentleman写的。 R语言于1993年首次亮相。2000年,第一版R.1.0.0正式发布。目前最新的版本是R3.5.3。

R语言有如下特点:

1、R是属于GNU系统的一个自由、免费、源代码开放的软件,R语言源代码托管在github。

2、R语言是一种脚本语言,源码不需要编译,解释执行。

3、R语言支持面向对象编程,但本质上它是一种函数式编程语言。

4、R语言存在大量的扩展包,它们提供了各种丰富的数据统计分析功能。

5、R语言是跨平台的,可在各种操作系统下进行开发和运行。

二、开发环境搭建

(一)下载安装

R语言的官网地址是 https://www.r-project.org/。我们更多的是使用CRAN(The Comprehensive R Archive Network),地址是https://cran.r-project.org/mirrors.html。CRAN提供了提供了上百个镜像网站,这些镜像分布在世界各地。R镜像是为了方便世界各地的使用者下载R软件及相关扩展包。各地的镜像都是R网站的备份文件,完全一样。所以,选择离你最近的镜像,你下载R软件或R包的速度相对较快。

比如在国内可以到https://mirrors.tuna.tsinghua.edu.cn/CRAN/去下载。

R语言提供了各种操作系统上可安装的版本。在本文中我们下载安装windows下的版本。我们下载的是基础的Base版本,下载后得到一个可执行程序R-3.5.3-win.exe,大小80M左右,可以看出R软件是非常精简的。我们直接双击该安装程序进行安装。

安装完成后,安装后的目录结构如下:


其中bin目录下有两个可执行程序,R.exe和Rscript.exe,其中R.exe是一个命令行开发工具,可以交互式的执行编写和执行R代码,可以很方便的用来学习R语言。但在实际开发环境下,我们会将编写的源代码保存到脚本文件中,这时可以用Rscript.exe来执行R脚本,R语言源码文件的扩展名为R。

为了方便调用这两个可执行程序,我们可以把bin目录加入到环境变量中。在linux下安装的R语言环境,也有类似的可执行程序。

(二)R命令行工具

我们运行R.exe,会出现一个控制台程序,显示的信息如下:

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.
>

最后一行的>是个提示符,可以输入R代码。我们来看一个最简单例子,如下:

> print("hello,world")
[1] "hello,world"
>

我们输入代码print("hello,world"),回车后输出[1] "hello,world",这里实际是调用R语言基础库中的print函数。

输入q()可退出命令行程序。

(三)查看帮助

R语言提供了丰富的帮助功能,可以查看各种函数的功能。在命令行下只需调用help函数即可。比如:

> help(print)
starting httpd help server ... done

我们输入help(print),回车后,会输出信息starting httpd help server ... done,然后会自动弹出浏览器,在浏览器中显示print函数的帮助信息。我们可以通过这种方式在命令行下边练习、边查看帮助。

(四)脚本执行

下面我们看下,如何执行R脚本。看一个简单例子:

1、打开任何文本编辑器,新建一文本,文本中只有一行代码,如:

print ( "hello,world")

2、保存文件为test.R

3、调用Rscript.exe执行脚本,如:

bin\Rscript.exe rexample\test.R

说明:实际练习时注意引用实际的路径。

(五)RStudio开发环境

R语言提供的命令行开发工具R.exe功能比较简单。有一款第三方的开发工具RStudio,RStudio是一款可视化的R语言开发工具,功能很强大,可以在各种操作系统下运行。

其官方网站是https://www.rstudio.com/

本文不会使用RStudio,本文的例子使用交互式命令行或脚本文件来展示。

(六)扩展包

R语言程序的编写主要是使用R语言自身和第三方提供的函数来实现。这些函数按照功能分类存储在一个个的包中。这些包物理上位于安装后目录的library目录下,每个包对应一个子目录(其中包含了R代码、帮助文件、数据集等),如下面界面:


R语言发行版中已经提供了很多有用的功能包,如上面界面所显示的。

但R语言社区也提供大量的可扩展包,可供我们选择使用。扩展包中也包含了R代码、帮助文件、数据集等。

有很多网站都提供R扩展包的下载,不过最重要的是CRAN,https://cran.r-project.org这个网站。

要使用扩展包,首先需要安装扩展包到本地的R语言的安装目录下。R语言所有的标准包和第三方扩展包都位于安装后目录的library目录下,每个包对应一个子目录。

我们有两种方式可以下载安装扩展包,一种是可以在R命令行程序下运行命令来在线安装;第二种是下载扩展包文件,离线安装。

本文我们介绍离线安装的方式,比如我们想安装fortunes扩展包(该扩展包包含了很多从R社区摘录下来的言论)。在国内,我们可以到https://mirrors.tuna.tsinghua.edu.cn/CRAN/网站上找到该扩展包,下载二进制的版本,我们这里是windows系统,所以下载的是fortunes_1.5-4.zip文件。把fortunes_1.5-4.zip文件解压到library目录下,会生成一个fortunes目录,fortunes目录的目录结构如下,这是一个扩展包的典型结构:

(七)导入包

要使用包中的函数,需要先使用library函数将扩展包加载进来才能使用(类似java中的import),然后就可以调用扩展包中提供的各种函数。如下面例子:

> 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)

在上面例子中,我们在R命令行程序下先输入执行library(fortunes),即调用library函数将fortunes包加载到当前执行环境中,包名fortunes可以不用引号括起来。然后我们调用fortune函数,传入参数"This is R",执行后返回一段文字。我们也可以不带参数调用fortune函数,如fortune(),这时会随机返回一段文字。我们一样可以调用help函数查看第三方包提供的函数的帮助信息,如help(fortune),这时会打开浏览器显示fortune函数的帮助信息。

需要说明的是,不仅对于第三方扩展包,对于R版本自带的包,除位于基础包中的函数被调用前不需要导入包(如print函数所在的包),其它包也需要先用library函数导入后才能使用其中中的函数。

三、基本语法

(一)风格

R语言程序源码程序有如下的风格:

1、每条语句不需要有分号结尾。

2、区分大小写,如变量命名、函数命名。

3、单行注释采用 # ,#后面的内容都被忽略。不支持多行注释。

4、点号可以是标识符的一部分,如 age.of.tom 可以是一个变量名,不是如java,python等编程语言中的对对象成员的引用。

5、声明变量和赋值采用<-运算符,而不是传统的=运算符。

6、字符串既可以用单引号、也可以用双引号括起来。

(二)数据类型

同其它编程语言一样,R语言的数据也是有类型的,基本的数据类型有如下几种:

  • 数值型

  • 布尔型:常量只有两个TRUE 和 FALSE ,分别表示真和假

  • 字符串:可以用单引号或双信号括起,如 “a”,“abc”, ‘xy’

同样,R语言也有变量的概念,举个例子,在R命令行下运行:

> v<-12
> print(v)
[1] 12

上面代码定义了一个变量,变量名为v,变量的值为整数12。在R语言中,不需要显示的声明数据的类型。

说明:R语言实际并不存在一个基本类型的变量,R语言中的单个值(如整数12)本质是一个只包含一个元素的向量对象,关于向量的详细含义在后面的章节会介绍。

需要特别注意的是,字符串与字符串的连接不能用+号,如:

“hello”+”,world”

上面的写法是错误的,执行会报错。

可以用内置的函数paste将字符串连在一起,如:

> re<-paste("hello","world")
> print(re)
[1] "hello world"

R语言提供了丰富的针对字符串的操作,包括查找、正则表达式等,本文对这些不做详细介绍。

(三)函数

在编写R语言程序时,我们可以提供R语言自带的包和第三方包提供的各种函数,也可以定义自己的函数。

在R语言中,定义函数使用function关键字,其基本语法如下:

函数名 <- function(参数列表) {

   函数体 

}

下面我们看一个简单例子:

plus <- function(a,b){
  print(a)
  print(b)
  return(a*2+b)
}
re<-plus(3,5)
print(re)

上面代码定义了一个函数plus,然后调用了这个函数。使用RScript执行上面脚本,输出信息如下:

[1] 3
[1] 5
[1] 11

R语言的函数除上面的标准定义和调用外,还有如下一些特点,如:

1、函数调用的参数可以按照函数中定义的顺序提供,也可以以不同的顺序提供,但需要指定参数名,如下面例子:

re<-plus(b=5,a=3)

上面代码调用了plus函数,传入的参数指定参数名,不是按顺序传入。

2、在定义函数时设置参数的值,这样在调用函数时,如果不传入值,这些设置的值就作为参数的默认值。如下面脚本:

plus <- function(a=1,b=2){
  print(a)
  print(b)
  return(a*2+b)
}

re<-plus()
print(re)

可以看出,定义plus方法,给参数设置了值,在调用函数时,可以不传入值。执行上面脚本,输出信息如下:

[1] 1
[1] 2
[1] 4

3、省略return语句

定义函数时,可以省略return语句,这样函数体最后一行代码作为表达式的值就作为函数的返回值,如下面脚本代码:

plus <- function(a,b){
  a*2+b
}

re<-plus(3,5)
print(re)

执行上面脚本,输出信息是:

[1] 11

4、省略{}:如果函数体只有一行代码,则可以省略{},该行代码可以直接放在参数列表的后面。如下面函数定义也是正确的:

plus <- function(a,b) a*2+b

5、变参:R语言也支持任意数量参数传入,用....表示,放在参数列表的最后,如下面例子:

show <- function(a,...){
  args = list(...)
  print(args)
}

show(12,"hello",TRUE,20)

上面代码中的show函数,有两个参数,第一个参数是a,第二参数是用...表示,表示可以传入任意个值。在函数体中利用 list(...)可以获取到传入的这些变参值,是一个列表。执行上面脚本,输出信息如下:

[[1]]
[1] "hello"

[[2]]
[1] TRUE

[[3]]
[1] 20

说明,关于R语言中列表,可以理解成包含一些列元素的集合。

(四)if条件语句

同c语言,java等语言类似,R语言也支持if条件语句,用法和c语言,java类似。下面简单介绍下。

1、if语句

if语句由一个布尔表达式后跟一个语句块(含1条或多条语句)组成。其语法格式如下:

if(boolean_expression) {

   一条或多条语句

}

如果布尔表达式的计算结果为true,那么if语句中的代码块将被执行。 如果布尔表达式的计算结果为false,则语句块中代码不被执行。

举例:

if(1==1){
  print(2)
  print(3)
}

如果if的语句块只有一个语句,则可以省略{},该语句可直接跟在布尔表达式后面,如:

if(1==2) print(2)
print(3)

2、if...else...语句

if语句后面可以跟一个可选的else语句,当布尔表达式为false时执行。其语法格式如下:

if(boolean_expression) {

   语句块(当布尔表达式为true时执行)

} else {

   语句块(当布尔表达式为false时执行)

}

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.

}

有几点需要注意的:

1)可以有1个或多个else if语句

2)可以没有else语句

3)从上往下匹配,一旦if后的布尔表达式或某个else if后的布尔表达式被匹配,剩余的条件不会被测试。

(五)for循环语句

R语言提供了for语句可以对向量、列表等集合对象中的值进行逐一遍历,其语法格式如下:

for (item in values){

    语句块

}

其中values是集合对象,item是对其中元素的引用。如下面例子:

for(i in 1:5){
   print(i)
}

说明,1:5 代表包含了5个元素的向量,关于向量的含义,后面章节会详细介绍,这里把它理解成一个数组(或集合)即可。

执行上面脚本,输出信息是

[1] 1
[1] 2
[1] 3
[1] 4
[1] 5

说明,如果{}中的语句块只有一个语句,则{}可省略,这点同c语言,java的语法。

R语言也支持break语句,可以设置提前跳出循环,如下面例子:

for(i in 1:5){
   print(i)
   if(i==3)
     break
}

运行上面脚本,输出信息如下:

[1] 1
[1] 2
[1] 3

说明,R语言的循环中不支持continue语句。

四、向量

向量是R语言中最重要的一个特性,是R语言数据统计分析的基础。R语言的向量是一种对象(数据结构),它是一组一维的数据,其中每个元素的类型是相同的,类似其它语言中的一维数组(或列表)。

与其它编程语言不同的是,单个值,如整数 12,字符串 “hello”,布尔类型值TRUE 等也是一个向量,只不过该向量只包含一个元素。这是R语言的一个重要特点。在前面的章节,我们只涉及到单个类型的值,其实它们都是向量。

在绝大部分运算中,能使用单个元素向量(如12,”hello”,TRUE)的地方,也能使用包含多个元素的向量。但也有特列,比如if语句后面的逻辑表达式,表达式的值只能是一个只包含单个布尔值的布尔向量。

下面我们来详细介绍如何在R语言中使用向量。

(一)创建向量

上面提到,在R语言中单个值就是一个向量,显然,最简单的向量,如 12, TRUE, “hello”这些常量。我们可以定义向量变量,如:

v<-12
v<-TRUE

另外我们可以通过冒号运算符:来定义连续值的整型向量,如 1:3 是个整型向量,其中含1~3这三个元素。如下面例子:

> 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语言的标准函数c来连接向量,如下面例子:

> v<-c(2,3)
> print(v)
[1] 2 3

上面的函数c将两个单元素向量连接一起,生成一个含两个元素的向量。

再看一个例子:

> v<-c(c(2,3),c(6,7))
> print(v)
[1] 2 3 6 7

可以看出,函数是c把各个向量中的单个元素抽取出(扁平化)组成新的向量。

data<- c(“hello”,”world”,”yes”)

上面语句声明了一个变量data,并创建了一个字符向量对象赋值给该变量。

需要说明的是NULL表示一个空向量,如:

v<-NULL

上面语句声明了一个向量变量,初始内容为空。

(二)向量的运算

从数据结构的角度看,和其它编程语言相比,向量并没有特别的地方,就是一个数组、或者列表之类的数据结构,是个集合对象。

对于集合数据的运算,传统的编程语言往往有两种方式:一是利用循环遍历集合中的元素;二是采用高阶函数+Lambda表达式(需要支持函数式编程的语言)。关于对集合数据的操作,可参看文档《函数式编程之集合操作》

而R语言的向量运算在传统语言的基础上,还提供了更简洁和强大的功能,我们先看一个简单例子感受下,先定义一个向量如下:

v<-c(3,5,8,10)

如果我们希望通过向量v生成一个新的向量,新向量中每个元素的的值是原向量中元素的两倍。熟悉函数式编程语言的会立即想到,这就是一个map操作,比如在scala语言(其它语言操作类似)中我们可以这么实现:

var data =List(2,4,5)
var newdata = data.map(item=>item*2)

上述代码执行后 newdata 变量指向的集合内容为 List(4, 8, 10)。

对于不支持函数式编程的语言,我们要实现上述功能,可采用传统的for循环方式来实现,比如在R语言中我们也可以用for循环来实现,如下面代码:

data<-NULL
for(i in c(2,5,7))
  data[length(data)+1]<-i*2
print(data)

运行上面代码,输出的信息是 [1] 4 10 14

但是在R语言中实现这个功能有一种更简单方式,即直接通过运算符来实现,如下面代码:

> v<-c(2,5,7)*2
> print(v)
[1]  4 10 14

可以看出,我们直接使用基本的算数运算符*就可以实现。

在其它编程语言中,一般算术运算符只能针对单个值进行操作,但因为R语言中,单个值也是一个向量,所以R语言中的运算符可以针对向量进行运算,即R语言中的运算符都是向量化的。

(三)数学运算符

同别的语言一样,R语言也支持各种算术运算符,如+ ,-,*,/等。但与别的语言不同的是,R语言的算术运算符都支持对向量的运算。下面我们以最常见的+运算符来说明。

对于 x+y 这个加法运算,其含义如下:

1、如果x和y都是单元素向量,则就如普通的数学运算,如 3+5 ,结果是8。

2、如果x和y有一个是单元素向量,另一个是多元素向量,则结果就是该单元素向量中的元素值和多元素向量中的每个元素相加,返回的是相加后的多元素向量。如 c(2,3,4) +2 结果是 (4,5,6)。

3、如果x和y都是多元素向量,且元素数量相同,则会按照元素顺序各元素相加,返回相加后的向量。如 c(1,2) +c (4,5) 结果是 (5,7)。

4、如果x和y都是多元素向量,但元素数量不相同,比如x的元素数量是m个,y的数量是m+n个,则结果向量的元素个数是m+n个,前m个元素的值是x和y的前m个元素一一相加的结果,后n元素的值是x向量的第1个元素和y向量的后n个元素的一一相加的结果。如 c(1,2)+c(4,5,6) 结果是 (5,7,7)。需要说明的是,这种情况运行时会出现警告提示,但不影响上面说的结果输出。

上面是以+运算符为例来说明向量运算的规则,其它数学运算规则类似,这里就不一一介绍。

(四)向量的属性

使用str函数可以查看向量的结构,如下面例子:

> 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函数可以获取到向量中元素的个数,如下面例子:

> length(12)
[1] 1

> length(c(12,16) )
[1] 2

> length(c(2,4,6))
[1] 3

(五)向量值的获取

我们可以通过位置索引获取向量中的元素,因为单个值也是个向量,实际是返回包含一个元素的子向量。如下面例子:

> x<-c(2,4,5)[1]
> print(x)
[1] 2

> x<-c(2,4,5)[3]
> print(x)
[1] 5

可以看出,向量的位置索引是从1开始的,即第一个元素的索引是1,这点与其它语言的数组(列表)等数据结构的索引从0开始是不同的。

(六)向量修改

反过来,我们还可以通过索引给向量增加元素或修改某个元素的值,下面举例介绍。我们先看一段代码:

> x<-NULL
> x[1]<-12
> x[2]<-20
> x[4]<-30
> print(x)
[1] 12 20 NA 30

首先通过x<-NULL声明一个空的向量,NULL表示空向量。

x[1]<-12 是往向量的第1个位置添加元素。上面代码我们直接越过了索引3往第4个索引添加元素,R语言也是允许的,因为第3个索引没有设置元素,可以看出当调用print函数显示向量的内容时,第三个元素显示NA,即值不存在。

在上面代码的基础上,我们继续执行:

> x[2]<-33
> x[3]<-5
> print(x)
[1] 12 33  5 30

可以看出,第2个元素的内容发生了变化,第3个元素也有了内容。

五、列表和矩阵

R语言除了提供了最基本的向量对象,还有列表、矩阵、数组、因子、数据帧等对象。在本文中,我们只对列表、矩阵进行介绍。

(一)列表

列表是R语言对象,它可以包含不同类型的元素,如数字,字符串,向量和其中的另一个列表。 列表还可以包含矩阵或函数作为其元素。 列表是使用list()函数创建的。如下面例子:

list_data <- list("Red", "Green", c(21,32,11), TRUE, 51.23, 119.1)
print(list_data)

可以看出,上面创建的列表包含各种类型的元素,这点与向量不同,向量中的元素要求是同类型的。

列表还有一个特点时,可以给列表中的元素命名,如下面例子:

 data<-list(1,"tom",20)
names(data)<-c("id","name","age")

上面的第二行代码通过names函数给列表中的每个元素设定了一个名称。

下面就可以通过名称来引用到列表中的元素,格式是 列表变量$元素名称,如下面例子:

> data$id
[1] 1

> data$name
[1] "tom"

> data$age
[1] 20

上面代码演示了如何通过名称来获取列表中的元素。

同向量一样,列表也支持通过索引来获取列表中的元素,如下面例子:

> data[1]
$id
[1] 1

> data[2]
$name
[1] "tom"

针对列表,R语言还有很多丰富的操作,本文不再详细介绍。

(二)矩阵

矩阵是其中元素以二维矩形布局布置的R对象,其包含相同原子类型的元素。 虽然我们可以创建一个只包含字符或只包含逻辑值的矩阵,但它们没有太多用处。 大部分场景下使用包含数字元素的矩阵用于数学计算。

使用matrix()函数创建一个矩阵,其语法格式如下:

matrix(data, nrow, ncol, byrow, dimnames)

各个参数的含义如下:
1)data参数是矩阵的数据元素的输入向量
2)nrow是要创建的矩阵的行数
3)ncol是要创建的矩阵的列数
4)byrow是一个逻辑线索。 如果为TRUE,则输入向量元素按行排列。默认为FALSE,输入向量元素按列排列。
5)dimname是分配给行和列的名称。

下面我们通过例子来说明:

> data<-matrix(1:6,3,2)
> print(data)
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

上面代码的第一行语句创建了一个3行2列的矩阵,向量1:6中的数据正好填满整个矩阵,因为byrow参数是默认值为FALSE,所以向量中的数据按照列来排列。如果我们传入TRUE,效果如下:

> data<-matrix(1:6,3,2,TRUE)
> print(data)
     [,1] [,2]
[1,]    1    2
[2,]    3    4
[3,]    5    6

可以看出,向量中数据在矩阵中按行排列。

如果我们给定的向量中的元素个数少于矩阵的单元格数据,来看下有什么效果,代码如下:

> 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

我们会发现,R语言会重复用向量中的元素来填充矩阵,这时运行时会给出了警告。

在创建矩阵时,可以只给出行的数量,R语言会自动根据向量中的元素个数计算出矩阵的列的数量,如下面代码:

> data<-matrix(1:6,3)
> print(data)
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

上面代码,我们只指定了矩阵的行数为3,没有指定列的数量。但因为向量中的元素为6,R语言自动计算出矩阵的列为2,所以最后创建的是3行2列的矩阵。

下面我们来看下如何设置矩阵的行和列的名称,举例如下:

> 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 参数来设置行和列的名称。

可以通过使用元素的列和行索引来访问矩阵的元素,针对上面创建的矩阵,我们可以如此获取其中的元素,如:

> print(data[1,2])
[1] 4

可以看出,data[1,2]就获取了第1行,第2列的元素。

再比如我们要获取第3行第1的元素,可以如下:

> print(data[3,1])
[1] 3

矩阵在数学中是个非常重要的工具,会有各种矩阵的运算,R语言也支持矩阵的丰富运算,很多运算符都支持矩阵的操作,我们下面看一个简单例子:

> 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

可以看出,+运算符作用在矩阵上,最后的结果也是一个矩阵,新矩阵中的每个元素是运算的两个矩阵的各个元素的和。

我们再看一个乘法运算,如下面例子:

> 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

可以看出,计算机制和加法类似,只不过元素之前由相加变成了相乘。

上面只是针对R语言矩阵的最基本运算,R语言还有针对矩阵的更多操作,本文不再详细介绍。

六、读写数据

在R语言中,我们可以从存储在R语言环境外的文件、数据库中读取数据, 我们还可以将数据写入将外部的文件和数据库中。 R语言可以读取和写入各种文件格式,如csv,excel,xml等。

对于文本文件(csv是文本文件的一种),R语言基础库中提供了函数进行支持。对于excel,xml,外部数据库需要下载扩展包来支持。

下面我们来以读取csv文件中的内容举例进行说明。

假设某个person.csv的内容如下:

id,name,age
1,tom,20
2,mike,30

我们可以通过如下代码读取文件中信息,如下:

data <- read.csv("person.csv")
print(data)

需要说明的是,如果不指定文件路径,该文件必须处于当前工作环境目录下,在R语言中,可以通过函数getwd()来获取当前的工作目录,可以通过setwd()来设置当前的工作目录。

因为csv文件的列之前以逗号分隔,对于读取更通用的文本文件,如列之间以tab键分隔,可以使用更通用的函数read.table来读取,该函数提供了更多可选的参数设置。

关于对其它文件和数据库的访问,本文不再介绍。

七、绘制图形

R语言提供了非常强大的图形功能,能够快速的实现数据可视化。R语言发行版中提供了很多很多包支持图形功能,比如graphics包提供了基本的图形功能,该包不需要导入即可使用。发行版中还提供了lattic包,该包可以用于绘制切片图。我们还可以下载强大的第三方图形包ggplot2,利用该包可以方便的实现各种图形功能。

下面我们使用基本图形库graphics来实现一个简单的图形功能,我们编写一个脚本文件,文件名如test.R,代码如下:

H <- c(5,10,40,20)
png(file = "my.png")
barplot(H)
dev.off()

然后我们调用RScript.exe执行该脚本。这时会发现当前目录下有了一个my.png图片文件,图片的内容如:


可以看出,这是一个简单的条形图。下面我们来看下生成这个图片的代码的含义:

1)第一条语句 H <- c(5,10,40,20) 用来定义一个向量,有4个元素

2)第二条语句png(file = "my.png")表示将生成一个png格式的图片文件,file参数值是指定生成的图片文件名。

3)第三条语句barplot(H)是进行数据图的生成

3)第四条语句dev.off()是关闭操作,用于释放IO资源。

我们可以在调用barplot函数时传入更多参数来丰富图形,比如增加添加标题,设置颜色等,代码如:

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()

执行该脚本,查看生成的图片,图片如下:


限于篇幅,本文只举这一个简单例子,但可以看出, R语言的图形功能非常强大,简单几行代码,就能生成一个实用的图片。

八、函数式特性

R语言是一种函数式编程语言,函数是一等公民。下面介绍R语言函数式编程的一些基本特性。

(一)函数作为一个变量

从R语言函数的定义就可以看出,R函数天生就可以作为一个变量,如下面例子:

> plus<-function(a,b)a+b
> plus(3,5)
[1] 8

> f=plus
> f(3,5)
8

可以看出,第一行定义了一个函数plus,可以将plus赋值给另一个变量f,这样f也是一个函数,可以被调用。

同样函数也可以作为参数传递,作为函数的返回值,这是高阶函数的特点,下面会接着介绍。

(二)高阶函数

所谓高阶函数,指如果一个函数中的参数、或函数的返回值是个函数,则该函数就称为高阶函数。

下面举例来说明:

f<-function(call,a,b){
  call(a,b)
}

上面定义了一个函数f,有三个参数,第一个参数是个函数,所以该f函数是高阶函数。下面再定义两个函数,如:

plus<-function(a,b)a+b
muti<-function(a,b)a*b

我们再调用函数f,如下:

> v<-f(plus,3,5)
> print(v)
[1] 8

> v<-f(muti,3,5)
> print(v)
[1] 15

(三)匿名函数

上面高阶函数的例子中,可以看到,为了调用高阶函数,还需要先显示的声明一个函数,这比较麻烦。同其它语言一样,R语言也支持匿名函数,这样可以简化代码的编写,如下面例子:

> v<-f((function(a,b)a+b),3,5)
> print(v)
[1] 8

同样调用上面定义的高阶函数f,我们没有再独立定义plus函数,而是直接将函数实现作为参数传入。再举例:

> v<-f((function(a,b)a*b),3,5)
> print(v)
[1] 15

函数式编程的特点很多,在本文中只是介绍了最基本的几个特点,更多的信息本文不再介绍。

九、小结

本文是对R语言的一个学习总结,包括R语言的基本概念、开发环境搭建、基本语法、核心数据结构向量的使用、以及读写数据、绘制图形、函数式编程等功能。学习R语言,除了要掌握它的语法知识外,很关键的一点是要熟悉R语言自带的和一些第三方扩展包中提供的各种函数。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335