R语言:从数据思维到数据实战
上QQ阅读APP看书,第一时间看更新

2.1.2 向量

前面介绍了R中的数据类型,包括数值型、字符型、因子型等,下面开始介绍数据结构。数据类型和数据结构有什么区别呢?简单地说,如果把一个个数据元素比作一块块砖头的话,那么数据类型就是说砖是圆形的还是方形的,主要针对的是砖本身的特性;而数据结构则表示盖房时砖头是怎样排列的,是横着排还是竖着排,是要垒成一个面还是一个体,主要着眼于砖头的排列组织方式。这里要讲的数据结构也类似,它更倾向于表达的是数据元素组织在一起的方式。

总体来说,R中常用的数据结构有四种:向量、矩阵、数据框和列表,不同的数据结构能够存储的数据类型不同,用来处理的函数也有很大差别。向量是用于存储同一种类型数据的一维数组,是所有数据结构中最基础的形式。它的存储方式如图2-5所示,每个格子存储同种类型(比如,这里是字符型)的元素。下面就通过向量的基本操作和常见类型两部分详细讲解。

picture

图2-5 向量的样子

1.基本操作

(1)创建。一般来说,采用函数c(  )即可完成向量的创建,只要在括号中输入每个向量元素就可以了;同时,它还可以把两个向量组合成一个。如果知道向量是以什么规律排列的,也可以按照规律生成向量。比如,创建的向量是等差数列的,就可以使用seq(  )函数;创建从a到b的连续整数,使用a:b就可实现;从一串数字中随机抽取几个数,使用sample(  )函数就可完美实现;用字符串的粘贴功能函数paste0(  ),可以把字符和数字有规律地组合起来(比如,当批量命名变量时)。具体示例如下:

picture

(2)引用。要从一个数据串中提取出其中一部分元素,在方括号中指定元素所处的位置即可调用。然而更多遇见的情形是:只知道想要哪个元素,却不知道它在“哪里”,这时可以通过which(  )函数来实现。另外,which.max(  ) 和which.min(  )还可以直接获取最大值和最小值的位置,是个很方便的定位操作(向量是很多数据结构的基础,之后介绍的数据框、列表结构中也会大量使用)。

picture

(3)集合运算。一个向量可以看作数学中的一个集合,因此自然可以对其进行许多常见的集合运算。这部分最常用的是以下三个:求交集intersect(  ) ;求并集union(  ) ;求差集setdiff(  ) 。

picture

这几个函数虽然平淡无奇,但在有些场合的巧妙使用能大幅提升处理大型数据集的效率。

以上就是一些向量的通用操作命令,下面将针对两种常见类型——数值向量和字符向量,详细讲解适合它们各自特点的操作技法。

2.常见类型

(1)数值向量。处理数值向量有很多函数。表2-4中罗列了常用的函数及其简单用法。下面主要对最容易混淆和特色功能比较隐蔽的函数进行介绍,这些函数也是在数据分析中常用的函数。

picture

表2-4 数值向量常用函数说明表

下面具体介绍两个特色功能很隐蔽的函数:match(  ) 和cut(  ) 。

picture

很明显,match(  )函数可为我们在y中找到x的元素所对应的位置,这在做两个对象匹配时很有用;cut(  )函数则可以帮我们完成一项数据分析的重要功能:连续数据离散化,也就是把连续型数据变成离散的定性数据来参与建模。用好cut(  )函数,就可以省去自己用条件语句转换的麻烦。

picture

下面再来看两个最容易混淆的函数:sort(  )和order(  )。

picture

从以上操作可以看出,通过sample(  ) 抽样得到的x为1 5 4 6 7。 sort(  )函数简单,就是把一个向量排序,默认是递增顺序,这里得到的结果是:1 4 5 6 7。如果想得到递减顺序,可以设置decreasing=T。 order(  )函数的逻辑则稍复杂些:它能够输出把原向量升序排序后(也就是得到:1 4 5 6 7后),每个排序后数据在原始向量中的位置。如在本例中,order(  ) 函数每个输出的含义是:最小值1在原始向量x中位于第1个,因此order(  )函数的输出结果中第一个元素就是1,而次小值4在原始向量x中位于第3个,因此order(  )函数的输出结果中第二个元素就是3,依次类推。因此,命令x[order(x)] 的实现效果跟sort(x)一样。

相对于sort(  ) ,order(  )的功能差不多,但明显难懂一些,那么order(  ) 是不是用处就不大呢?下面给一个场景,在操作Excel时常用一个功能:对一个数据表,先按x列排序,排好后再按y列排序,甚至还得按z列再排次序,这类有先后的复杂排序功能在R中如何实现呢?此时就可以通过order(  )函数来实现,具体的操作将在介绍数据框时详细讲解。

(2)字符向量。字符这种变量类型不同于数值,它有很多独有的特征,处理时需要用专用函数来实现。先拿单独一个字符对象来说,就有很多独特性,比如我们通常不太会对一个数值求它的长度,但对一个字符,很可能就需要了解它的长度。

picture

既然有了长度,就可以对字符进行切分,提取出一个子字符串,这时会使用到的函数是substr(  ) ,具体用法是substr("char" begin_position end_position)。示例如下:

picture

切分可以让字符变小,要想让字符变大就要用到另一个粘贴函数paste(  ) ,这个函数可以把一个向量的各个元素粘起来,也可以把多个向量对应位置上的元素统一粘起来。示例如下:

picture

需要注意的是,collapse是用来给结果的各个元素加连接符的参数。当然除了collapse,还有另外一个连接参数sep。观察以下结果,看是否能体会参数collapse和sep的区别。

picture

collapse可以把一个向量内部的元素粘连起来,而sep则适用于把不同向量分别粘起来,所以它在上面代码的第二行命令中其实并没有起什么作用。

为了进一步熟悉这两个参数的区别,读者可以尝试是否能从下面的命令看出它们的实现结果。

picture

下面再介绍一下大家最关注的查找替换函数,这个在Office里非常热门的功能可快速扫描大量文本查找特定的字符。在R中,用来查找的函数是grep( ),用来替换的函数是gsub( ),基本用法非常简单,可以参考以下例子:

picture

grep( )和gsub( )的用法虽然简单,但却是清洗数据必备函数之一。设想几个场景。近年来,青春片热度超前,那么在前面提到的电影数据集中,青春片的票房表现如何呢?最简单的方法是,通过grep( )提取片名含有“青春”的观测,就能一目了然了。

picture

从以上命令可以看出,电影数据集中的青春片是改编自刘同同名小说的《谁的青春不迷茫》,它在3个月内达到了近1.78亿元的票房,豆瓣评分6.4。我们再通过简单的逻辑比较命令就能马上获知,在电影数据集中,这部影片的票房在均值之下,但豆瓣得分在平均水平以上。

再比如,目前,数据分析师这个职业炙手可热,大家对其可观的收入也是众说纷纭。假如我们获得了5个数据分析师年薪统计的一手资料,想看看收入的平均值和中位数如何,可不巧的是,它们后面均带了“万”这个单位,这时该怎么办呢? gsub( )函数就可以派上用场了(别忘了再转换成numeric格式)。

picture

最后,我们通过一个总体的表格来整体回顾一下字符向量的处理要点(见表2-5)。

picture

表2-5 字符向量处理函数说明表

向量是R语言中最基本的数据结构,实际上,向量化处理在R语言中是非常重要的编程思想,它能让我们避免很多循环,使代码更为简洁、高效和易于理解。什么是向量化呢?简单来说,就是把应用于每一个元素的操作应用于这些元素组成的向量,从而实现批量计算。