一文学会使用dplyr包进行数据转换
大家好,我是阿琛。可视化是展示结果的重要途径与手段。在之前的内容中,从认识ggplot2开始,我们相继介绍了箱型图,桑基图,棒棒糖图,以及雷达图等等。然而,不同的作图方法对输出数据的格式要求也不尽相同。在训练营以及平时的交流中,我发现即使将整个绘图的代码摆在眼前,很多小伙伴仍然感到无从下手,不知道如何将数据整理到合适格式。
当我们拿到一份数据,无论是TCGA下载的转录组数据,GEO数据库中的芯片表达数据,亦或者是自己测序等途径得到的数据内容,其数据格式正好完全符合我们需求的情况,是非常罕见的。一般来讲,我们需要对数据进行预处理,比如提取其中的某些变量值,变量的重命名,创建一些新的统计变量等等,从而使得数据格式达到输入要求,变得更容易处理。
关于这些内容,Hadley Wickham大神已经体我们充分进行了考虑,并由此创造了一个新的数据处理方式,即tidyverse中的一个核心R包---dplyr包。在介绍中,Hadley提到,dplyr是一种新的数据处理的语法,提供了一组一致的动词来帮助您解决最常见的数据处理难题,它们分别是:
按值筛选变量(filter())
对行进行重新排序(arrange())
按名称选取变量(select())
使用现有变量的函数创建新变量(mutate())
将多个值总结为一个摘要统计量(summarize())
接下来,我们一起来看一下这几个函数的使用方法。
1.R包的安装与读取以及数据的读取
1.1 R包准备
首先加载tidyverse包,讲解中的dplyr包属于tidyverse包。
if(!require(tidyverse))install.packages("tidyverse")library(tidyverse)
在加载tidyverse包时,在输出信息中我们可以看到存在一些冲突信息,它会告诉你在dplyr包中有两个函数与基础R包的函数存在冲突。当我们要在加载了tidyverse包后,想使用基础R包的这两个函数时,需要提供其完整的名称分别是stats::filter()和stats::lag()两个。
1.2 数据准备
dat <-read.table("exp.txt", header=T,sep="\t", check.names=F,row.names = 1)dat[1:4,1:4] #查看数据类型
随后,将数据读取进来。在分析前,提取其前4行4列,我们先看一下这个数据的结构与内容,当然,也可以直接在RStudio中通过View(dat)来查看整个数据框。可以发现,在该数据集中,共包含80行,132列内容,其中行名为患者的编号,第一列为患者的生存状态(fustat),第二列为患者的分期(Stage),其后为130个不同的基因。
2.使用filter()筛选行
首先,我们来筛选一下fustat为1,Stage为2的所有患者:
dat2 <-filter(dat, fustat == 1,Stage == 2)
运行以后,dplyr包会执行相应的筛选操作,并返回一个新的数据框。但是,需要注意的是,dplyr包中的函数从来不会修改原数据框内容。因此,如果想要保存运行结果,需要将其赋值给一个新的变量。可以发现,经过筛选,最终得到7个样本所组成的新数据集dat2。
补充内容:比较运算符与逻辑运算符
在筛选的过程中,我们需要熟悉如何运用比较运算或者逻辑运算过程,来快速且准确的筛选变量信息。
2.1 比较运算符
在R语言中,其提供了一整套用于比较运算的符号,分别是:>,>=,<,<=,!=,以及==六种。
#筛选stage为3和4的样本(即Stage >= 3) dat3 <- filter(dat, Stage >= 3) #筛选fustat为1的患者(即fustat == 1或者fustat != 0) dat4 <- filter(dat, fustat == 1) dat4 <- filter(dat, fustat != 0) #得到的结果与上一句一致 #筛选LSR基因表达量小于4的样本(即LSR < 4) dat5 <- filter(dat, LSR < 4)
大部分的比较方法与我们常规在数学或日常学习中的使用是一致的;
但是,需要注意的是:
在此判断是否相等使用的是==,而不是=(在R中,=表示赋值的含义);
关于“浮点数”的问题
sqrt(2)^2 == 2#[1] FALSE 1/49 * 49 == 1#[1] FALSE
是不是觉得十分神奇呢?这是因为计算机使用的是有限精度运算,每一步运算后其保存的均是一个近似值。因此,在比较这类运算结果时,我们不能使用==,而应该借助near()函数的帮助:
#near() near(sqrt(2)^2, 2) #[1] TRUE near(1/49 * 49, 1) #[1] TRUE
2.2 逻辑运算符
关于逻辑运算符,大家想必不会陌生吧。常用的布尔逻辑运算符包括:&(与),|(或),以及!(非)三种。
#筛选stage为3和4的样本(即Stage == 3 | Stage == 4) dat6<- filter(dat, Stage == 3 | Stage == 4) #筛选fustat为0,且stage为3的样本(fustat != 1 & Stage == 3) dat7<- filter(dat, fustat != 1 & Stage == 3)
此外,还有一种十分有用的简写形式,即x %in% y(表示选取x是y中的一个值时的所有行)。这样,上面的代码就可以简化为以下的形式:
#%in%的使用 dat8 <- filter(dat, Stage %in% c(3,4)) #筛选stage为3和4的样本 identical(dat6, dat8) #比较两个数据集是否相同 #[1] TRUE
可以发现,使用|得到的dat6与使用%in%得到的dat8之间是完全相同的两个数据集。
3.使用arrange()排列行
arrange()函数的使用方法与filter()函数比较相似,但是arange()函数的作用是改变行的顺序。
3.1 将Stage按降序进行排列
arrange(dat, desc(Stage))
3.2 将数据框以fustat,Stage,以及XYLT2基因的表达量来进行排列
arrange(dat, fustat, Stage, XYLT2)
可以发现,当列名不止一个时,它会自动使用后面的列在前面排序的基础上继续排列,即当fustat相同时,根据Stage进行进一步的排列,依次往下。
4.使用select()选择列
4.1 按名称选择列
select(dat, fustat, Stage)
4.2 选择在第一列fustat和第三列XYLT2之间的所有列
select(dat, fustat:XYLT2)
4.3 选择不在第一列fustat和第三列XYLT2之间的所有列
select(dat, -(fustat:XYLT2))
4.4 select()与everything()联用
当我们想要将几个变量移动到数据框开头时,则需要同时借助select()与everything()的作用。
select(dat, XYLT2, LSR, everything())
运行后,我们可以发现,第三列XYLT2和第四列LSR被移动到了整个数据框的前两列。
此外,还可以在select()函数中使用一些辅助函数,比如:
starts_with("abc"):匹配以“abc”开头的名称
ends_with("xyz"):匹配以“xyz”结尾的名称
contains("ijk"):匹配包含“abc”的名称
matches("(.)\1"):选择匹配正则表达式的变量
num_range("x", 1:3):匹配x1,x2和x3
好啦,本次的内容先介绍到这里,剩下的两个函数mutate()和summarize(),以及管道符号%>%的使用,我们将在下一期的内容中进行详细的介绍~以简单易懂的介绍,带领大家快速入门数据处理,我们下期再见~~
欢迎大家关注解螺旋生信频道-挑圈联靠公号~
继续阅读
阅读原文