zl程序教程

您现在的位置是:首页 >  其他

当前栏目

【生信技能树培训笔记】R语言基础(20230112更新)

基础笔记语言 更新 技能 培训 生信
2023-06-13 09:16:30 时间

本培训使用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种数据结构,如下:

image.png

- 数据框约等于“表格”。数据框要求每一列只能有一种数据类型,且数据框只是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:向量只允许一种数据类型存在,当出现不同类型的数据时,会自动根据下图的优先顺序进行转换。

image-20230105111325248.png

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的区别见前文“本节函数”

循环补齐

当两个向量长度不一致时,会通过循环补齐的方式对照较长的那个向量补齐运算。

image-20230105114908340.png

利用循环补齐简化代码:

> 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%的区别
image-20230105120847978.png

当两个向量长度不等时,==会发生循环补齐;而%in%不适用。 ==是元素对应位置的比较,有顺序的影响,%in%前后两个向量中所有元素都会互相比较,没有顺序的影响。下图中的问题,则应该使用%in%而不能使用==。(即xx %in% y)

image-20230105125120918.png
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轴
image-20230105130334435.png
image-20230105130345181.png

plot() 默认作散点图,可以指定另外的作图形式(折线图,点线图等,详见帮助文档) boxplot() 用~连接指定需要作图的数学公式中的函数和自变量(可以是组合分组变量),如:boxplot(y~g1: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.数据框的来源

  1. 用代码新建
  2. 由已有的数据转换或处理得到
  3. 读取表格文件
  4. R语言内置数据
什么是热图?

热图是用颜色的深浅来表示数值的大小。

II.数据框的生成与操作

  1. 用函数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
  1. 从文件中读取

从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
  1. 数据框属性
> 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" 
  1. 数据框取子集
  • 用$指定列名或列号来取数据框的某列
> 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对应的行/列丢掉。 用于取子集的逻辑值向量,与原集对应即可,不必一定由原集生成。

  1. 数据框的修改
> #改一个格
> 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:

  1. 当取用的列名为原数据框存在的列名,则赋值为修改改列内容;当取用的列名不存在与原数据框,则赋值为新增一列。
  2. 两个数据框的连接

假设有三个数据框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包中有哪些函数