R语言入门系列之一

2022-05-05 11:13:02 浏览数 (1)

写在前面

计算机语言的学习并不困难,关键是一定要由浅入深的实际操作练习。也许最开始的比较简单,学习者一带而过没有实际操作,之后的进一步学习很可能会陷入不知所云的困境,实际操作所带来的感觉是无法替代的,其价值也是非常重要的。

1.对象与函数

R(https://cran.r-project.org/)是一个很好的数据分析以及可视化工具。在R中对象(object)是指可以赋值给变量(variable)的任何事物,在R语言中使用对象来存储数据也即储存变量,对象类型有标量、向量、矩阵、数组、数据框、列表。R语言通过函数(function)来提取对象属性、变量运算,函数可以来自R平台,也可以来自各种软件包(package)、自定义函数。

R语言不用事先声明对象或变量,对象在赋值时同步创建。对象或变量名以字母开头,可由字母、数字、“.”、“_”组成。对象赋值一般使用赋值符号“<-”,而在很多情况下也可以用传值符号“=”代替,也即“=”具有二义性,区别在于在函数内部时“=”只具有参数传递作用,举例如下:

在函数的括号内部使用“=”则将一个值传递给函数的内置参数(这个参数必须是函数具有的),而使用“<-”则将一个值赋值给变量,这时候a2作为一个对象而不是参数存在。可以使用objects()函数来查看当前对象目录,使用rm(objectname)来移除遗留的对象。

推荐在安装R后安装RStudio(https://www.rstudio.com/),在RStudio中编辑、运行R脚本。

1.1标量与向量

⑴赋值及运算符

标量是存储数据的最基本结构,可以是数值型、字符型或逻辑型(TRUE/FALSE)。在R语言里数值型变量运算的加、减、乘、除、幂指数分别为“ ”、“-”、“*”、“/”、“^”,一定要注意乘号不可省略;科学计数法可以用e来表示,也即“12300”记为“1.23e 4”。在不用变量赋值的情况下R平台里也可以直接进行数学运算,其运算符优先级与数学中一致。赋值为字符串时字符串需要添加引号。具体示例如下:

向量(vector)是存储数据的一维数组,标量可以理解为只含有一个元素的向量。向量可以使用执行组合的函数c()来创建向量,其数据来源可以是数值型、字符型、逻辑型数据(单个向量其数据类型必须相同),也可以来自标量,其参数可以是变量名,具体如下所示:

连续的整数可以使用“:”来表示也即“1:4”等效于“c(1,2, 3, 4)”。向量可以通过“[]”来进行索引,方括号内为元素的位置,可以是大于1的整数或者向量,位置前加负号“-”则表示删除这个位置的元素,但是使用向量索引时只能全是正整数或者负整数,不能混杂,如下所示:

R语言中判断符号有大于“>”、大于等于“>=”、小于“<”、小于等于“<=”、完全等于“==”、不等于“!=”、存在于“%in%”,如下所示:

在向量的索引[]里也可以加入判断语句,例如a[a>5]。

函数vector()可以来产生一个一定长度、一定类型的空向量,函数numeric()可以用来产生一个一定长度的数值型向量,函数character()可以用来产生一个一定长度的字符型向量,函数as.vector()可以用来将其他类型的数据转换为一定类型的向量,函数is.vector()可以用来判断数据是否为一定类型的向量,具体使用格式如下:

代码语言:javascript复制
vector(mode="logical", length=0)
numeric(length=0)
character(length=0)
as.vector(x, mode="any")
is.vector(x,mode="any")

其中x为作用对象;length为向量长度(正整数);mode为向量类型,有任意"any"、数值型"numeric"、字符型"character"、逻辑型"logical"、整数"integer"、复数"complex"。

另外还有几种产生向量的方式:

rep(x, times=0) #产生重复,x可以是任意标量、向量,times为重复次数

seq(1.5, 6, by=0.5) #产生序列数,前面两个数为起始范围,by为步长

sample(x, size=3, replace=FALSE) #在x(任意向量)中随机抽样,size抽样次数,replace是否放回抽样

pretty(c(a, b), n) #将区间(a, b)插入n个等间距的间隔点,从而将区间分成n 1个相等区域,在画图中常用

⑵函数

R可以非常灵活的处理数值与文本数据,并且有很好的面向对象的编程方式,对于标量与向量,常用内置基本函数如下所示(其中绿色部分为数值处理;蓝色部分为字符串处理,R支持正则表达式;红色部分为对象属性及操作):

函数

含义

round()

round(x, 2)将数值对象x四舍五入法保留小数点后2位

trunc()

四舍五入去整,floor()向下取整,ceiling()向上取整

signif()

取有效数字

sqrt()

返回标量或向量元素的平方根

log()

log(x, y)返回以y为底x的对数,y默认值自然常数e

exp()

返回自然常数e的指数

sin()

返回正弦值,其余还有cos()、tan()等详细查看?sin

min()

返回最小值,此外which.min()返回最小值id

max()

返回最大值,此外which.max()返回最小值id

abs()

返回数值对象绝对值

sum()

返回对象元素的和

prod()

返回对象元素的乘积

mean()

返回对象元素的均值

var()

返回对象元素的方差

sd()

返回对象元素的标准差

median()

返回对象元素的中位数

nchar()

返回标量或向量元素的字符长度(包含空格)

paste()

paste(a,b,c,sep=" ")将a、b、c粘贴为一个字符串,空格分割

tolower()

转换为小写,toupper()转换为大写

substring()

substring(a,1,3)返回字符对象a中第1到第3个字符

strsplit()

strsplit(x, split=" ", fixed=FALSE, perl=FALSE)根据split将字符串对象x分割,默认split为正则表达式, fixed=TRUE则做精确匹配,当perl=TRUE时,使用perl的正则表达式规则,当分隔符为?, , {, |, (, )时,要使用'\'来消除特殊含义

grep()

grep("x", a),返回a中包含有字符“x”的元素id,可以使用正则表达式匹配,与strsplit()类似。此外还有grepl()返回匹配逻辑值、sub()替换、gsub()全局替换等

length()

返回对象的长度也即元素个数

mode()

查看对象数据类型(也即数值型、字符型等)

names()

返回向量元素名字

order()

对向量元素排序,decreasing=TRUE则为降序,na.last=TRUE将缺失值排在最后,返回值为元素排名

sort()

对对象元素排序(不限于向量),返回排序后的对象

union()

union(a, b)求两个向量并集

intersect()

求两个向量的交集

setdiff()

setdiff(a, b)求在a中而不在b中的部分

setequal()

setequal(a, b)检验ab是否完全相同,此外is.element(12, a)检验元素12是否属于a,all(c%in%a)检验集合a是否包含c

此外,缺失数据用大写NA表示,数据不确定用NaN表示,数据是无穷用Inf表示,判断是否为空数据用函数is.na(),判断是否不确定用函数is.nan(),数据是否有限用is.finite(),数据是否为无穷用函数is.infinite()。当向量含有缺失值时,若是计算向量的均值、方差等,需要在函数内设置参数na.rm=TRUE来去除缺失值。对于函数的使用方法可以使用?function来查询。

⑶内置常量

R语言有一些内置常量,方便使用的时候调取:

LETTERS #26个大写字母

letters #26个小写字母

month.abb #12个月份的三字母缩写

month.name #12个月份的全称

pi #3.14...

colors() #语言颜色表

上面这些内置常量都可以像其他向量一样取用,例:letters[c(1:8)]。

1.2矩阵与数组

矩阵(matrix)是一个二维数组,矩阵内所有元素必须具有相同的模式(数值型、字符型、逻辑型),矩阵可以使用向量、数据框等数据赋值转换,方法如下所示:

matrix(vector, nrow=m, ncol=n) #使用向量生成m行n列的矩阵

matrix(NA, nrow=m, ncol=n) #生成一个m行n列的空矩阵

as.matrix(x) #将对象转换为矩阵

is.matrix(x) #判断对象是否为矩阵

具体示例如下:

矩阵通过行、列id或者行列name对元素进行索引,也可以使用向量,id前加负号“-”则表示删除改行、列的元素,索引值也可以引入逻辑判断,如下所示:

注意,R中的判断符号有“<”、“<=”、“>”、“>=”、“==”、“!=”,逻辑连接符有与“&”、或“|”、非“!”。

索引里面也可以使用order()等函数:

对于矩阵,也适用上一小节的基本函数,对于二维数据增添的的属性函数如下所示:

ncol()

返回矩阵、数组、数据框的列数目

nrow()

返回行数目

colnames()

返回列名字

rownames()

返回行名字

t()

矩阵转置

数组(array)与矩阵相似似,但是维度可以大于2,类似的具有array()、as.array()、is.array()函数,创建方式如下所示:

array(vector, dimensions=c(3,3,3), dimnames=list(dim1,dim2,dim3)) #使用向量生成3*3*3的数组,dimnames为行名字、列名字、维度名字

示例如下:

数组可以通过三元id进行索引,如下所示:

1.3数据框与因子

有时候通过实验、调查获得的数据不只有一种模式,也即字符型、数值型等混杂在一起(但是每一列必须同一模式),需要一种简单的数据集来存储变量数据,即数据框(dataframe)。数据框可以使用data.frame()来创建,数据来源可以是任何类型的矩阵、向量等,其实用方法如下所示:

data.frame(matrix, row.names=NULL, check.names=FALSE) data.frame(col1, col2, col3...)

数据框必须有列名字,若没有则默认为X1、X2……。

数据框元素索引有三种方法,第一种为通过列的序号索引,第二种通过列名字索引,第三种通过$变量名索引,如下所示:

可以使用attach()函数来将数据框添加到当前平台,这样就可以直接使用列名字或变量名来调用数据框中的数据,使用完后用detach()来移除这些变量名(而不是移除数据框),如下所示:

变量(variable)可以分为名义型、有序型、连续型。名义型变量例如不同膳食类型、不同糖尿病类型,一般为字符型;有序型变量表示一种顺序关系,例如癌症的早、中、晚期,虽然也可以用数字表示,但不是数值关系,没有比较的意义,也无法衡量不同阶段间的差别大小;连续性变量可以为两个值之间的任何值,例如温度,DO,年龄等,可以进行数值运算。类别(名义型)变量和有序变量在R中称为因子(factor)。

函数factor()或者as.factor()以一个正整数向量的形式存储类别值,如下所示:

这时会自动按照字母和数字的顺序映射类别与数字,并存储为(1,2, 4, 3, 2)。若是存储有序变量,也即水平的顺序是有意义的,这时候需指定参数ordered=TRUE:

可以看到这时候不同level之间不再是并列的,有了顺序的意义。有时候按照字母顺序排序的因子向量不能满足现实需要,需要指定顺序,则可以通过设定levels参数来实现:

可以看到这时的顺序发生了变化。接下来我们通过一个小练习练熟悉数据框内不同模式变量差别:

函数str()和summary()可以很方便的查看总结数据信息。可以看到对于数值变量age会计算最大值、最小值、平均值等,但是对于因子变量,只会计算频数。变量类型不同,在统计中其处理方法也不同(例如RDA、CCA等),结果也不相同。

由于因子的存在,数据分组信息等都可以转换为一个变量,从而使得数据框可以存储远多于矩阵的数据。

1.4列表

列表(list)是R中最复杂的一种数据类型。列表是一些对象的有序集合,这些对象可以是向量、矩阵、数据框,甚至其他列表。列表可以使用list()函数进行创建,如下所示:

代码语言:javascript复制
list(object1, object2, ...) #默认名字为编号
list(name1=object1, name2=object2, ...) #为每个对象命名

举例如下:

列表的索引可以使用双括号[[]]加编号或者名字,也可以使用$加名字提取,如下所示:

列表是一种简单的数据组织和调用方式,很多函数的计算结果也是列表(例如lapply()函数),因此列表在R中非常重要。

1.5软件包

R语言提供了大量的功能,而且大部分功能是通过可选模块进行下载安装,这些模块被称为包(package)。这些包即有用来分析作图的函数包,也有用来作为例子的数据包。包即可以在线安装,也可以下载后本地安装。对于大部分包,均可以通过函数install.packages()来进行安装,如下所示:

初次安装需要选择国内CRAN(ComprehensiveR Archive Network,R语言综合典藏网)接口,如安装失败可尝试不同的CRAN。

有些专项的包,有独特的安装方式,例如生物学数据分析最常用的BioconductorProject(http://www.bioconductor.org/),其安装方法如下所示:

代码语言:javascript复制
source("https://bioconductor.org/biocLite.R")
biocLite("packagename")

此外,很多软件包并不包含在R的CRAN内,而在一些托管平台,最常见的为GitHub(https://github.com/),安装托管软件可以使用devtools软件包,安装方法一般为:

代码语言:javascript复制
devtools::install_github("class/packagename")

其中class也即该软件在GitHub上存放的类别。查看当前环境中已经安装的软件包,可以使用如下命令:

代码语言:javascript复制
.packages(all.available=T)

更为详细地,查看已经安装的软件包的版本、安装路径等信息可以使用如下命令:

代码语言:javascript复制
installed.packages()[,c('Package','Version','LibPath')]

查看当前版本的R可以安装的软件包,可以使用如下命令:

代码语言:javascript复制
available.packages()

利用该命令,我们可以查询想要安装的软件包是否在R的仓库里:

代码语言:javascript复制
ap=available.packages()
grep('packagename', rownames(ap))

安装好的软件包,在使用之前需要library()函数加载,才能调用其中的函数。require()函数同样可以调用软件包,区别在于require会返回一个布尔值(True或False)来表示被加载的包是不是可用,而library函数会根据调用方式不同而有不同返回结果。

使用命令:

代码语言:javascript复制
(.packages())

可以查看当前工作环境加载的R包,使用命令:

代码语言:javascript复制
detach("package:packagename")

可以从当前工作环境移除R包。

关于软件包的使用说明,可以使用help()或者直接??packagename来查询,使用命令help(package='packagename')可以查看某个软件包所包含的全部函数。此外,一个很重要的软件包是installr,其中的updateR()函数能将R更新到最新,并将已安装的兼容最新版本的程序包整合到新版本R中,如下所示:

代码语言:javascript复制
library(installr)
updateR()

1.6输入与输出

R可以通过键盘输入数据,也可以导入其他数据框软件生成的数据,常用的一般为文本文件、Excel文件、Web文件等。

⑴键盘输入数据

函数edit()会自动调用一个允许手动输入数据的文本编辑器,来为对象(向量、矩阵、数据框)赋值,如下所示:

代码语言:javascript复制
mydata=data.frame(a1=numeric(0), a2=numeric(0), a3=character(0))
mydata=edit(mydata)

在这个编辑器里点击变量名可以更改变量类型(数值型、字符型),还可以点击未命名的变量(var4...)添加新变量。可以直接从其他地方复制数据并粘贴进去。关闭编辑器后,输入的数据即被保存赋值。

⑵从带分隔符的文本文件导入数据

函数read.table()可以从带分隔符的文本文件导入数据,此函数读入一个表格格式的文件并保存为数据框,使用方法如下:

代码语言:javascript复制
read.table("file", header=FALSE, sep = "",quote = ""'",
           row.names, col.names,na.strings = "NA", 
           colClasses =NA, check.names = TRUE
          stringsAsFactors = default.stringsAsFactors())

其中file为文件名,header=FALSE第一行不是变量名(R会添加默认变量名),为TRUE则会使用第一行作为变量名;row.names、col.names设置那一列为行名字,哪一行为列名字;sep设置分隔符,默认是一个或多个空格、制表符tab;设置stringsAsFactors=FALSE则不会把字符型自动转化为因子;colClasses可以设置每一列的模式(logical、numeric、character);check.names是否检查变量名(合不合语法要求);quote=""'"表示单双引号内部为完整字符串的一部分,这对于字符串内含有与分隔符相同字符时很有用,需要与sep搭配设置。注意文件名前需要添加完整的目录(路径不同层级之间使用/或\)。

一般情况下,我们把文件都复制到工作路径方便引用,查询当前路径使用getwd(),更改路径使用setwd(),如下所示:

除了read.table()外,还有专门读取逗号分隔的csv文件的read.csv()等,如下所示:

⑶保存导出数据

R输出文件包括数据的输出、图片的输出。数据输出可以使用write.table(),其使用方法与read.table()类似,如下所示:

代码语言:javascript复制
write.table(object, file="filename", quote=F,row.names=F, col.names=T, sep='t')

其中quote设置字符型元素是否用引号引起来。

对于图片,我们更推荐直接使用Rstudio的图形界面输出图片。在脚本中可以使用pdf()函数直接保存图片,如下所示:

代码语言:javascript复制
pdf("practice.pdf", width=9, height=9)
x=1:10
y=1:10
plot(x, y, type="p")
dev.off()

图片会自动保存在当前工作路径。

0 人点赞