下面是学习order函数的记录
(生信技能树学员luka)
写下这篇笔记的初衷是有小伙伴在群里提出问题,我在寻找答案过程中参与了学习群内的互动,借此机会写下个人浅薄的理解,希望帮助您更好理解order( )函数逻辑,如有错误,请指正!
最初问题来源:如何理解order(x,y)的结果 ?
看到这个问题的时候,我是不知所云的,因为课堂上只讲过order(x),没有出现order(x,y),不理解其运算逻辑,就不能理解函数的结果。因此我整合了order( )函数从基础到上述问题解决的学习过程,仅供参考!
一、order( )函数的介绍
排序在R语言处理数据的重要过程,有多种内置的基本函数进行排序。
- order( ) 函数:将元素按数值、字母顺序、逻辑值等从小到大排序后,返回元素的原始次序(位置);
- sort( ) 函数:将元素按数值、字母顺序、逻辑值等从小到大排序后,返回已排序的元素;
- rank( ) 函数:返回元素在向量中的秩(排名);
> x1 <- c(3, 1, 4, 15, 92)
> order(x1) #排序后返回原始次序(位置)
[1] 2 1 3 4 5
> sort(x1) #返回已排序的元素
[1] 1 3 4 15 92
> rank(x1) #返回元素在向量中的秩(排名)
[1] 2 1 3 4 5
order( )的参数和默认值
代码语言:javascript复制order(..., na.last = TRUE, decreasing = FALSE,
method = c("auto", "shell", "radix"))
# na.last 是否将缺失值放在最后,TRUE放在最后,FALSE放在最前
# decreasing 是否按降序进行排列,TRUE为降序排列,FALSE为升序排列
二、order( )函数应用于单个向量
代码语言:javascript复制# 构建几个向量
> x <- c(1,1,3:1,1:4,3);x
[1] 1 1 3 2 1 1 2 3 4 3
> y <- c(9,9:1);y
[1] 9 9 8 7 6 5 4 3 2 1
# order()对各向量进行排序,返回排序后的原始次序
> order(x) #当遇到相等值时,按原始顺序排列
[1] 1 2 5 6 4 7 3 8 10 9
> order(y)
[1] 10 9 8 7 6 5 4 3 1 2
# order()函数默认为升序排序,通过decreasing = TRUE 改为降序排序
> order(x,decreasing = T)
[1] 9 3 8 10 4 7 1 2 5 6
# 也可以通过在向量前加上"-",进行反向排序
> order(-x)
[1] 9 3 8 10 4 7 1 2 5 6
三、order( )应用于多个向量
当order( )中包含两个向量时
代码语言:javascript复制# order()对2个向量进行排序
> order(x,y)
[1] 6 5 1 2 7 4 10 8 3 9
似乎突然不知所云,我们将x,y组成数据框,尝试解读一下
代码语言:javascript复制> xy <- data.frame(x=x,y=y) #行名相当于原始次序
> xy[order(xy$x),] #只看x这一列这里相当于order(x)的结果,行名为原始次序
> xy[order(xy$x,xy$y),]
一开始,我心里是有疑惑的:
x和y是单独向量,他们之间没有关联,为什么order(x,y)跟组成数据框之后分析结果是一样的?是否因为我们利用order函数把x, y放在一起,导致函数默认他们之间是对应的关系?
为了验证这一点,我们可以把order( )处理过后,x和y对应的值输出来对比图中的数据。
代码语言:javascript复制> order(x)
[1] 1 2 5 6 4 7 3 8 10 9
> x[order(x)] #与上图 xy[order(xy$x),] 的x列一致
[1] 1 1 1 1 2 2 3 3 3 4
> order(x,y)
[1] 6 5 1 2 7 4 10 8 3 9
> x[order(x,y)] #与上图 xy[order(xy$x,xy$y),] 的x列一致
[1] 1 1 1 1 2 2 3 3 3 4
> y[order(x,y)] #与上图 xy[order(xy$x,xy$y),] 的y列一致
[1] 5 6 9 9 4 7 1 3 8 2
结果发现确实一致,但是我忽略了一个问题。
小洁老师:事实上,单独的向量和数据框里单独取出来了一列,没有任何区别。他们的对应关系是只能自己把握,无法指定也不必指定的。
xy$x 与 x 本质上都只是一个向量,其对应关系只有使用函数者自己理解和把握。当两个向量长度相等时,只要符合函数运算规律,放在order( )中(也许其他函数也类似)就可以形成运算,并不需要特意指定也无法指定。当然,这并不妨碍我们使用函数。需要注意的是,如果两个向量长度不等,是无法进行运算的。
代码语言:javascript复制> x <- 1:3
> y <- 5:1
> order(x,y)
Error in order(x, y) : argument lengths differ
如果你还没有理解上述函数运算逻辑,我们换一个更贴近生活的例子。
生信学习班里的几位同学最近进行了R语言和Linux的测试,现在我们要根据他们的成绩进行排序。排序要求如下,首先按R语言成绩排名,如果R语言成绩一致,则再按Linux成绩排名。
- 构建成绩表
> name <- c('James','John','Luka','Green','Lisa','Curry','Jimmy','Xiaojie')
> R_scores <- c(88,68,76,76,93,76,98,98)
> Linux_scores <- c(78,63,76,82,81,63,92,95)
> scores <- data.frame(name=name,R_scores=R_scores,Linux_scores=Linux_scores)
> print(scores)
name R_scores Linux_scores
1 James 88 78
2 John 68 63
3 Luka 76 76
4 Green 76 82
5 Lisa 93 81
6 Curry 76 63
7 Jimmy 98 92
8 Xiaojie 98 95
- 按R语言成绩(R_scores)进行排序,此时行名相当于order(x)
rank_R <- scores[order(scores$R_scores),]
print(rank_R)
name R_scores Linux_scores
2 John 68 63
3 Luka 76 76
4 Green 76 82
6 Curry 76 63
1 James 88 78
5 Lisa 93 81
7 Jimmy 98 92
8 Xiaojie 98 95
- 在R语言成绩排名的基础上,进行Linux(Linux_scores)成绩排名
> rank_R_Linux <- scores[order(scores$R_scores,scores$Linux_scores),]
> print(rank_R_Linux)
name R_scores Linux_scores
2 John 68 63
6 Curry 76 63
3 Luka 76 76
4 Green 76 82
1 James 88 78
5 Lisa 93 81
7 Jimmy 98 92
8 Xiaojie 98 95
四、最初的问题如何解决
我们回到最初问题来源:如何理解order(x,y)的结果 ?
答案已经显而易见:
首先x和y要有一对一的对应关系,这句代码才有意义!否则虽然代码不报错,逻辑也是错的。order(x,y) 的运算过程分为两个部分:
- 先按照x从小到大排序
- x有相同数值时,按照y从小到大排列;如果x里没有相同数值,y就用不上啦。
最后输出x对应的原始次序(位置)
同理,我们可以尝试理解 order(y,x) 的运算逻辑。