本培训使用R 4.2及以上版本。
一、前言
用R分析数据得出结果,需要解决两个问题:
用什么包/函数来处理数据?
如何整理数据,使得数据可以套进函数里进行处理?
(一)在R中新建项目
方式:RStudio中,菜单栏File→NewProject→NewDirectory→NewProject→DirectoryName
该方式通过新建一个目录的方式来新建一个项目,创建一个R的项目文件(Rproj):
- 将所有与该项目相关的数据、脚本、文件等都存放在该项目文件夹下,每次通过运行Rproj文件启动项目,自动关联相关文件,便于统一管理和调试。
- 该项目的工作目录即为新建该项目创建的目录。即后续创建的脚本文件默认保存位置均为该目录。
- 项目目录移动后,项目中的文件、脚本仍然可以通过项目文件(Rproj)关联使用。
(二)在项目中新建脚本
方式:Rstudio菜单栏,File→NewFile→RScript
保存:
- R脚本保存的文件后缀为.R
- 保存的默认位置为当前的工作目录(working directory)
Tips:
脚本中点击Run或快捷键ctrl+Enter,执行光标所在行的代码,光标会移动到下一行
脚本中选中多行,点击Run,执行所选的代码
使用#为脚本添加注释。让自己和其他协作者了解代码的用途。R不会执行#后面的内容。
(三)与R交互的两种方式
1. 控制台窗口(console)
显示每个命令的结果
2. 脚本编辑器
记录工作代码,让代码和工作流程具有可重复性。
点击Run来运行代码
(四)程序运行的问题指南
1. 出现ERROR
即报错。需要对症处理。
2. 长时间运行中,并未出现命令提示符>
可能卡住了。点击console窗口右上角红色STOP按钮终止程序运行。
3. 运行出结果、没反应、出现warning、其他提示信息,出现新一行的命令提示符>
目前一切顺利
4. 出现问题
必须回答。
5. 出现+
代码不完整。补齐代码,或按ESC键退出。
二、数据类型
- 数值型(numeric)
1.3 2 - 字符型(character)
“a” “nn” - 逻辑型(logical)
TRUE(T) FALSE(F) NA
NA:为缺失值,表示存在但未知。
NULL:为空,表示没有这个值(不存在)。
可以用函数class()来判断数据的类型。
Tips:打出前几个字母即出现提示,用上下键翻动,Tab键自动补全
(一)逻辑型数据
比较运算
比较运算的结果是逻辑值。
比较运算符号:
<,>, >=, <=, ==(判断是否相等), !=(判断是否不等)
举例:
> 3==5
[1] FALSE
> 3!=5
[1] TRUE
多个逻辑条件的连接
连接符号:
& 表示和/与
| 表示或
!表示非
举例:
> 3<5&4>5
[1] FALSE
> 3<5 | 4>5
[1] TRUE
> !(4>5)
[1] TRUE
(二)数据类型的判断和转换
is族函数,判断数据类型,返回值为逻辑值
is.numeric()
是否为数值型数据
is.logical()
是否为逻辑型数据is.character()
是否为字符型数据
as族函数实现数据类型之间的转换
as.numeric()
将其他数据类型转换为数值型
as.logical()
将其他数据类型转换为逻辑型as.character()
将其他数据类型转换为字符型
本节函数
1. class()
描述:判断数据类型。
举例:
> class(2)
[1] "numeric"
> class('abc')
[1] "character"
> class(FALSE)
[1] "logical"
> class(NA)
[1] "logical"
2. is.numeric()
描述:判断是否为数值型数据
举例:
> is.numeric("a")
[1] FALSE
> is.numeric("4")
[1] FALSE
3. is.logical()
描述:判断是否为逻辑型数据
举例:
> is.logical(FALSE)
[1] TRUE
4. is.character()
描述:判断是否为字符型数据
举例:
> is.character("4")
[1] TRUE
5. as.numeric()
描述:将其他数据类型转换为数值型
举例:
> as.numeric('4')
[1] 4
> as.numeric('jimmy')
[1] NA
Warning message:
NAs introduced by coercion
讨论:开始讲,NA表示“存在但未知”,as.numeric("jimmy")返回NA,意思是可以将Jimmy这个字符串转换成数值类型,但是这个这个值是未知的?R转换了类型,但不知道是个啥,所以返回了NA。NA也有数值型NA和字符型NA。
参见以下代码:
> a <- 'jimmy'
> class(a)
[1] "character"
> a <- as.numeric(a)
Warning message:
NAs introduced by coercion
> class(a)
[1] "numeric"
6. as.logical()
描述:将其他数据类型转换为逻辑型
举例:
> as.logical(4)
[1] TRUE
> as.logical('a')
[1] NA
7. as.character()
描述:将其他数据类型转换为字符型
举例:
> as.character(4)
[1] "4"
> as.character(TRUE)
[1] "TRUE"
三、数据结构
R语言中主要有4种数据结构,如下:
- 数据框约等于“表格”。数据框要求每一列只能有一种数据类型,且数据框只是R语言内部的一个数据,不是一个文件。
- 数据框单独拿出来的一列是一个向量,视为一个整体。一个向量可以出自数据框的一列,也可以用代码生成。
- 一个向量只能有一种数据类型,可以有重复值。
Tips:若打开的脚本文件是乱码,可以将编码修改成UTF-8来解决(File→Reopen with Encoding→UTF-8)。若还不行,则脚本文件本身可能已经损坏。
(一)向量(vector)
向量是一维的。
I.向量的生成
1. 用函数c()集合在一起生成
举例:
> c(2,5,6,2,9)
[1] 2 5 6 2 9
> c('a','f','md','b')
[1] "a" "f" "md" "b"
2. 生成连续的数字向量用冒号“:”
举例:
> 1:5
[1] 1 2 3 4 5
3. 有重复的用函数rep(),有规律的序列用seq(),随机数用rnorm()
举例:
rep('x',times=3)
[1] "x" "x" "x"
> seq(from=3, to=21, by=3)
[1] 3 6 9 12 15 18 21
> rnorm(n=3)
[1] -1.7067961 0.6295338 -0.9499346
4. 通过组合,产生更为复杂的向量
举例:
> paste0(rep('x',times=3),1:3)
[1] "x1" "x2" "x3"
II.对单个向量进行的操作
1. 赋值
举例:
> x <- c(1,3,5,1) #<-是规范的赋值符号,快捷键Alt+-
> x
[1] 1 3 5 1
> x = c(1,3,5,1) #比较随意的写法
> x
[1] 1 3 5 1
赋值和输出一起实现
举例:
> (x <- c(1,3,5,1))
[1] 1 3 5 1
> x <- c(1,3,5,1);x
[1] 1 3 5 1
变量名称的选择:
不建议用函数或包的名称。
不建议用带引号的字符。
可以用字母和数字的组合,但是数字要在字母后面。
不能用空格,运算符号在名称中。可以使用下划线。
不建议用中文作为变量名称。
2. 计算
> x <- c(1,3,5,1);x
[1] 1 3 5 1
> x+1
[1] 2 4 6 2
> log(x)
[1] 0.000000 1.098612 1.609438 0.000000
> sqrt(x) #开方运算
[1] 1.000000 1.732051 2.236068 1.000000
3. 进行比较运算,生成逻辑值向量
> x>3
[1] FALSE FALSE TRUE FALSE
> x==3
[1] FALSE TRUE FALSE FALSE
4. 初级的统计运算
> max(x) #最大值
[1] 5
> min(x) #最小值
[1] 1
> mean(x) #均值
[1] 2.5
> median(x) #中位数
[1] 2
> var(x) #方差
[1] 3.666667
> sd(x) #标准差
[1] 1.914854
> sum(x) #总和
[1] 10
几个重要的统计函数
> length(x) #长度,即向量的元素个数
[1] 4
> unique(x) #去重复,去除向量中重复的元素,只保留第一次出现的那个(从左到右)
[1] 1 3 5
> duplicated(x) #判断对应元素是否在前面(左边)出现过重复。没出现返回FALSE,出现返回TRUE。所以重复的元素,第一次出现返回FALSE,后面的重复都返回TRUE。
[1] FALSE FALSE FALSE TRUE
> table(x) #重复值统计
x
1 3 5 #第一行返回向量中的取值(去重后的向量元素)
2 1 1 #第二行返回每个元素的重复次数
> sort(x) #默认升序排序
[1] 1 1 3 5
> sort(x,decreasing = F) #即默认参数decreasing为FALSE
[1] 1 1 3 5
> sort(x,decreasing = T) #将decreasing改为TRUE,即降序打开,结果将按照降序排列。
[1] 5 3 1 1
本节函数
1. rep()
描述:复制参数x的值。
格式:rep(x, ...)
参数:
x 为向量
... 可以为
times,若为1个元素,则表示重复x向量的次数;若为长度与x向量相等的向量,则表示分别重复x中各元素的次数。
length.out,指定输出向量的长度,从左至右选择,多余的元素舍弃。
each,指定x中每个元素重复的次数。
举例:
> rep('x',times=3)
[1] "x" "x" "x"
> rep(1:4, 2)
[1] 1 2 3 4 1 2 3 4
> rep(1:4, each = 2)
[1] 1 1 2 2 3 3 4 4
> rep(1:4, each = 2, length.out = 4)
[1] 1 1 2 2
2. seq()
描述:生成有规律的序列
格式:seq(from=... , to= ... , by=... )
参数:
from,to 指定序列的起始值和最大结束值
by 指定序列的增量
也可以有length.out参数指定输出向量的长度,则by通过指定的长度计算得出。
举例:
> seq(from=3, to=21, by=3)
[1] 3 6 9 12 15 18 21
3. rnorm()
描述:生成指定个数的服从正态分布的随机数,可以指定均数和标准差。
格式:rnorm(n, mean=0, sd=1)
参数:
n 指定生成的随机数的个数
mean 指定生成随机数的平均数,默认为0
sd 指定生成随机数的标准差,默认为1
举例:
> rnorm(n=3)
[1] -1.7067961 0.6295338 -0.9499346
4. paste0()与paste()
描述:将向量转换成字符型数据后进行连接。
格式:paste(...,sep=" ",collapse=NULL )
paste0与paste(..., sep="", cllapse=NULL)相同
参数:
... 可以是1个或多个向量,当其为1个向量时,其作用相当于函数as.character()
sep 多个向量连接时,指定各元素之间的连接符号,paste默认为空格,paste0固定为空(即元素之间没有连接符号,紧密连接)
collapse 非单元素的多向量连接时,将生成的多个元素合并成1个元素,并指定多元素间合并的连接符号
举例:
> paste0(rep('x',times=3),1:3)
[1] "x1" "x2" "x3"
> paste(rep('x',times=3),1:3, sep=',')
[1] "x,1" "x,2" "x,3"
> paste(rep('x',times=3),1:3, collapse=',')
[1] "x 1,x 2,x 3"
> paste(rep('x',times=3),1:3, collapse='-')
[1] "x 1-x 2-x 3"
5. log()和sqrt()
描述:取对数运算和开方运算的函数
举例:
> x <- c(1,3,5,1)
> log(x)
[1] 0.000000 1.098612 1.609438 0.000000
> sqrt(x)
[1] 1.000000 1.732051 2.236068 1.000000
6. 另外参见文中统计函数部分的函数介绍
探索
练习2-2,1.生成1到15之间所有偶数讲解的答案是:
seq(from=2, to=15, by=2)
讲解中提到,如果:
seq(from=1, to=15, by=2)
则生成1到15的奇数,与题目的要求不符。可以通过加1变成偶数,再想法去掉多出来的16这个数。这种方式比较复杂。但本着熟悉代码的原则,我按照这种思路进行尝试,有以下2种方式得出相同的结果:
seq(1,15,2)c(1:7)+1 #首先取出7个奇数再变成偶数
> 1 2 4 6 8 10 12 14(seq(1,15,2)+1)c(1:7) #先将8个奇数变成偶数,再取出其中7个
> 1 2 4 6 8 10 12 14
Tips:向量只允许一种数据类型存在,当出现不同类型的数据时,会自动根据下图的优先顺序进行转换。
III.对两个向量的操作
1. 比较运算,生成等长的逻辑向量
> x == y
[1] FALSE FALSE TRUE FALSE
> y == x
[1] FALSE FALSE TRUE FALSE
2. 数学计算
> x + y
[1] 4 5 10 7
3. 连接
> paste(x,y,sep=",")
[1] "1,3" "3,2" "5,5" "1,6"
paste与paste0的区别见前文“本节函数”
循环补齐
当两个向量长度不一致时,会通过循环补齐的方式对照较长的那个向量补齐运算。
利用循环补齐简化代码:
> paste0(rep("x",3),1:3)
[1] "x1" "x2" "x3"
> paste0("x",1:3)
[1] "x1" "x2" "x3"
4. 交集、并集、差集
> x;y
[1] 1 3 5 1
[1] 3 2 5 6
> intersect(x,y)
[1] 3 5
> union(x,y)
[1] 1 3 5 2 6
> setdiff(x,y) #取差集,x中有而y中没有的元素,即并集中去掉y,???后文的半连接
[1] 1
> setdiff(y,x) #取差集,y中有而x中没有的元素,即并集中去掉x
[1] 2 6
重点:%in%
x %in% y #x的每个元素在y中是否存在
> x;y
[1] 1 3 5 1
[1] 3 2 5 6
> x %in% y #x的每个元素在y中存在吗
[1] FALSE TRUE TRUE FALSE
> y %in% x
[1] TRUE FALSE TRUE FALSE
%in%返回的逻辑值向量与该符号前面向量中的每个元素一一对应。
==与%in%的区别
当两个向量长度不等时,==会发生循环补齐;而%in%不适用。
==是元素对应位置的比较,有顺序的影响,%in%前后两个向量中所有元素都会互相比较,没有顺序的影响。下图中的问题,则应该使用%in%而不能使用==。(即xx %in% y)
intersect()与%in%的区别
取交集会去重复,而%in%取子集不会。见R_01项目中02_exercise.R练习第6题。
> # 6.向量g中有多少个元素在向量s中存在(要求用函数计算出具体个数)?将这些元素筛选出来
#正确答案
> table(g %in% s)
FALSE TRUE
37 63
> g[g %in% s]
[1] "GFM2" "SLCO1C1" "NYNRIN" "COMMD1"
[5] "COMMD1" "AC017081.1" "RAB7A" "CASKIN2"
[9] "GGT7" "SNRPE" "RGPD3" "ZNF586"
[13] "COMMD1" "GGT7" "URB1" "RAB7A"
[17] "MPP2" "AFG3L2" "URB1" "AC104581.1"
[21] "MPP2" "SNRPE" "ARHGAP1" "ZNF461"
[25] "OR2D3" "CECR5" "SPDL1" "CLEC17A"
[29] "ZNF461" "ATG10" "ATG10" "ATG10"
[33] "SLC25A25" "SLC30A9" "SLCO1C1" "GGT7"
[37] "CASKIN2" "GSTP1" "MPP2" "NYNRIN"
[41] "INTS12" "MPP2" "RGPD3" "RGPD3"
[45] "SLC30A9" "C10orf128" "HBD" "SLC30A9"
[49] "GGT7" "HEPH" "RP5-1021I20.4" "KLHDC8A"
[53] "HBD" "ZNF586" "CECR5" "OR2D3"
[57] "LIPE" "INTS12" "LIPE" "SPDL1"
[61] "SLCO1C1" "GGT7" "CECR5"
#错误使用取交集函数。
> length(intersect(g,s))
[1] 32
IV.向量筛选(取子集)
用 将TRUE对应的值挑选出来,FALSE丢弃。
> x <- 8:12
> x
[1] 8 9 10 11 12
#根据逻辑值取子集
> x[x==10]
[1] 10
> x[x<12]
[1] 8 9 10 11
> x[x %in% c(9,13)]
[1] 9
#根据位置取子集
> x[4]
[1] 11
> x[2:4]
[1] 9 10 11
> x[c(1,5)]
[1] 8 12
> x[-4] #-表示除了该位置的其他元素都取出来,只支持数字,不支持逻辑值。逻辑值取相反用叹号!
[1] 8 9 10 12
> x[-(2:4)]
[1] 8 12
Tips:
-(减号)表示除了该位置的其他元素都取出来,只支持数字,不支持逻辑值。逻辑值取相反用!(叹号)
重点:
按照逻辑值:中括号里是与x等长且一一对应的逻辑值向量。
按照位置:中括号里是由x下标组成的向量。
因此,指定向量中的具体某个元素时,无论用逻辑值还是位置来指定,都必须使用向量。
下面的代码会报错:
> x
[1] 8 9 10 11 12
> x==10
[1] FALSE FALSE TRUE FALSE FALSE
> x[FALSE,FALSE,TRUE,FALSE,FALSE]
Error in x[FALSE, FALSE, TRUE, FALSE, FALSE] :
incorrect number of dimensions
> x[3,5]
Error in x[3, 5] : incorrect number of dimensions
报错中显示维度错误。向量是一维的,中括号中逗号分割表示多维度,所以报错。指定多维度的数据时,用逗号分割。
V.修改向量中的某个(些)元素
1. 改一个元素
> x
[1] 8 9 10 11 12
> x[4] <- 40
> x
[1] 8 9 10 40 12
2. 改多个元素
> x
[1] 8 9 10 11 12
> x[c(1,5)] <- c(80,20)
> x
[1] 80 9 10 40 20
注意:修改元素就是取子集+赋值的联合操作。
VI.简单向量作图
> k1 = rnorm(12);k1
[1] 0.04332943 -0.75023874 0.51691113 1.10119324
[5] 1.59135095 -0.04078699 -0.65780426 0.93452471
[9] 1.44189919 0.44143937 -0.21297901 -0.25711064
> plot(k1) #作点图
> k2 = rep(c("a","b","c","d"),each = 3);k2
[1] "a" "a" "a" "b" "b" "b" "c" "c" "c" "d" "d" "d"
> boxplot(k1~k2) #作箱线图。将k1作为y轴;k2作为x轴
plot() 默认作散点图,可以指定另外的作图形式(折线图,点线图等,详见帮助文档)
boxplot() 用连接指定需要作图的数学公式中的函数和自变量(可以是组合分组变量),如:boxplot(yg1:g2)。详见帮助文档
(二)矩阵(matrix)
- 矩阵是二维的。
- 只允许一种数据类型。
Tips: 判断数据结构
- 根据生成他的函数来判断
- 用函数class或is族函数来判断
I.新建矩阵和取子集
矩阵取子集,不支持$符号。
#新建矩阵
> m <- matrix(1:9, nrow = 3)
> m
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
#加列名
> colnames(m) <- c("a","b","c")
> m
a b c
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
#取第2行
> m[2,]
a b c #由于加了列名,所以取出的行,会带上对应的列名一起输出
2 5 8
#取第1列
> m[,1]
[1] 1 2 3
#取第2行第3列的数值,同样会带上对应的列名。
> m[2,3]
c
8
#取出指定的连续的行和列。
> m[2:3,1:2]
a b
[1,] 2 5
[2,] 3 6
II.矩阵的转置和转换
> m
a b c
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
#转置
> t(m) #t函数可以将矩阵或者数据框的行和列进行互换
[,1] [,2] [,3]
a 1 2 3
b 4 5 6
c 7 8 9
#转换
> as.data.frame(m) #将矩阵转换成数据框的数据结构
a b c
1 1 4 7
2 2 5 8
3 3 6 9
重点:
将数据框或举证转置之后,其数据结构都是矩阵。
> df1
gene CHANGE score p.value
r1 gene1 up 12 0.01
r2 gene2 up 23 0.02
r3 gene3 down 50 0.07
r4 gene4 down 2 0.05
> t(df1)
r1 r2 r3 r4
gene "gene1" "gene2" "gene3" "gene4"
CHANGE "up" "up" "down" "down"
score "12" "23" "50" " 2"
p.value "0.01" "0.02" "0.07" "0.05"
> class(t(df1))
[1] "matrix" "array"
由于矩阵要求所有数据类型都相同,因此,转置后的矩阵数据都是字符串类型。
若此时将矩阵转换成数据框数据结构,则其数据类型依然全部为字符串类型。
> m <- as.data.frame(m)
> m
r1 r2 r3 r4
gene gene1 gene2 gene3 gene4
CHANGE up up down down
score 12 23 50 2
p.value 0.01 0.02 0.07 0.05
> class(m)
[1] "data.frame"
> class(m$r3)
[1] "character"
若强行将某一列转换成数值类型,则非数值的单元格将由NA代替。
> m$r3 <- as.numeric(m$r3)
Warning message:
NAs introduced by coercion
> m
r1 r2 r3 r4
gene gene1 gene2 NA gene4
CHANGE up up NA down
score 12 23 50.00 2
p.value 0.01 0.02 0.07 0.05
- 给矩阵画热图
pheatmap::pheatmap(m)
- 关闭聚类功能,使热图颜色与矩阵数值一一对应:
> pheatmap::pheatmap(m, cluster_rows = F, cluster_cols = F)
(三)数据框(data.frame)
- 数据框是二维的。
- 每列只允许一种数据类型,各列间的数据类型可以不相同。
I.数据框的来源
- 用代码新建
- 由已有的数据转换或处理得到
- 读取表格文件
- R语言内置数据
什么是热图?
热图是用颜色的深浅来表示数值的大小。
II.数据框的生成与操作
- 用函数data.frame()生成
> #新建和读取数据框
> df1 <- data.frame(gene = paste0("gene",1:4), #每行生成一个向量,作为数据框的一列
+ change = rep(c("up","down"),each = 2), #每行代码用逗号分隔
+ score = c(5,3,-2,-4))
> df1
gene change score
1 gene1 up 5
2 gene2 up 3
3 gene3 down -2
4 gene4 down -4
- 从文件中读取
从CSV(逗号分隔符文件)文件中读取数据,生成数据框。函数read.csv()
> df2 <- read.csv("gene.csv") #文件gene.csv需放在当前的工作目录下
> df2
gene change score
1 gene1 up 5
2 gene2 up 3
3 gene3 down -2
4 gene4 down -4
- 数据框属性
> dim(df1) #dim函数查看数据框的行数和列数,dim表示维度的意思
[1] 4 3
> nrow(df1) #只查看行数
[1] 4
> ncol(df1) #只查看列数
[1] 3
#查看行名和列名
> rownames(df1) #提取行名
[1] "1" "2" "3" "4"
> colnames(df1) #提取列名
[1] "gene" "change" "score"
- 数据框取子集
- 用$指定列名或列号来取数据框的某列
> df1$gene #删掉score,按tab键试试
[1] "gene1" "gene2" "gene3" "gene4"
> mean(df1$score)
[1] 0.5
- 按坐标、行列名、行列条件取子集
> ## 按坐标
> df1[2,2]
[1] "up"
> df1[2,]
gene change score
2 gene2 up 3
> df1[,2]
[1] "up" "up" "down" "down"
> df1[c(1,3),1:2]
gene change
1 gene1 up
3 gene3 down
> #按名字
> df1[,"gene"]
[1] "gene1" "gene2" "gene3" "gene4"
> df1[,c('gene','change')] #用$取子集的列,只能取1列。用[]可以取多列。
gene change
1 gene1 up
2 gene2 up
3 gene3 down
4 gene4 down
> #按条件(逻辑值)——筛选score大于0的行
> df1[df1$score>0,] #表示行进行筛选,列都要
gene change score
1 gene1 up 5
2 gene2 up 3
#思路拆解
> df1$score
[1] 5 3 -2 -4
> df1$score>0
[1] TRUE TRUE FALSE FALSE
> df1$score[df1$score>0]
[1] 5 3
> #筛选score > 0的基因
> df1[df1$score > 0,1]
[1] "gene1" "gene2"
> df1$gene[df1$score > 0] #用于取子集的逻辑值向量与原集对应即可
[1] "gene1" "gene2"
#第一种方式还可以保留数据框的格式
> df1[df1$score > 0,1,drop=F]
gene
1 gene1
2 gene2
#将参数drop设置为FALSE,则只提取出对应的字段,并保留原来的数据结构,不转换成向量。
#第二种方式是不可以的,因为第二种方式首先提取出gene这一列(df1$gene)已经是向量了,再取向量子集,仍然是向量。
#取数据框最后一列(不知道具体列数)
> df1[,ncol(df1)] #函数ncol()求出数据框的总列数,最后一列即为第“总列数”列。
[1] 5 3 -2 -4
#取数据框除去最后一列的其他列
> df1[,-ncol(df1)] #减号表示除去该列意外其他列
gene change
1 gene1 up
2 gene2 up
3 gene3 down
4 gene4 down
中括号里的逗号,表示维度的分割。
重点与Tips:
- 数据框按照逻辑值取子集,TRUE对应的行/列留下,FALSE对应的行/列丢掉。
- 用于取子集的逻辑值向量,与原集对应即可,不必一定由原集生成。
- 数据框的修改
> #改一个格
> df1[3,3] <- 5
> df1
gene change score
1 gene1 up 5
2 gene2 up 3
3 gene3 down 5
4 gene4 down -4
> #改一整列
> df1$score <- c(12,23,50,2)
> df1
gene change score
1 gene1 up 12
2 gene2 up 23
3 gene3 down 50
4 gene4 down 2
> #增加一列
> df1$p.value <- c(0.01,0.02,0.07,0.05)
> df1
gene change score p.value
1 gene1 up 12 0.01
2 gene2 up 23 0.02
3 gene3 down 50 0.07
4 gene4 down 2 0.05
> #改行名和列名
> rownames(df1)
[1] "1" "2" "3" "4"
> colnames(df1)
[1] "gene" "change" "score" "p.value"
> rownames(df1) <- c("r1","r2","r3","r4")
> #只修改某一行/列的名
> colnames(df1)[2] <- "CHANGE"
> df1
gene CHANGE score p.value
r1 gene1 up 12 0.01
r2 gene2 up 23 0.02
r3 gene3 down 50 0.07
r4 gene4 down 2 0.05
Tips:
- 当取用的列名为原数据框存在的列名,则赋值为修改改列内容;当取用的列名不存在与原数据框,则赋值为新增一列。
- 两个数据框的连接
假设有三个数据框test1,test2,test3,如下:
> test1 <- data.frame(name = c('jimmy','nicker','Damon','Sophie'),
+ blood_type = c("A","B","O","AB"))
> test1
name blood_type
1 jimmy A
2 nicker B
3 Damon O
4 Sophie AB
> test2 <- data.frame(name = c('Damon','jimmy','nicker','tony'),
+ group = c("group1","group1","group2","group2"),
+ vision = c(4.2,4.3,4.9,4.5))
> test2
name group vision
1 Damon group1 4.2
2 jimmy group1 4.3
3 nicker group2 4.9
4 tony group2 4.5
>
> test3 <- data.frame(NAME = c('Damon','jimmy','nicker','tony'),
+ weight = c(140,145,110,138))
> test3
NAME weight
1 Damon 140
2 jimmy 145
3 nicker 110
4 tony 138
merge()函数将两个数据框按照列名称进行合并。指定的列名称取交集,其余列均包含在新数据框中。如下:
> merge(test1,test2,by="name")
name blood_type group vision
1 Damon O group1 4.2
2 jimmy A group1 4.3
3 nicker B group2 4.9
当列名称不同时,若仍旧需要按照这两列取交集合并,则可以具体指定两个列名称,如下:(注意指定的列名称顺序需与前面指定的数据框顺序对应)
> merge(test1,test3,by.x = "name",by.y = "NAME")
name blood_type weight
1 Damon O 140
2 jimmy A 145
3 nicker B 110
merge()函数的帮助文档:
描述:将两个数据框按照共同的列或行的名称进行合并。
格式:merge(x,y, by= intersect(names(x), names(y)),
by.x= by, by.y= by, all=FALSE, all.x=all, all.y=all, sort=TRUE)
参数:由上可知,默认是取两个数据框的共同相同名称的列或者行。或者进行单独指定。默认all=FALSE,表示只取共同列或行中相同值的内容进行合并,当指定all=TRUE时,取两个数据框中指定行列的并集进行合并,任一表中的缺失值,则用NA填充。
举例:
> merge(test1, test2, by='name', all=T)
name blood_type group vision
1 Damon O group1 4.2
2 jimmy A group1 4.3
3 nicker B group2 4.9
4 Sophie AB <NA> NA
5 tony <NA> group2 4.5
也可分别指定按照哪个数据框中的数据为标准进行取值(即指定数据框中的数全部取,另一数据框数据取与之的交集。) 相应的缺失值同样用NA填充,如:
> merge(test1, test2, by='name', all.x = T)
name blood_type group vision
1 Damon O group1 4.2
2 jimmy A group1 4.3
3 nicker B group2 4.9
4 Sophie AB <NA> NA
> merge(test1, test2, by='name', all.y = T)
name blood_type group vision
1 Damon O group1 4.2
2 jimmy A group1 4.3
3 nicker B group2 4.9
4 tony <NA> group2 4.5
(四)列表(list)
列表可以装各种数据结构和类型。
I. 新建列表
#列表
l <- list(m1 = matrix(1:9, nrow = 3),
m2 = matrix(2:9, nrow = 2))
> l
$m1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$m2
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 3 5 7 9
II.列表取子集
> l[[2]] #列表的取子集,用两个中括号,表示取出其中的第几个元素
[,1] [,2] [,3] [,4] #取出的是矩阵。
[1,] 2 4 6 8
[2,] 3 5 7 9
> l$m1 #也可以用$符号指定元素的名称来取子集
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
Tips:
列表取子集时,用两个中括号,取出来的是指定元素本来的数据结构。如上例中,取出的子集是矩阵。
若用1个中括号,取出来的子集数据结构仍然是列表,内容虽然一致。
某些时候,一些函数只能对矩阵、向量等数据结构进行处理,而不支持列表,这时候需要严格区分所取出的数据结构具体是哪一种。
> l
$m1
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
$m2
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 3 5 7 9
> class(l[[1]])
[1] "matrix" "array"
> class(l[1])
[1] "list"
> pheatmap::pheatmap(l[[1]]) #可以作图
> pheatmap::pheatmap(l[1]) #报错
Error in dist(mat, method = distance) :
'list' object cannot be coerced to type 'double'
重要练习题:
# 3.筛选test中,Species列的值为a或c的行
test[test$Species!="b",]
test[test$Species=="a"|test$Species=="c",]
test[test$Species %in% c("a","c"),]
第三个答案反复体会。
四、函数
function为编写函数的函数。
列出一个包里有哪些函数或数据
ls('package:stringr') #列出stringr包中有哪些函数