今天进一步跟随生信星球的豆豆和花花了解R的数据结构,因为之前接触过,因此笔记就主要是记录一下自己在运行代码过程中的一些探索吧。
认识数据结构
- 数据类型包括五种,有向量、矩阵、数组、数据框、List。
1.向量
向量是用于存储数值型、字符型或逻辑型数据的一维数组。可以通过c()
函数来创建向量。
a<-c(1,2,3,4,5,6) #数值型向量
b<-c("one","two","three") #字符型向量
c<-c( TRUE,FALSE,TRUE) #逻辑型向量
- 注意:单个向量中的数据必须拥有相同的类型或模式,不能再同一个向量混杂不同模式的数据
- 在花花老师的教程中,创建向量也用到了
rep()
函数和seq()
函数,前者为重复数值函数,后者为顺序函数。咱们来实战看看结果。
#rep()函数
>x<-rep(1:4,each=2) #每个数值单独重复两遍
>x
[1] 1 1 2 2 3 3 4 4
>x<-rep(1:4,2) #x<- rep(1:4,times=2)
>x
[1] 1 2 3 4 1 2 3 4
>x<-rep(1:4, c(2,2,2,2)) #rep(1:4,each=2)
[1] 1 1 2 2 3 3 4 4
>x<-rep(1:4, c(2,1,2,1) #每个数值各有各的情况
[1] 1 1 2 3 3 4
#seq()函数
> seq(0, 1, length.out = 11)
[1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
> seq(stats::rnorm(20)) # effectively 'along'
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
> seq(1, 9, by = 2) # matches 'end'
[1] 1 3 5 7 9
> seq(1, 9, by = pi) # stays below 'end'
[1] 1.000000 4.141593 7.283185
> seq(1, 6, by = 3)
[1] 1 4
> seq(1.575, 5.125, by = 0.05)
[1] 1.575 1.625 1.675 1.725 1.775 1.825 1.875 1.925 1.975 2.025
[11] 2.075 2.125 2.175 2.225 2.275 2.325 2.375 2.425 2.475 2.525
[21] 2.575 2.625 2.675 2.725 2.775 2.825 2.875 2.925 2.975 3.025
[31] 3.075 3.125 3.175 3.225 3.275 3.325 3.375 3.425 3.475 3.525
[41] 3.575 3.625 3.675 3.725 3.775 3.825 3.875 3.925 3.975 4.025
[51] 4.075 4.125 4.175 4.225 4.275 4.325 4.375 4.425 4.475 4.525
[61] 4.575 4.625 4.675 4.725 4.775 4.825 4.875 4.925 4.975 5.025
[71] 5.075 5.125
> seq(17) # same as 1:17, or even better seq_len(17)
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- 从向量中提取元素
> x<- rep(1:4,times=2) #向量
> x
[1] 1 2 3 4 1 2 3 4
> x[4] #挑取第4个元素
[1] 4
> x[-4] #去掉第4个元素
[1] 1 2 3 1 2 3 4
> x[2:4] #挑取第2-4个元素
[1] 2 3 4
> x[-(2:4)] #去掉第2-4个元素
[1] 1 1 2 3 4
> x[c(1,5)] #挑取第1和第5个元素
[1] 1 1
#根据值挑取
>x[x%in%c(1,4,6)] #从x中挑取存在于向量c(1,4,6)中的元素,处理表达矩阵也经常用到
[1] 1 4 1 4
2.矩阵
矩阵是一个二维数组,只是每个元素都拥有相同的模式(数值型、字符型或逻辑型),可以通过函数matrix()
创建矩阵。
> y<-matrix(1:20,nrow = 5,ncol = 4)
> y
[,1] [,2] [,3] [,4]
[1,] 1 6 11 16
[2,] 2 7 12 17
[3,] 3 8 13 18
[4,] 4 9 14 19
[5,] 5 10 15 20
> cells<-c(1,26,24,68)
> rnames<-c("R1","R2")
> cnames<-c("C1","C2")
> mymatrix<-matrix(cells,nrow = 2,ncol = 2,byrow = TRUE,dimnames = list(rnames,cnames)) #byrow = TRUE,按行(row)填充2*2矩阵
> mymatrix
C1 C2
R1 1 26
R2 24 68
> mymatrix<-matrix(cells,nrow = 2,ncol = 2,byrow = FALSE,dimnames = list(rnames,cnames)) #byrow = FALSE,按列填充2*2矩阵
> mymatrix
C1 C2
R1 1 24
R2 26 68
#提取元素
> y[2,] #[行,列]提取第2行数据
[1] 2 7 12 17
> y[,2] #提取第2列数据
[1] 6 7 8 9 10
> y[1,4] #提取第1行第4个元素
[1] 16
3.数组
数组与矩阵类似,但是维度可以大于2,不只包括行和列,可以通过函数array()
函数创建。myarray<-array(vector,dimensions,dimname)
dimensions是一个数值型向量,dimnames是可选的、各维度名称标签的列表。
> dim1<-c("A1","A2")
> dim2<-c("B1","B2","B3")
> dim3<-c("C1","C2","C3","C4")
> z<-array(1:24,c(2,3,4),dimnames = list(dim1,dim2,dim3)) #dim3=4维,行为dim1,列为dim2
> z
, , C1
B1 B2 B3
A1 1 3 5
A2 2 4 6
, , C2
B1 B2 B3
A1 7 9 11
A2 8 10 12
, , C3
B1 B2 B3
A1 13 15 17
A2 14 16 18
, , C4
B1 B2 B3
A1 19 21 23
A2 20 22 24
#提取元素
> d<-z[1,2,3] #z数组中的C3中的矩阵中第一行第二个元素,提取元素时量度数目一定要对应
> d
[1] 15
4.数据框
数据框中不同的列可以包含不同模式(数值型、字符型等)的数据,是R中经常要处理的数据结构。可以通过函数data.frame()
来创建。mydata<-data.frame(col1,col2,col3,.....)
> patientID<-c(1,2,3,4)
> age<-c(25,34,28,52)
> diabetes<-c("Type1","Type2","Type1","Type1")
> status<-c("Poor","Improved","Excellent","Poor")
> patientdata<-data.frame(patientID,age,diabetes,status)
> patientdata
patientID age diabetes status
1 1 25 Type1 Poor
2 2 34 Type2 Improved
3 3 28 Type1 Excellent
4 4 52 Type1 Poor
#选取数据框中的元素
> patientdata[1,] #挑取第1行
patientID age diabetes status
1 1 25 Type1 Poor
> patientdata[1:3,] #挑取第1到3行
patientID age diabetes status
1 1 25 Type1 Poor
2 2 34 Type2 Improved
3 3 28 Type1 Excellent
> patientdata[1:3] #挑取第1到3列
patientID age diabetes
1 1 25 Type1
2 2 34 Type2
3 3 28 Type1
4 4 52 Type1
> patientdata$patientID #挑取特定列可以用$
[1] 1 2 3 4
- 每次都要键入patientdata$实在是太麻烦了,懒虫走捷径的时候到了!!!
1.attach()、detach()和with()
可以通过联合使用函数attach()
和detach()
或者单独使用with()
来达到简化代码的效果。
#此处以R自带的mtcars数据框来讲述这三个函数
> str(mtcars) #查看mtcars的类型为data.frame,有32行,11个变量
'data.frame': 32 obs. of 11 variables:
$ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
$ cyl : num 6 6 4 6 8 6 8 4 4 6 ...
$ disp: num 160 160 108 258 360 ...
$ hp : num 110 110 93 110 175 105 245 62 95 123 ...
$ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
$ wt : num 2.62 2.88 2.32 3.21 3.44 ...
$ qsec: num 16.5 17 18.6 19.4 17 ...
$ vs : num 0 0 1 1 0 1 0 1 1 1 ...
$ am : num 1 1 1 0 0 0 0 0 0 0 ...
$ gear: num 4 4 4 3 3 3 3 4 4 4 ...
$ carb: num 4 4 1 1 2 1 4 2 2 4 ...
> summary(mtcars$mpg)
Min. 1st Qu. Median Mean 3rd Qu. Max.
10.40 15.43 19.20 20.09 22.80 33.90
> plot(mtcars$mpg,mtcars$disp)
> plot(mtcars$mpg,mtcars$wt) #每次都要输入前面的对象真的好麻烦
> attach(mtcars) #关联数据框
> summary(mpg)
Min. 1st Qu. Median Mean 3rd Qu. Max.
10.40 15.43 19.20 20.09 22.80 33.90
> plot(mpg,disp)
> plot(mpg,wt)
> detach(mtcars) #取消关联数据框,否则会影响其他操作
#但是当名称相同的对象不止一个时,这种方法会显得十分局限
> attach(mtcars)
The following object is masked _by_ .GlobalEnv:
mpg
> plot(mpg,disp)
Error in xy.coords(x, y, xlabel, ylabel, log) :
'x' and 'y' lengths differ
> mpg #数据框mtcars被attach()绑定之前,环境中就有一个mpg对象了,在这种情况下,原始对象将取得优先权,因此会出现报错。
[1] 24 24 26 26
> with(mtcars,{
print(summary(mpg))
plot(mpg,disp)
plot(mpg,wt)
})
Min. 1st Qu. Median Mean 3rd Qu. Max.
10.40 15.43 19.20 20.09 22.80 33.90
#用with()函数进行关联
> with(mtcars,{
nokeepstats<-summary(mpg)
keepstats<<-summary(mpg)
})
> nokeepstats #在Rstudio右上方中没有找到这个对象的数值
错误: 找不到对象'nokeepstats'
> keepstats #在Rstudio右上方中可以找到这个对象的数值
Min. 1st Qu. Median Mean 3rd Qu. Max.
10.40 15.43 19.20 20.09 22.80 33.90
#特殊赋值符:<<-替代标准赋值符<-可以将对象保存在with()之外的全局环境
- 在输入
with()
函数时有一个疑问,应该怎样在控制台上令操作命令换行呢?
同时按住shift
和enter
就可以啦!
5.列表
列表是R的数据类型中最为复杂的一种。一般来说,列表是一些对象的有序集合。列表允许你整合若干(可能无关的)对象到单个对象名下。例如,某个列表中可能是若干向量、矩阵、数据框,甚至其他列表的组合。可以使用list()
创建列表。
> g<-"My First List"
> h<-c(25,26,18,39)
> j<-matrix(1:10,nrow=5)
> k<-c("one","two","three")
> mylist<-list(title=g,ages=h,j,k)
> mylist
$title
[1] "My First List"
$ages
[1] 25 26 18 39
[[3]]
[,1] [,2]
[1,] 1 6
[2,] 2 7
[3,] 3 8
[4,] 4 9
[5,] 5 10
[[4]]
[1] "one" "two" "three"
> mylist[[2]] #输出list的第2个成分,即ages
[1] 25 26 18 39
数据的导入和导出
(1)读取本地数据
>setwd(" 本地工作目录 ") #注意要用正斜杠/
>getwd() #查看当前工组目录,以确保要导入的文件是否在当前工作
> read.table(file = 'huahua.txt',sep = '\t',header = T)
X1 X2
1 A 1
2 B NA
3 C NA
4 D 3
5 E NA
> read.table(file = 'huahua.txt',sep = '\t',header = F) #header=FALSE时,会自动剔除掉NA值
V1 V2
1 X1 X2
2 A 1
3 B
4 C
5 D 3
6 E
- sep 是函数的形式参数,多数情况下, seq 参数用来指定字符的分隔符号。csv 文件是用逗号分隔的,故而 sep = ","tsv 文件是用制表符分隔的,故而 sep = "\t"常用的分隔符还有空格 sep = " "分隔符是任意的,可根据具体情况指定的。在输入的时候,原内容是用什么符号分隔的,sep就要保持一致,否则可能无法正确读取。
(2)设置行名和列名
> x<-read.csv('doudou.txt')
> x
X1 X2
1 A 1
2 B NA
3 C NA
4 D 3
5 E NA
> colnames(x)
[1] "X1" "X2"
> rownames(x)
[1] "1" "2" "3" "4" "5"
>colnames(x)[1]<-'bioplanet' #修改第一行第一个元素名称
bioplanet X2
1 A 1
2 B NA
3 C NA
4 D 3
5 E NA
(3)数据框的导出
write.table(x,file = "yu.txt",sep = ",",quote=F) #分隔符改为以逗号分隔,字符串不加双引号
write.table(x,file = 'li.txt',sep = ',',quote = T)
一个小问题:
save(X,file="test.RData")
这句代码如果报错object X not found,是为什么,应该怎么解决?
- 这个就要看自己是不是没有赋值X了,因为报错提醒找不到X对象,注意这里的X是大写的。如果没有赋值就要添加一个赋值如:X<-,如果前面运行的是小写的x,那这里的保存对象应该改回x。
参考:
R语言实战(第2版)
生信星球
R语言里的sep什么意思
R语言实践之Rstidio代码换行输入