向量:一维
矩阵matrix
数据类型都相同,两个维度行数、列数。
matrix生成矩阵的函数,默认按列排,按行排标by row。
> x=sample(1:100,28) #sample函数随机取样,每次取出来的都不一样
> matrix(x,nrow = 7)
[,1] [,2] [,3] [,4]
[1,] 82 35 76 4
[2,] 12 16 19 1
[3,] 44 17 100 98
[4,] 52 41 70 68
[5,] 46 86 81 36
[6,] 18 94 67 56
[7,] 89 92 21 20
给随机的东西可重复性,让每次取出来的数一样
set.seed设置随机种子,每一次取数必须set.seed和函数一起连用
> #设置随机种子
> set.seed(10201) #随便写数字
> sample(letters,10)
[1] "a" "z" "r" "x" "h" "c" "f" "q" "w" "e"
> set.seed(10201)
> sample(letters,10)
[1] "a" "z" "r" "x" "h" "c" "f" "q" "w" "e"
> sample(letters,100)
Error in sample.int(length(x), size, replace, prob) :
cannot take a sample larger than the population when 'replace = FALSE'
?sample
#repalce默认F,不放回
> x=sample(letters,100,replace = T)
> x
[1] "m" "m" "i" "t" "o" "l" "o" "f" "l" "w" "d" "z" "x" "y" "v" "d" "s" "o" "q" "p" "t" "n" "f" "d" "b" "n" "d" "x" "g" "p"
[31] "m" "p" "c" "z" "h" "g" "d" "o" "x" "k" "i" "y" "z" "s" "w" "m" "o" "k" "d" "y" "q" "i" "o" "y" "n" "i" "c" "p" "r" "x"
[61] "x" "s" "l" "t" "z" "i" "y" "j" "g" "b" "d" "n" "r" "r" "e" "q" "s" "p" "g" "w" "q" "m" "q" "m" "h" "o" "m" "g" "g" "u"
[91] "z" "z" "m" "d" "y" "e" "h" "r" "e" "i"
> unique(x)
[1] "m" "i" "t" "o" "l" "f" "w" "d" "z" "x" "y" "v" "s" "q" "p" "n" "b" "g" "c" "h" "k" "r" "j" "e" "u"
#回答有多少个取值
> length(unique(x))
[1] 25
> length(table(x))
[1] 25
> sum(!duplicated(x))
[1] 25
cbind三个向量按列拼接 向量名字带过来,不同于list,名字带不过来
> x1 = sample(1:100,7);x1
[1] 62 86 70 65 6 27 52
> x2 = 11:17;x2
[1] 11 12 13 14 15 16 17
> x3 = sample(1:10,7);x3
[1] 7 10 1 8 9 3 5
> cbind(x1,x2,x3) #向量名字带过来
x1 x2 x3
[1,] 62 11 7
[2,] 86 12 10
[3,] 70 13 1
[4,] 65 14 8
[5,] 6 15 9
[6,] 27 16 3
[7,] 52 17 5
数据框data.frame
概念:多个长度相同,数据类型可以不同的向量组合在一起。
列表list
概念:长度可以不同,数据类型可以不同。没有行列概念,可有多级元素。
integer整数型,数值型的一种。
数据框的两种显示形式
1.在environment里面直接点名字,查看预览视图,相当于View(df)
2.控制台显示形式(纯文本)
作图要处理的数据绝大多数在数据框
写嵌套式代码时从外往里写
打开02_data_structure.R
options(stringsAsFactors = F)
字符串转换成因子否,注意不要用因子,options开头的函数表设置
数据框来源
(1)在R中新建
(2)由已有数据转换或处理得到 as.dataframe()
(3)从文件中读取
df2 <- read.csv("gene.csv")
(4)内置数据集
新建数据框
本质上是向量按列组合
df <- data.frame(gene = c("gene1","gene2","gene3"),
sam = c("sample1","sample2","sample3"),
exp = c(32,34,45))
等号左边列名,等号右边列的内容,列与列的分隔逗号分隔。
数据框的行:向量个数,数据框的列:多少等式,多少列名。
读取文件,得到数据框
df2 <- read.csv("gene.csv") #gene.csv文件名
数据框属性描述
dim(df)
nrow(df)
ncol(df)
rownames(df)
colnames(df)
数据框取子集(一个、一行、一列、多行多列)
1.选一个 用坐标
df[2,2]
选一行/一列
左边是行,右边是列
逗号作用:维度分割
中括号里的逗号,表示维度的分割
df[2,]
df[,2]
行列双选:把要选的行组成一个向量,要选的列组成一个向量
df[c(1,3),1:2]
2.根据行名或列名选择
df[,“exp”]
df[,c(“gene”,“exp”)] 把这几列的列名写成一个向量
当行数和列数很多时,这个操作就很有用,不用数行列数。
向量也可以根据“名字”提取。
编程习惯,可修改空间。重复使用代码,把可能变化的东西赋值给一个新的变量。
nn = c("gene", "exp")
df[,nn]
反选,去掉最后一列
df[,-col(df)] #df变化,ncol跟着变化
3.提取列的常用操作
数据框常用操作:df$exp,这样就是个向量
$只能提取1列,可自动补齐
tab/回车补齐。
**能对向量进行的计算和统计,都能对df$exp做**
max(df$exp) 最大值
3.按照逻辑值取子集。见练习题。
数据框修改:本质:修改向量
取子集$或[] +赋值操作
改一个格
df[3,3]<- 5
改一整列
df$exp<-c(12,23,50) 现成列名,表修改
df$abc <-c(23,15,37) 新列名,表新增一列
写成向量,只写1个数字,一列都被改为同一个数字
误操作怎么办
运行了错误的代码,不能撤销,但可以覆盖
重新赋值一次就行。对变量多次赋值,以最后一次为准。
改全部行名和列名
rownames(df) <- c("r1","r2","r3")
改一个行名
rownames(df)[2]="x"
把行名这个向量提取出来,对向量取子集再赋值。不是对数据框取子集再改行名。
修改第二列的行名,就是修改行名这个向量的第二个元素
练习
4.修改test前两列的列名为Length和Width
colnames(test)[1:2] = c("Length","Width")#对
colnames(test[,1:2])=c("Length","Width")#错,在改子集的名字,而不是数据本身
子集已经是一个新的数据,修改它的行名列名跟原来的数据框无关。
5.提取test中,最后一列值为versicolor或setosa的行,组成一个新的数据框,赋值给test2。
test2 = test[test$Species %in% c("versicolor","setosa"),] #%in%放松
test2 = test[test$Species!="virginica",] #反选慎重,反选一定要考虑到所有情况,只能有3个取值。
class(test[,1])
[1] "numeric"
class(test[1])
[1] "data.frame"
#只写一个维度,test[1],默认取列,并且保留数据框的属性。
#iris[,1:4]和iris[1:4]一样,只写一个维度默认取列,取多列时无差别,只在取一列时有差别。
test[,1],属性向量。
数据框跟向量一样,可以按照逻辑值取子集。按行取子集,逻辑值的数必须和行数一致。
统计逻辑值向量有多少个TRUE,可以用table,sum。
数据框进阶
1.行数较多的数据框可以截取前/后几行查看
head(iris) #作者默认前6行
head(iris, 3) #自定义前3行
tail(iris) #后6行
2.行列数都多的数据框可取前几行前几列查看
不经过赋值,只是输出、看看
iris[1:3, 1:3] #就是数据框取子集
3.查看每一列的数据类型和具体内容
str()
数据框,5行数,2列数
x1,x2列名,chr int 这两列的数据类型,integer 是numeric中的一种 整数;列出了每一列的前几个数值
str(iris)
'data.frame': 150 obs. of 5 variables:
$ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
$ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
$ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
$ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
$ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
factor,level这两个关键词,碰上因子,躲着点。
-
去除含有缺失值的行
na.omit(df)
仅按照某一列来去除缺失值、缺失值替换:tidyr包
- 两个表格的连接
- 按列连接:cbind 前提:行数相同
- 按行连接:rbind 前提:列数相同
-
智能连接:只要有共同的一列内容相同
取交集,merge按照第2个的顺序
内容有交集,但列名不同。大小写不同,R语言严格区分大小写。
法一:数据框修改列名
法二: merge(test1, test3, by.x= "name", by.y= "NAME")
注意顺序对应,x y不能改
交集、并集、补集、全集等,参考dplyr包
6. 如果列名顺序错乱,如何按照指定顺序重排?
数据框列的顺序错乱,如何重排
矩阵新建和取子集
m <- matrix(1:9, nrow = 3)
m
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
取子集:行数、列数;逻辑值;行名、列名
区别: $
只有数据框、列表能用,矩阵不支持 $
矩阵的转置和转换
t(m) #行变列,列变行,行名列名跟着走
as.data.frame(m)
矩阵画热图
pheatmap::pheatmap(m) #默认按聚类树画
pheatmap::pheatmap(m, cluster_cols = F, cluster_rows = F)
列表新建和取子集
l <- list(m = matrix(1:9, nrow = 3),
df = data.frame(gene = paste0("gene",1:3), sam = paste0("sam", 4:6)),
x = c(1,3,5))
l$m
l$df
l$x
l[[2]]
新建列表:list
取子集:
没有名字按位置:l[[2]] 提取出干净的矩阵、数据框。区别于[],仍是列表。
[1] "matrix" "array" #矩阵是一个特殊的数组,所以后面写array
> class(tl[2])
[1] "list"
有名字:l$df
删除变量
删除一个rm(l) 变量名
删除多个rm(df,m)
删除全部rm(list = ls())
清空控制台 ctrl+l 仅清空控制台,没有清空任何数据
rm只能删除整个变量,不能删除一个变量的一部分
数据结构的总结
补充:元素的“名字” - names()
元素可命名,用函数names(),
可以根据名字提取子集,向量、数据框、列表通用。
> x =1:10
> names(x) = letters[1:10]
> x
a b c d e f g h i j
1 2 3 4 5 6 7 8 9 10
> x["a"] #向量根据名字提取子集
a
1
> class(x)
[1] "integer" #名字不影响数据类型
letters 内置数据:没有赋值就可以直接调用的数据就是内置数据
练习3-2
#3.将test的行名改为flower1,flower2...flower149,flower150。
rownames(test) <- paste0("flower",1:nrow(test))
注意,这里建议用nrow(test),而不是直接写150
#4.将test的第51到100行删除
test <- test[-(51:100),]
注意:错误写法
> rm(test[(51:150),])
Error in rm(test[(51:150), ]) : ...要么含名字,要么是字符串
rm只能删除整个变量,不能删除变量的一部分
> class(tl[[2]])
[1] "matrix" "array" #矩阵是一个特殊的数组,所以后面写array
> class(tl[2])
[1] "list"
identical判断两个数据是否完全相同
identical(tl[[2]],tl[2])
[1] FALSE #数据类型,数据结构,顺序等不相同
#6.提取tl的第二个元素
> tl <- list(iris,test) #这里要给元素命名,否则后面麻烦
> tl$x2
NULL
> tl$test #列表并没有把元素的名字带过来
NULL
> names(tl)
NULL
#7.修改tl第二个元素的名字为td
> names(tl)[2] <- "td"
> names(tl)
[1] NA "td"
> names(tl)[1] <- "iris"
> names(tl)
[1] "iris" "td"
向量匹配排序 - match
match(x,y):将x作为模板,调整y的顺序,返回的结果是y的下标
match:谁在外面,谁就在后面
y[match(x,y)]:y按照x的顺序重新排序
match大有用处
法一 依照x动y
#我的做法:把x$ID赋值给x的行名,把x$file name按照y的列名排序,再把rownames(x)赋值给colnames(y)。这样只用改y的列名顺序,不用改动内容顺序。
#关键点:按照x$file_name调整y的内容顺序,列名是随之而动的。
load("matchtest.Rdata")
x$file_name
colnames(y)#这两个向量内容相同,顺序不同
a=match(x$file_name,colnames(y))
#返回的结果是y列名的下标,列名的下标就是列的顺序
colnames(y)=colnames(y)[a]#这样只有y的列名改变了顺序,列的内容并没有跟着改变
y=y[,a]#a在逗号右边,表示调整列的顺序
#现在y的内容已经调好顺序,y的列名顺序随之改变
> identical(x$file_name,colnames(y)) #确保y和x的顺序一样
[1] TRUE
> colnames(y)=x$ID
法2 依照y动x,简单
load("matchtest.Rdata")#刚刚的方法y的值已改变,重新加载
colnames(y)=x$ID[match(colnames(y),x$file_name)]
#x$ID用x$file_name的下标处理,因为同一个数据框里下标通用
#只用一句代码,依照y的顺序调整x的顺序,最终就只用换y的列名,不用动内容