我们前面讲完了数据读取、数据提取、数据读取、数据概述。这部分我们来讲讲跟剩下一些跟生统相关的函数与操作。不过我这里讲的还是数据排序。
因为这部分我觉得掌握 order 函数就可以了,其他的 for、apply、function 我认为其实没啥必要掌握。因为生统数据一般都是才几行几列的数据,完全可以通过复制粘贴来完成这些操作。而这几个操作学习成本略大。反正生统考试也是代码抄到纸上。所以其他的函数我视情况再往上加。
排序函数
R 语言里面的排序相关的函数有三个,分别是 order、rank、sort。我们来看下这三个函数的使用。
# 产生一个测试向量
> set.seed(19960521)
> test <- sample(10, 5)
> test
[1] 9 5 2 6 4
# order
> order(test)
[1] 3 5 2 4 1
# rank
> rank(test)
[1] 5 3 1 4 2
# sort
> sort(test)
[1] 2 4 5 6 9
大家看到结果可能会比较懵逼,让我们来一个个来看。
order
order 实际上返回的是最小值,次小值,再次小值……次大值,最大值在原始数据中的位置。比如我们原始的数字是9,5,2,6,4。其中最小值是 2,那么 2 在原始数据中排在第 3 个位置。然后就可以 order 在结果中输出的第一个值就是 3,即代表原始数据中,最小值(2)在原始数据中的位置。次小值是4,在原始数据中排在第 5 个位置,那么order 函数输出的第二个值就是 5。
order 默认地排序是升序,即返回的是最小值,次小值,再次小值……次大值,最大值在原始数据中的位置。如果你在向量的前面加一个减号,那么就会变成降序,即返回的是最大值,次大值……次小值,最小值在原始数据中的位置。
> order(-test)
[1] 1 4 2 5 3
大家看到在原始位置中的位置这个信息有没有感觉很有帮助。事实上,我们可以利用 order 返回给我们的信息来对数据进行排序。
> test[order(test)]
[1] 2 4 5 6 9
> test[order(-test)]
[1] 9 6 5 4 2
order还可以对数据框、矩阵进行排序,还是拿我们之前病人的那个数据。不过我把 patientID 稍微更改一下。
> patientID <- c(2, 2, 3, 1)
> age <- c(25, 34, 28, 52)
> diabetes <- c("Type1", "Type2", "Type1", "Type1")
> status <- c("Poor", "Improved", "Excellent", "Poor")
> patientdata <- data.frame(patientID, age, diabetes, status)
> patientdata
patientID age diabetes status
1 2 25 Type1 Poor
2 2 34 Type2 Improved
3 3 28 Type1 Excellent
4 1 52 Type1 Poor
我们可以根据病人的年龄进行排序。
# 一步步来,先得到坐标索引
> order(patientdata$age)
[1] 1 3 2 4
# 再把坐标索引输进去
> patientdata[order(patientdata$age),]
patientID age diabetes status
1 2 25 Type1 Poor
3 3 28 Type1 Excellent
2 2 34 Type2 Improved
4 1 52 Type1 Poor
我们还可以让数据框先根据病人的ID进行排序(升序)。排完序之后,然后再根据年龄进行排序(降序)。
# 获取坐标索引
> order(patientdata$patientID,-patientdata$age)
[1] 4 2 1 3
# 再把坐标输进去
> patientdata[order(patientdata$patientID,-patientdata$age),]
patientID age diabetes status
4 1 52 Type1 Poor
2 2 34 Type2 Improved
1 2 25 Type1 Poor
3 3 28 Type1 Excellent
我们可以看到,我们的病人数据框里面。ID是按升序进行排列的,然后再排age。可以看到ID 那边有 2 个数是相同的,即 2,2。单根据第一列排序是分不出先后的,那么我们就再根据 age 的顺序进行排列。
这种先根据什么,后根据什么排列对于处理生信相关的数据还是比较有用的。比如 peak 文件经常就是Chr,start,end,peakID这几列,我们就可以根据order来排列我们的Peak文件。但对于生统来说,可能只要掌握单列排序就行了。
之前有一题让我们提取出 p-value 最显著的前 10 个数据。我们就可以用 order 来做了。
# 有一大堆 p-value 值。
> head(test4_sig_result,20)
gene12 gene37 gene49 gene62 gene95 gene101 gene104 gene129
0.0362923840 0.0121764651 0.0418676419 0.0329430116 0.0298363658 0.0105665102 0.0166156137 0.0017854211
gene131 gene135 gene152 gene177 gene178 gene186 gene217 gene239
0.0395431910 0.0439433653 0.0474609370 0.0340475106 0.0109452086 0.0170048804 0.0140824498 0.0087974170
gene250 gene277 gene279 gene282
0.0133802343 0.0007355859 0.0337127909 0.0280345683
……茫茫多p-value
# 提取出前10个
## 先对这一大堆 p-value 进行排序
test4_sig_result[order(test4_sig_result)]
## 得到了有顺序的 p-value之后,利用 [] 提取
> test4_sig_result[order(test4_sig_result)][1:10]
gene28801 gene27868 gene27438 gene21642 gene24019 gene12323 gene12962 gene28939
4.277344e-06 6.093302e-05 8.229606e-05 9.889894e-05 1.124717e-04 1.261658e-04 1.298200e-04 1.462493e-04
gene2387 gene18712
1.522920e-04 1.601297e-04
rank
> test
[1] 9 5 2 6 4
> rank(test)
[1] 5 3 1 4 2
rank 实际上返回的是你原始数据中的每个值,在原始数据中的顺序(排名)。
打个比方,有 10 个人站成一排军训。order 函数会告诉教官,最矮的人站在哪里,次矮的人站在哪里,最高的人站在哪里。然后教官就可以根据 order 返回的信息,大声地说 XX号,站出来,排在第一位,XX号站出来,排在第二位。这样,教官一个个吼,最后这10个人就能从矮到高排好了。
而 rank 函数则是,有 10 个人站成一排军训,rank 函数则是会像一个检测器一样。每次经过一个人,就告诉教官,这个人在整个队列中,是排几矮的。就好比,检测器扫过第一个人,就会大声说出,这个人在这10个人中,是排在第2矮的。
比如我们这里数据,原始数据的顺序是9,5,2,6,4。9 在这 5 个数据中是最大的,就是第 5 小的。那么 rank 就会告诉我们 9,在原始数据中是排在第5位的。
sort
> test
[1] 9 5 2 6 4
> sort(test)
[1] 2 4 5 6 9
sort 就相当于帮教官自动地排好了队列。
事实上,由于 order 不仅可以应用于向量,还可以应用于数据框,矩阵等等。所以应用场景也更多,我们生统也应该就用到它了。
for,function,apply
视情况而定。
网友评论