R语言_数据框排序与数据框连接

主要学习R语言的专题为以下几个内容:

  • 数据框排序
  • 表达矩阵画箱线图
  • 花里胡哨的连接

需要重点掌握:

R语言里的管道符号:%>%

str_detect()

Ifelse()

apply()

先安装R包:

options("repos" = c(CRAN="http://mirrors.tuna.tsinghua.edu.cn/CRAN/"))
if(!require(tidyr))install.packages("tidyr",update = F,ask = F)
if(!require(dplyr))install.packages("dplyr",update = F,ask = F)
if(!require(stringr))install.packages('stringr',update = F,ask = F)
if(!require(tibble))install.packages('tibble',update = F,ask = F)
library(tidyr)
library(dplyr)
library(stringr)
library(tibble)

tidyverse:Hadley Wickham-《R for Data Science》

https://r4ds.had.co.nz/

https://r4ds.had.co.nz/introduction.html

大佬研发了一套不需要写中括号,引号,$等符号,颠覆的R语言体系,让代码变得更简单,对初学者比较友好,但是要学习原始的基础包,tidyverse当做扩展学习,基础包里有几个函数,而tidyverse为一整套的包,包里有20多个小包,可以把这些小包分别安装,或只要安装几个核心包。

《R for Data Science》的大概介绍:

readr和data.table:数据导入

ggplot2:数据可视化。

有些包不基于ggplot2,如pheatmap包画的热图比ggplot2画得要好,给pheatmap包一个矩阵就可以,而不能给ggplot2一个矩阵,要数据框。

dplyr:专门用来处理数据框。

stringr:专门用来处理字符串。

Rmarkdown:有多余的时间可以去研究,可以做笔记,导出代码运行结果等。

专题1:数据框排序

order与sort复习:只对数据框的某一列(向量)操作

sort(iris$Sepal.Length)
iris$Sepal.Length[order(iris$Sepal.Length)]
##以上的两句代码运行的结果相同。Sepal.Length为iris的一列,也是一个向量。
#order(iris$Sepal.Length)是对Sepal.Length的下标进行排序

现在要进行整个数据框的排序,对某一列排序,它所对应的关系(其它列)也跟着动。数据框一列的下标,其实就是行号。

1.1 升序(默认)

##新建数据框:
test <- iris[c(1:2,51:52,101:102),]
rownames(test) =NULL
test

# order 可以给向量排序,也可以给数据框排序
sort(test$Sepal.Length)
test$Sepal.Length[order(test$Sepal.Length)]
##数据框一列的下标,其实就是行号,order(test$Sepal.Length)是下标打乱得到的东西,其实就是行号打乱得到的东西

##数据框升序
test[order(test$Sepal.Length),]
##test[行,列],在数据框行到的位置放行号,实现对整个数据框的排序,也就是把某一列的下标(行号)放在数据框行的位置,实现整个数据框的排序。order默认参数为升序
#整数据框按照第一列(Sepal.Length)大小来排序,对应的整行都动
##order()既可以对本列,又可以对其它的进行列排序,还可以给整个数据框使用

1.2 降序

test[order(test$Sepal.Length,decreasing = T),]
##decreasing = T,降序,

数据框整体升序和降序,对列操作,按行号排序,整体一起排,练习,不对第一列,对其它列操作试试,数据框[行,列],只操作数据框[order(...),]

1.3 tidyverse让代码更易读

arrange()排序
  • 数据框升序

arrange(test,Sepal.Length),注意不加引号。

arrange(数据框名,第一列),实现整个数据框的每一行按第一列从小到大排列起来

library(dplyr)
arrange(test, Sepal.Length)
#该函数唯一的写法,从大到小排列,没有decreasing=T
  • 数据框降序

使用函数:desc(),把要降序的列写在括号里,desc()函数不能单独用,它只能和dplyr里的一些函数结合使用

arrange(test, desc(Sepal.Length))

还有强大的功能:按照多列来排序

  • 双排序

先按照A列排,如果A列相同,按照B列排

arrange(test, desc(Sepal.Width),Sepal.Length)

##desc(Sepal.Width)是A列为降序,Sepal.Length是B列没有套上desc()是升序。谁在前面优先排序,Sepal.Width在前面优先排序,如果Sepal.Width没有重复值,Sepal.Length写和没写,没有区别。
##先按Sepal.Width先排,该列有两个重复的值3.2,再对重复值对应的Sepal.Length列的值进行排序,谁小谁在前

1.4 补充3个出自dplyr的函数

mutate():数据框新增列

select():筛选数据框的列

filter():筛选数据框的行

1.4.1 mutate:新增列
###使用mutate给数据框新增一列
mutate(test,new=Sepal.Width*Sepal.Length)
##新增的一列的名字为new,内容为Sepal.Width与Sepal.Length的乘积:*
##在R语言里,没有赋值,就没有变化,还是原来的test
test=mutate(test,new=Sepal.Width*Sepal.Length)

###原来给数据框test新加一列的用法:
test$新的列名<-c():
#基础包里的数据框新增列,
test$new=test$Sepal.Width*Sepal.Length

##还是tidyverse的方法好用:tidyverse里的mutate函数会减少$符号的使用
1.4.2 select(),filter()筛选数据框列,行

select()是筛选数据框的列:select(数据框名,列名),注意不用$,引号之类的

library(dplyr)
select(iris,Species)
#筛选出数据框的Species,只显示一列,只对某一列或是几列操作。

filter()是筛选数据框的行:filter(数据框名,逻辑值),x==y,x!=y,x%in%y,x>y等

library(dplyr)
filter(iris,Sepal.Length>6)
##筛选出Sepal.Length大于6,把其它对应关系也显示出来,是对数据框操作。

用中括号[行,列]可以筛选数据框的行与列。

优秀的管道符号%>%

把前一句的输出作为后一句的输入。

##select(),filter()筛选数据框列,行
x1=filter(iris,Sepal.Width>3)
##filter()筛选行,筛选第二列数字大于3的行,把行提取出来还是一个表格。
x2=select(x1,c("Sepal.Width","Sepal.Length"))
##在x1的结果上筛选列,筛选第一列和第二列
x3=arrange(x2,Sepal.Length)
##排序
##以上3句代码完成的作用,从iris出发,筛选行,筛选列,排序之后得到一个新数据,并赋值给x3.
##从iris得到x3,那么x1,x2是中间产物,并不想用。

##优秀的管道符号是用来克服以上出现的x1,x2等多余的东西,让代码变得丝滑些。
##使用管道符%>%的前提是加载tidyverse里的任何一个R包,管道符号会被调出来。
x=iris %>%
filter(Sepal.Width>3)%>%
select(c("Sepal.Width","Sepal.Length"))%>%
arrange(Sepal.Length)
##从iris出发,经历筛选行,筛选列,排序得到一个新数据并且赋了值x。

##使用管道符号,没有生成中间变量,管道符号可以理解为向后传递。

##对比分析:
##filter(iris,Sepal.Width>3)与iris %>% filter(Sepal.Width>3)的意思一样
##x2=select(x1,c("Sepal.Width","Sepal.Length")) 与iris %>% filter(Sepal.Width>3)%>%select(c("Sepal.Width","Sepal.Length"))的意思一样

专题2:表达矩阵画箱线图

这里的箱线图,是指用ggplot画出来的。

一个矩阵是不可以作为ggplot画图的输入数据。

ggplot画图潜在的规律,输入数据是数据框不能是矩阵,aes(x=数值,y=数值)。

需要进行数据整理,与iris示例数据一样,怎么处理数据:

2.1 转置t

表达矩阵不能直接画图,首先进行调整,如下面的表达矩阵需要整理成数据框,gene在一列,所有的count在一列上,分组在一列上。

###新建表达矩阵
set.seed(10086)
##set.seed是保证运行生成的随机数据一样。set.seed是设置生成随机数一样
exp = matrix(rnorm(18),ncol = 6)
exp = round(exp,2)
##round函数是取小数点后几位小数,这里保持两位小数
rownames(exp) = paste0("gene",1:3)
##加行名
colnames(exp) = paste0("test",1:6)
##加列名
##画ggplot图的时候,横坐标是基因,纵坐标是count具体的数字。
exp[,1:3] = exp[,1:3]+1
##+1所有的数值加1
##前3列+1,为了让两组数据有差别,前3列为一个组,后三列为一个组,看看分组的差异,所以前3列加1
exp

转置之后,行变列,列变行,之后转换为数据框。

library(tidyr)
library(tibble)
library(dplyr)
dat = t(exp) %>% ###转置后的exp此时还是矩阵,作图都用数据框
  as.data.frame() %>% ##把行名变为数据框的一列
  rownames_to_column() %>% ##把原来的行名转换成列名
  mutate(group = rep(c("control","treat"),each = 3))##mutate是新增一列,group 为分组,给数据框新增一列。

ggplot2语法不认行名,所以把test1..test6变为一列。

把原来的行名变成第一列

一个样本在多个基因的表达量,但是不能作图

2.2 宽变长

要把gene1..gene3变为一列,把具体的数值作为一列,test1..test6各自重复了3次。(6行3列,变成18行3列)。好处是,有横纵坐标,可传递给ggplot2,进行作图了。

pdat = dat%>% 
  pivot_longer(cols = starts_with("gene"),###宽变长的函数pivot_longer()三个参数,cols=合并的列
               names_to = "gene",
               values_to = "count")##新生的数据框新生的两个列名 
## pivot_longer()为宽变长的函数,比mute()函数好用。
##宽变长需要三个参数:cols=要把那几列宽变长,就是说哪几列的列名成为新的一列,内容成为新的一列; names_to = 那一列的名字叫什么,叫gene。values_to =那些数字组成的一列且名字叫什么,为count。总结,把几列变为一列且起名字,把那几列对应的数字组成一列且取名字。

##作为初学者,不需要知道rownames_to_column()和 pivot_longer()出自哪个包。

宽边长的理解:原来是3列,现在变成1列。长变宽(同样可以实现),但是很少用。

2.3 画图

library(ggplot2)
p = ggplot(pdat,aes(gene,count))+
  geom_boxplot(aes(fill = group))+
  geom_jitter()+
  theme_bw()
##画图,x=gene,y=count,把x=和y=都省略,fill = group,映射,theme_bw()去除背景。

2.4 图分面

p
p + facet_wrap(~gene,scales = "free")###
##facet_wrap分面函数,把gene1,gene2,gene3各自分到一张图里。

专题3:花里花哨的连接

inner_join():交集 left_join:左连接 right_join:右连接 full_join:全连接 semi_join:半连接 anti_join:反连接

test1 <- data.frame(name = c('jimmy','nicker','Damon','Sophie'), 
                    blood_type = c("A","B","O","AB"))
test1
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

library(dplyr)
##连接函数需要加载的dplyr包。

3.1 inner_join:交集

合并在一起,共同的留下,不共同的都去掉。

library(dplyr)
inner_join(test1,test2,by="name")

去掉Sophie 和 tony

注意:

以下各种连接中,代码里两个test的前后顺序,写在前的为左边,写在后面的为右边:

3.2 left_join:左连接

以左边的表test1为准,连接完之后,保留左边表的所有信息,右边表的行数和左边表的行数一样多,tony在左边表没有就直接被踢掉,Sophie在左边表有,但是在右边表没有对应的信息,存在却未知,以NA值填充。

library(dplyr)
left_join(test1,test2,by="name")

3.3 right_join:右连接

以右边的表为标准,右边有的人都留下,左边表没有的就去掉,在左边的表没有值,以NA值填充。

library(dplyr)
right_join(test1,test2,by="name")

##其实与left_join(test2,test1,by="name")一样,左右连接这两个函数用一个就可以,只是把两个表的顺序调一下,以后根据自己的分析来定顺序

左右连接这两个函数用一个就可以,只是把两个表的顺序调一下,以后根据自己的分析来定表格顺序。

3.4 full_join:全连接

取全集,但凡两个表有的信息都保留下来,没有的信息,填上NA

library(dplyr)
full_join(test1,test2,by="name")

取交集和全集的比较,取交集没有的就掉,不会有NA,取全集时,都留下,没有对应信息的用NA填充。交集没有NA,全集有NA。


以下semi_join和anti_join基本用不上:

3.5 semi_join:半连接

应用全景不广泛。虽然叫连接,其实并没有连接。意思是,把左边的表取子集,取在右边表里存在的子集,有的人才被留下,没有的去掉,其实就是%in%。

library(dplyr)
semi_join(test1,test2,by="name")

3.6 anti_join:反连接

意思是,把左边的表取子集,取在右边表里没有的子集,没有的人才被留下,有的去掉。

library(dplyr)
anti_join(test1,test2,by="name")

以上的几个连接函数相当于一个merge函数,merge函数实现交集连接,全连接等靠参数来实现的,找参数时比较麻烦。

说明

以上内容是听生信技能树小洁老师的R语言线上课,根据自己的理解记录下来,小洁老师授课非常细心,对不同水平的同学都照顾到,并且补充很多技巧,如数据框多种排序方法,还有一些注意事项,如ggplot输入数据是数据框,如果是矩阵如何处理等。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342

推荐阅读更多精彩内容