在语言编程的过程当中,选取数据的子集是一个常规操作,通常的情况下我们会使用到索引,来帮助我们灵活地选取自己,或者是使用subset函数。但无可避免的是这些方法,通常情况下都会给我们造成一定的困扰。因为在不同的数据结构中,索引的使用方法,往往是不同的,并且subset函数有的时候并不那么的简洁和灵活。这里就R语言中的subset函数和索引进行一定的深入展开。
常规索引取子集操作
这一部分将会稍微顺带的提一下常规的索引取子集操作。由于内容比较基础,所以基本上就举几个简单的例子一笔带过。
使用iris数据集和数据框数据类型为例
上述着四种结果无疑是不同的,其中涉及到两个方面,一个方面是维度,另外一个方面是操作符号: “[“、”[[“、“$”。
“[”操作符
向量是一维的,但是数据框、矩阵的维度更高,所以当你直接使用“[”操作符号的时候需要考虑到这个问题。
拿数据框为例,数据框下表分为[row,colum],如果你直接输入[x],则会返回一个第x列的数据框,如果你输入[x,]则返回第x行的值,[,x]同理。如果想要体会其中的不同,不妨使用str来查看一下。
“:”、”c()”、“-”以及字符串形式
介于上面有个实时操作的嵌入iframe,简易可以直接拿来直接练手。此处直接以行为例。
1 | iris[1:5,] #输出1到5行,“:”的含义基本等同于from left to right |
“[[“操作符和“$”操作符
“[[“操作符和“$”操作符直接提取相应下标、字符串的值。
1 | iris[[1]] #提取第1列的值 |
下面给出《Advanced R》里面的插图帮助理解。
Wickham, H. (2020). 4 Subsetting | Advanced R. Retrieved 21 April 2020, from https://adv-r.hadley.nz/subsetting.html#subset-single
另外,这是本神书,在怎么推崇也不为过,但是建立在你有基础的情况下。刷过几次《R语言实战》还是觉得自己的代码写的稀烂。还自行总结了很多技巧。但人家早给你系统化的整理好了,真的是茅塞顿开。
排序操作
排序
在R语言中的排序操作主要包含三类,即order、rank、和sort,在提取子集的时候往往需要用到这些排序,但很多初学者无法有一个明确的区分。这里梳理下。
我们以一个名称为ppd的向量为例(调戏pdd大佬😈)。
1 | pdd <- setNames(c(11,43,5,20),letters[1:4]) |
order
下面看一下order的结果:
1 | pdd |

看不懂。。。没关系,让我们来画个示意图:
示意图已经挂了,自行领会吧
注:上述示意图为博主自行手绘,随意引用但不要去水印。也不要介意小黄人都叫什么…
实时上order就是干了这么一件事情,它告诉你排序完之后目前对应位置的元素现在在哪里。
这样就很清晰了。
那么pdd(order(pdd))这个指令事实上做的操作就是按照排序完以后的顺序输出结果。
rank
rank相对于order来说就简单很多了,rank输出的事实上就是当前位置上的值在总体排序的位次。
1 | rank(pdd) |
sort
sort(pdd) == pdd[order(pdd)]
1 | identical(sort(pdd),pdd[order(pdd)]) |
order在多维数据中使用更加灵活,所以理解以后应用还是很方便的。
排序在取子集中的应用
例如我就想看看iris数据集中Sepal.Length排名前20的,那么可以这么做:
1 | iris[order(iris$Sepal.Length)[1:20],] |
这里可能会有小伙伴作出这样鬼畜的事情:
1 | iris[order(Sepal.Length)[1:20],] |
如果你了解R的enviroment策略,那么就不会出现这样的问题,Sepal.Length是对象iris中的列名,并不包含在environment里,所以会提示上述错误。但是如果你改不了这个习惯,那么也有办法。
1 | attach(iris) |
attach函数事实上达到的效果就是将iris的列名模拟做对象名称。
我个人觉得这不失为一个好方法,但是更喜欢直接使用$进行补全,两种方法我都用,但是分场景。
当你指处理少量数据的时候,可以用attach,无疑使得代码很简洁。
但是当你导入大量数据,且不同表格数据中有大量相同的列名或标签名时不建议这么做。还是老老实实以object$colname的形式比较好,自己容易记清楚。
当你学会排序以后,对于子集的截取会相对高效很多。
结语
本来想要毕其功于一役的,但是这部分内容其实能深入的还是很多的。所以分成2到3部分进行讲述。下面是一些注意事项。
注意:
- R语言是为了数据科学家进创造的“编程”语言,所以,它的第1位并不是像常规编程语言从0开始,而是从1开始。
- 习惯py的小伙伴千万不要把取后20位写成iris[,-20:-1]…,R里面不是这么玩的。