购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.4 R语言中的数据处理

作为一种统计分析软件,R语言的优势在于其出色的数据处理能力,简便而强大的编程语言以及集成的函数包使得R语言几乎能够胜任各种数据分析统计工作。本节主要介绍R语言中的各种数据处理操作。

1.4.1 从数据集中提取信息

R语言中有许多函数可以提取对象或数据集的内容。

ls()函数用于列出当前工作环境中的所有对象:

names()函数可用于提取对象中的变量:

str()函数用于展示对象的结构:

levels()函数可以列出因子型变量中的因子水平:

dim()函数用于获取矩阵等数据类型对象的维度:

class()函数可用于获取对象的数据类型:

直接输入某个对象的名称可获取对象中包含的所有元素:

head()函数用于获取数据的开头几行:

tail()函数用于获取数据的末尾几行:

1.4.2 缺失信息处理

在R语言中,缺失的信息用符号NA(not available)表示,不存在的数值(如除以0)用符号NaN(not a number)表示。不同于SAS,R语言对字符型数据和数值型数据使用相同的符号。

is.na()函数用于验证数据中的缺失值,其返回值为逻辑向量,若数据为NA,则返回TRUE,否则返回FALSE。

R语言中还允许用户将元素重新编码为缺失值:

缺失数据会对数据分析的结果和速度造成一定的影响,因此在通常情况下,我们在进行数据分析时往往希望移除缺失数据。在R语言中通过将参数na.rm的值设置为TRUE即可达到此目的。

complete.cases()函数返回一个逻辑向量,指示数据集中没有缺失数据的部分。下面的示例中,我们通过!complete.cases(mydata)语句指示矩阵mydata中有缺失的部分。

na.omit()函数用于返回删除缺失值后的对象,下面的示例展示了如何获取删除缺失值后的mydata。

1.4.3 运算符

对于有编程基础的读者来说,R语言中的二进制运算符和逻辑运算符看起来将会非常熟悉,它们类似于其他编程语言中的运算符。需要注意的是,二元运算符适用于向量、矩阵以及标量。表1-5展示了R语言中的算术运算符,表1-6展示了R语言中的逻辑运算符。

表1-5 R语言中的算术运算符

表1-6 R语言中的逻辑运算符

我们来看一些关于运算符的具体示例:

上述示例中,向量x12内共有8个元素:1 2 3 4 5 6 7 8,第一个条件x12>6执行后,返回的结果为F F F F F F T T,第二个条件x12<2执行后,返回的结果为T F F F F F F F,逻辑运算符|执行后的返回结果为T F F F F F T T,因此最终结果在输出前的运行程序为x12[c(T,F,F,F,F,F,T,T)],因此输出结果为1 7 8。

R语言中还封装了许多常用的数据统计函数,如对数运算函数log2()、开方函数sqrt()等,读者可自行探索。

1.4.4 替换现有字段中的数据

数据处理的过程中,往往需要替换现有字段中的数据,在R语言中有多种方式达到这一目的。我们首先构造一个数据框schoolData_o,该数据框中含有三个字段:ID、Grade、Status,每个字段包含8个元素,其中sample()函数为取样函数,用于随机打乱字段Grade和Status中的元素顺序。

原始数据框构造完毕后,我们将其复制到数据框schoolData中,之后所有的操作都在schooData上进行。值得一提的是,每开始一轮新的操作,将重置schoolData中的元素为schoolData_o,schoolData_o中的元素如图1-4所示。

图1-4 schoolData_o中的元素

下面将用几个示例展现如何替换R语言中现有字段中的数据。我们先展示在无条件的情况下如何替换现有字段中的数据。以下将数据框SchoolData中的Grade字段中的所有数据分别替换为数字5、文本字符串“Five”或NA。

把数据框schoolData中的Grade字段的所有数据替换成数字5:

把数据框schoolData中的Grade字段的所有数据替换成文本字符串“Five”:

把数据框schoolData中的Grade字段的所有数据替换成NA:

下面展示了如何应用条件以便仅替换特定行中的数据。需要注意的是,如果想用某个值替换NA,则不能使用"value"==" NA",必须使用is.na()函数。

把数据框schoolData中的Grade字段内取值小于等于5的所有数据替换成Grade Five or Less:

把数据框schoolData中的Grade字段内的缺失数据替换成Missing Grade:

下面展示了如何根据多个条件替换数据。下面的这段代码创建了一个新字段Type,并找到Grade字段内取值等于5且Status字段内值为open的行,将这些行的Type字段下的元素赋值为“Elementary”。

下面展示了如何复制现有字段。有时我们不想重新编码数据,而只是想要另一列包含相同的数据。此时我们可以制作一个字段的副本,然后在此副本上进行重新编码。

下面基于字段Grade创建一个名为NewGrade的新字段。

为了重新编码数据,我们可能会使用一种或多种R语言的控制结构。

在数据框中创建字段GradeCat,并依据字段Grade中的数值创建三个成绩类别bad、middle、good。与前面提过的示例一样,我们可以再次使用逻辑运算符&或任何其他运算符来生成我们想要的条件。

1.4.5 变量的重命名

在数据处理的过程中,有时为了提高编码的效率与可读性,我们需要修改数据集中某几列的变量名,这在R语言中有多种实现方式。我们首先构造一个简单的数据框simpleData_o,该数据框包含五个字段:ID、Color、Logic、Float、Mix,每个字段包含3个元素。

原始数据框构造完毕后,我们将其复制到数据框simpleData中,之后所有的操作都在simpleData上进行。值得一提的是,每开始一轮新的操作,将重置simpleData中的元素为simpleData_o,simpleData_o中的元素如图1-5所示。

图1-5 simpleData_o中的元素

下面展示了如何更改数据框中列的名称。在没有其他条件的情况下,程序将从第一列开始改名,直到用完提供的名称。例如,数据框simpleData中有五列数据,但我们只提供了两个名称,则只有前两列将被重命名,其余列名会被重置为NA。

下面展示了如何通过使用列名称来标识将要被更改名称的列。以下代码将数据框中名为Logic的字段重命名为NewLogic。

下面展示了如何使用列号来标识将要被更改名称的列。以下代码将数据框中的第4列重命名为NewFloat。

在实际使用的过程中,应尽量避免使用列号标识改名这种方法。因为如果列的顺序发生更改,它将错误地改变列的名称。

1.4.6 数字的四舍五入

数字的四舍五入是一种常见的数据处理方式,在R语言中主要通过round()函数实现这一功能,其语法如下:

其中,x为待舍入的数,digits用于指定四舍五入保留的小数位数。

我们将使用之前构造过的数据框simpleData进行操作。第一个示例将数据框simpleData中的Float字段的数字四舍五入到整数位,并将四舍五入的数字保存回同一字段。round()函数如果未指定小数位数,则默认四舍五入到整数位。

需要注意的是,被四舍舍入的元素必须是数值型参数,否则系统将返回错误提示。以下这段代码中,舍入前的字段元素都丢失了。

我们通常会将舍入后的数值保存在新的字段中,保留原始数据以供以后使用。下面的这段代码是正确的。

下面展示了如何指定要舍入的小数位数。

1.4.7 子集数据

R语言具有强大的索引功能来访问对象元素,这些特征可用于选择和排除变量及观察值。R语言中通过使用符号“[ ]”指定向量、矩阵、数组或数据框内单个元素的索引或名称,从而实现访问这些元素的目的。

我们仍然以数据框simpleData为例,通过指定索引或元素名称来访问元素。

我们还可通过不同数据类型的向量访问元素,如数值型向量、逻辑型向量等。

通过运算符“$”,我们可以指定数据框中的具体字段,示例如下:

下面我们将演示变量的保留,仍以数据框simpleData为例:

接着我们将演示变量的排除,R语言中可通过“!”“-”等运算符直接排除相应的数据,也可以通过给数据赋值NULL达到排除变量的目的。

下面我们将演示观察值的保留或删除,以数据框schoolData为例:

我们在保留变量和观察值时,也可以运用子集函数subset(),该函数是保留变量和观察值的最简单的方式之一。下面的例子中,我们通过subset()函数找出数据框schoolData中的Grade字段大于3或者Status字段为close的行,并保存相应的ID字段中的元素。

下面的示例与上述类似,但是保存的元素为ID字段到Status字段中相应的元素。

1.4.8 随机抽样

从总体中选择样本的方式有很多,其中常用的一种就是随机抽样。在R语言中,通过sample()函数可以模拟随机抽样过程,其语法如下:

其中:x为抽样的总体;size为样本数量;replace表示是否为有放回抽样,其默认值为FALSE;prob表示每个元素被抽中的概率。我们先看一个基础的例子:

接下来我们以数据框schoolData为例,展示sample()函数在数据处理中的用法。

在R语言中,sample()函数还有一种非常实用的使用技巧——随机打乱数据集中的元素顺序。

1.4.9 apply()函数集合

当需要对列表的所有元素或数组的所有列执行多次相同或相似的任务时,可以用到R语言中的apply()函数集合:lapply()、sapply()、apply(),它们有时比for循环更快更简单。

我们首先来学习一下lapply()函数,其语法如下:

函数function会应用到列表li的每个元素上,输出结果还是一个列表,其中的元素皆为应用function后的值。我们看下面这个具体的例子:

sapply()函数与lapply()类似,但该函数试图通过将结果转换为适当大小的向量或数组达到简化结果的目的。其语法如下:

下面的示例中,function函数被设置成和上述lapply()一样的函数,我们来看结果有何差异:

sapply()函数的输出结果被转换成了一个向量,看起来显然比lapply()函数的输出结果更为简洁。

apply()函数具有强大的机制,它可以沿数组的某些维度应用函数,并返回适当大小的向量或数组。apply()函数的语法如下:

其中:arr为数据对象;margin代表维度的下标;margin值为1时表示行,值为2时表示列;fct为指定的函数。接下来的示例中,我们首先构造一个3行4列的矩阵x13,随后在x13上应用apply()函数。

1.4.10 数据类型转换

R语言中的数据类型转换非常简单。is.foo()函数可以测试数据类型是否为foo,若是则返回TRUE,否则返回FALSE,常用的函数包括is.numeric(),is.character(),is.vector(),is.matrix(),is.data.frame()。使用函数as.foo()可以将数据类型显式转化为foo,常用的函数包括as.numeric(),as.character(),as.vector(),as.matrix(),as.data.frame()。需要注意的是,并不是任意两种类型的数据之间都能转换,可发生转换的数据类型如表1-7所示。

表1-7 数据类型间的转换

值得一提的是,R语言中的数据类型转换还有一种隐式转换,如将字符串添加到数值向量中会将数值向量中的所有元素转换为字符。

1.4.11 数据聚合

在R语言中聚合数据相对容易,aggregate()函数可以根据用户需求把数据打组聚合,并对聚合后的数据执行求和、平均等操作,其语法如下:

其中:x为待处理的对象;by为分组元素的列表;FUN为数据处理的函数;simplify决定是否将结果简化为矩阵或向量,其默认值为TRUE;drop决定是否删除没有使用到的分组,其默认值为TRUE。

接下来的示例中,我们使用的数据集为R包自带的数据集iris,其部分信息如图1-6所示。

图1-6 数据集iris的部分信息

其结果如图1-7所示。

图1-7 数据集iris的聚合结果

在该示例中,aggregate()函数中待处理的对象为数据集iris的第1~4列,分组列表为字段Species,处理函数为求均值。结果表明,iris中第1~4列的数据总共被分为三组:setosa、versicolor、virginica,每组中各字段的平均值被计算了出来。

为了加深读者对aggregate()函数的理解,我们将对R包自带的数据集mtcars做进一步的分析,数据集的部分信息如图1-8所示。

图1-8 数据集mtcars的部分信息

其结果如图1-9所示。

图1-9 数据集mtcars的聚合结果

以上信息表明,待处理的对象为mtcars中的全部数据,分组列表为cyl以及vs,处理函数为求均值。从结果来看,mtcars中的数据总共被分为了5组,第一组的特征为cyl=4,vs=0,第二组的特征为cyl=6,vs=0,以此类推,计算每组中各个字段数据的均值。

1.4.12 文本数据排序

对文本数据进行排序是一项很常见的操作,R语言中可以通过order()函数实现这一功能,该函数的语法如下:

其中:x为排序的对象;na.last用于处理缺失值,其默认值为TRUE,表示将缺失值放在最后,反之则将缺失值放在最前,若其取值为NA,则表示移除缺失值;decreasing=FALSE表示默认排序方式为升序排序。order()函数的返回结果为位置次序,即排序后的结果在原对象中的索引。

上述示例中,向量x_o含有8个元素,应用order()函数排序后,排序结果为:18 23 43 45 59 67 73 78,找到这些数在原向量x_o中的位置,即为最终输出结果4 1 6 2 8 5 3 7。

order()函数不仅可以对数值型向量进行排序,还可应用于其他类型的数据。下面的例子展示了order()函数如何对一列字符型数据进行排序,为了获取实验用的数据集stulevel,我们需要安装eeptools包并加载它:

获取数据集stulevel后,我们对其数据中的某几列应用order()函数:

数据集stulevel升序排序后的部分结果如图1-10所示。

图1-10 数据集stulevel升序排序后的部分结果

上述示例首先构建了用于排序的字符型数据字段proflvl_character和race_character,随后对proflvl_character字段中的数据进行升序排序。输出排序结果时,ncol()函数用于获取数据集中的列数,因此(ncol(stulevel1)-3):ncol(stulevel1)表示只输出数据集stulevel的最后四列。

对单行字符型数据进行降序排序,数据集stulevel降序排序后的部分结果如图1-11所示。

图1-11 数据集stulevel降序排序后的部分结果

对两行字符型数据进行升序排序后,我们调用head()函数只输出数据集的前几行。head()函数会默认输出前6行的结果,因此输出结果如图1-12所示。

图1-12 数据集stulevel中的两行字符型数据进行升序排序的部分结果

对两行字符型数据进行降序排序的代码如下:

输出结果如图1-13所示。

图1-13 数据集stulevel中的两行字符型数据进行降序排序的部分结果

1.4.13 数据合并

在R语言中,我们一般使用merge()函数水平合并两个对象,大多数情况下,数据合并的实现需要借助一个或多个公共关键变量,因此数据合并的关键是识别两个不同数据框之间共有的列或行。merge()函数的语法如下:

其中:x、y为需要合并的对象;by用于指定合并的列,函数中默认两个对象通过共同的列进行合并,合并时,共同的列被提出,随后两个对象被合并在一起,用户可以通过by.x或者by.y指定合并是基于共同的列还是共同的行;all用于指示连接为内连接(FALSE)还是外连接(TRUE),all.x=TRUE表明为左外连接,all.y=TRUE表明为右外连接。

下面的例子中,我们首先构造了两个数据框mydataframe1和mydataframe2,随后将二者合并成数据框mydataframe1_2。

上述示例展示了R语言中的内连接,与之相对应的是R语言中的外连接:返回两个表中的所有行,从左边连接在右表中具有匹配的记录。相关代码如下所示。

R语言的外连接又可以分为左外连接和右外连接,其中左外连接返回左表中的所有行,以及右表中具有匹配键的任何行。右外连接返回右表中的所有行,以及左表中具有匹配键的任何行。

1.4.14 table()函数

R语言中的table()函数使用变量及其频率执行数据的分类制表,其主要目标为创建带有条件的频率表和交叉表。下面我们将为R语言自带的数据集iris中的物种类型创建一个频率表。

结果表明,数据集iris中共有三类物种:setosa、versicolor、virginica,它们的频率都是50。我们也可以通过table()函数创建带有条件的频率表,比如数据集iris中有多少观察值的字段Sepal.Length>6.0。

table()函数同样有助于创建2路交叉表。接下来的示例中,我们将使用R语言自带的数据集mtcars,并创建其gear和carb的2路交叉表。

类似于2路交叉表,table()函数还能帮助我们创建3路交叉表。 MmLhgBkP8XdC34Smp3aBjDfeFjYxnLB+QUvvtb/YHB6jjeVxV9MeWwk/huAIuGQn

点击中间区域
呼出菜单
上一章
目录
下一章
×