ITPub博客

首页 > > > 【R语言】:基本数据管理(2)

【R语言】:基本数据管理(2)

作者:浪花小雨滴 时间:2020-06-17 10:33:44 0 删除 编辑
操纵日期和缺失值
熟悉数据类型的转换
变量的创建和重编码
数据集和排序,合并与取子集
选入和丢弃变量
参考书籍:《R语言实战(第2版)》第四章
本文代码运行环境为Windows版RStudio

日期值

日期值通常以字符串的形式输入到R中,然后通过函数as.Date()转化为以数值形式存储的日期变量,并且可以规定读取数据的格式,用法为 as.Date(x, "input_format") ,其中 x 是字符型数据, input_format 表示读取日期的格式(见下图,《R语言实战(第2版)》中截图)。


举例来说,todaydates <- as.Date("25/03/2017", "%m/%d%Y")将日期按照“月/日/年”的格式读取数据并储存。

函数Sys.Date()可以返回当天的日期(注意区分大小写,第一个S为大写,否则会报错),函数date()可以返回当前日期和时间。

函数format()可以来输出指定格式的日期值,并且提取日期值中的某一部分,下图为该函数用法的截图。

比如,我们打算输出当前系统时间的非缩写月份、数字表示的日期以及四位数的年份,通过对照最开始的日期格式表,输入以下代码并运行

或者我们可以看见今天是周几,输入以下代码并运行

此外,可以看到函数format还有很多其他用法,这里就不逐个阐述了,如果之后遇到可以再仔细研究。

《R语言实战(第2版)》这本书上还提到R语言存储日期以1970年1月1日以后的天数表示的(比这一天早的日期表示为负数),所以可以计算两个日期之间的天数。比如,我们可以通过以下代码很容易得出新中国成立距当前的系统时间(2017年3月28日)有多少天。

此外,还可以使用函数 difftime() 来计算时间间隔,并以星期、天、时、分、秒来表示,其中tz表示time zone时区,是可选项,下图为该函数用法的截图。
举例说明,与上面类似,如果计算新中国成立距当前的系统时间(2017年3月28日)有多少个星期,可以通过以下代码实现
starttime <- as.Date("1949-10-01")
endtime <- as.Date(Sys.Date())
difftime(endtime, starttime, units = "weeks")

计算多少天、时、分、秒可分别将代码中的"weeks"替换为"days"、"hours"、"mins"、"secs"即可。

一、日期转换为字符型变量

上面讲的是如何把字符型变量转换为日期变量,这种转换是可逆的,用函数as.character()可以将日期变量转换为字符型变量。

举例说明,以下代码就可以将系统日期转化为字符型变量并储存。

strDate <- as.character(Sys.Date())

运行代码后在RStudio的Global Environment中见到字符型变量strDate。

二、两个扩展包

lubridate 包可用于识别和解析日期-时间数据,抽取日期-时间成分(例如年份、月份、日期等),以及对日期-时间值进行算术运算。

fCalendar 包提供了大量的日期处理函数,可同时处理多个时区,帮助用户对日期进行复杂的计算并且提供了复杂的历法操作功能,支持工作日、周末以及假期。

类型转换

从以上内容我们不难联想到:不同类型的变量通过某些函数可以相互转换。除此之外,R语言还提供了很多函数帮助用户判断某个对象的数据类型。《R语言实战(第2版)》一书提供了一些判断和转换数据类型的常用函数,截图如下:

后面第五章将涉及到控制流,比如if-then,这时与is函数结合可以让用户根据数据的具体类型以不同的方式处理数据;同时,as函数可以帮助用户在必须使用某个特定类型的数据时将数据转换为该特定类型的数据格式。

数据排序

对已有的数据进行排序是一个很常见的需求,相信很多人在Excel中经常使用排序功能。在R语言中,可以使用函数order()对数据框进行排序,默认为升序,降序可以通过在排序变量的前面加一个减号(-)来实现。函数order()用法的截图如下:

其中na.last为真表示把缺失值NA放在最后,decreasing为真表示按照降序排列(也可以用变量前面加减号的方法)。

举例说明,对系统自带的数据框mtcars中优先按照车身重量wt升序排列,在此基础上按照每加仑汽油行驶英里数(耗油量)升序排列,代码如下

#获取系统自带数据框mtcars
attach(mtcars)

#创建一个新的数据集newdata,优先按照车身重量排序,在此基础上按照每加仑汽油行驶英里数(耗油量)升序排列
newdata <- mtcars[order(wt, mpg), ]

#解除绑定数据框mtcars
detach(mtcars)

运行代码,看一下数据集newdata的部分截图,车身重量wt按照升序排列,三个wt相等(均为3.440)的车再按照耗油量mpg升序排列。

再试一下降序,可以优先按照车身重量wt升序排列,在此基础上按照每加仑汽油行驶英里数(耗油量)降序排列,代码如下

#获取系统自带数据框mtcars
attach(mtcars)

#创建一个新的数据集newdata,优先按照车身重量排序,在此基础上按照每加仑汽油行驶英里数(耗油量)升序排列
newdata <- mtcars[order(wt, -mpg), ]

#解除绑定数据框mtcars
detach(mtcars)

运行代码,再看一下数据集newdata的部分截图,车身重量wt按照升序排列,三个wt相等(均为3.440)的车再按照耗油量mpg降序排列,还有两个wt相等(均为3.570)的车也同样按照 耗油量mpg降序排列。

数据集的合并

一、添加列

如果两个数据框(数据集)中有某几列(一个或多个)名称一致,那么两个数据框(数据集)可以通过这一个或多个共有的列(变量)进行联结,也称为内联结(inner join),可以利用函数merge()将两个数据框(数据集)按这几列合并,也称为横向合并。

其中x和y表示合并的两个数据框;by、by.x、by.y表示依据哪些列名合并数据框,默认值为相同列名的列向量;all、all.x、all.y表示x和y列向量中的行合并之后如何输出(因为有可能会有数据缺失,也就是存在空值,所以这一块非常复杂,将来有机会可以写一篇文章专门说明,这里有一篇说得较为详细:R数据分析之merge函数,如果有兴趣可以参考);sort表示by指定的列额是否要排序;suffixes表示除by外相同列名的后缀;incomparables表示by中哪些单元不进行合并。简单举例,见以下代码。


#将dataframeA和dataframeB按照ID合并
total <- merge(dataframeA, dataframeB, by="ID")

#将dataframeA和dataframeB按照按照ID和Country合并
total <- merge(dataframeA, dataframeB, by=c("ID", "Country"))

直接横向合并两个对象(矩阵或数据框),并且不需要指定公共索引,则可以直接使用函数cbind(),但每个对象必须拥有相同的行数并且以相同顺序排序,这里的对象甚至可以只是一个列向量,可参考【R语言】:数据结构入门(2)。

二、添加行

既然数据框可以横向合并,必然也可以纵向合并,也就是向数据框中添加行——观测记录。纵向合并两个数据框,使用函数rbind()。纵向合并的两个数据框必须拥有相同的列,不过顺序不必一定相同。

假设有两个数据框dataframeA和dataframeB,可通过以下代码纵向合并两个数据框。

total - rbind(dataframeA, dataframeB)

两个数据框拥有不相同的列应该如何处理?如果dataframeA中存在dataframeB中不存在的列变量,那么合并之前必须完成以下某种处理:

  • 删除dataframeA中的多余列变量;
  • 在dataframeB中创建追加的变量并将其值设为缺失值NA。

数据集取子集

一、选入(保留)变量

实际工作中,我们常常需要从一个很大的数据集中选择有限数量的变量创建新的数据集(这并不算随机抽样),在【R语言】:数据结构入门(2)中曾经介绍过。

用法为数据框名称[行目录, 列目录],以系统自带数据框mtcars举几个例子。

#获取系统自带数据框mtcars
attach(mtcars)
#在数据框mtcars中选取第2列到第7列
newdata_1 <- mtcars[, c(2:7)]

运行代码后,查看newdata_1,如下图。

#在数据框mtcars中选取mpg、cyl、wt这三列
newdata_2 <- mtcars[c("mpg", "cyl", "wt")]

运行代码后,查看newdata_2,如下图。

二、剔除(丢弃)变量


往更深层想一下,剔除(丢弃)变量的本质是通过从原数据集中删除变量的方法来确定需要选入(保留)向量,没被删除的向量自然就保留了下来。还是以系统自带数据框mtcars为例,如果想用剔除(丢弃)变量的方法得到跟newdata_1相同的结果,代码可以这样写

#在数据框mtcars中选取删除第1列和第8-11列
newdata_3 <- mtcars[, c(-1, -8:-11)]

运行代码,删除了原数据框mtcars中的第1列和第8-11列,新数据框newdata_3与newdata_1完全一致,如下图

此外,还有另外一种相对复杂的方法,适合列向量比较多并且知道列向量名称的情况。因为这种情况下不太容易确定要删除的列向量所对应的数字。

如果还想得到跟newdata_1一致的数据框,需要删除原数据框mtcars中名称为mpg、vs、am、gear、carb这五个列向量。先看代码,再详细解释。

deldata <- names(mtcars)%in%c("mpg", "vs", "am", "gear", "carb")
newdata_4 <- mtcars[!deldata]

这段代码删除了数据框mtcars中的五个列变量mpg、vs、am、gear、carb,下面逐步拆解详细说明:

  • names(mtcars)表示生成了一个包含数据框中所有列向量名称的字符型向量:c("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear", "carb");
  • 函数match与函数%in%,两者都是匹配函数,用法截图如下,这里仅详细说明后者(函数match之后可单独写一篇说明)。对于函数%in%来说,返回值是逻辑型变量,前面x中每个匹配table的元素的值为TRUE,否则为FALSE。所以在本例中,代码的含义就是让字符型向量names(mtcars)中与向量c("mpg", "vs", "am", "gear", "carb")匹配,得到的逻辑型变量为c(TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE,TRUE);
  • 利用运算符"!"将逻辑值反转,得到完全相反的逻辑型变量c(FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE);
  • mtcars[c(FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE)]表示选择了逻辑值为TRUE的列向量,所以五个列变量mpg、vs、am、gear、carb被删除了,得到newdata_4与newdata_1、newdata_3一致。

三、选入(删除)观测(行)


在数据分析的准备工作中,因为数据缺失而选入(或删除)观测(行)几乎是必不可少的,这也是进行成功数据分析的关键步骤。

仍然以系统自带数据框mtcars举例,选取前5行观测,跟选入列类似,不再赘述,代码如下

newdata_5 <- mtcars[c(1:5), ]

运行代码,得到newdata_5,如下图

同理,也有另外一种相对复杂的方法,运用函数which()可以按照行名称选入(或删除)观测,用法截图如下

比如我们选择cyl等于8,wt大于4的观测,代码如下

newdata_6 <- mtcars[which(mtcars$cyl == 8 & mtcars$wt > 4), ]
  • 逻辑比较mtcars$cyl == 8生成了向量c(FALSE, ..., TRUE, TRUE, ..., FALSE),即列向量cyl中为8的元素为TRUE,否则为FALSE;
  • 同理,逻辑比较mtcars$wt > 4生成了向量c(FALSE, ..., TRUE, TRUE),即列向量wt中所有大于4的元素为TRUE,否则为FALSE;
  • 用运算符"&"逻辑比较前逻辑型向量,生成新的逻辑型向量;
  • "&"逻辑比较的规则:两个TRUE为TRUE,一个TRUE一个FALSE或一个FALS一个TRUE为FASLE,两个FALSE为FALSE;
  • 函数which()给出了最后比较得出的逻辑型向量中为TRUE的元素下标,假设为向量c[2, 14, 25, 32](数据框总共32行,具体确定太麻烦,能够说明问题即可);
  • 最后mtcars[c(2, 14, 25, 32), ]表示选择了数字对应的观测。

运行代码,得到newdata_6,如下图

四、subset()函数


前面第二和第三小节中,详细描述了逻辑型向量和比较运算符在R语言中的解释方式,通过理解上面例子的工作原理能大大有助于对R语言代码的解读。

函数subset()是选择变量和观测最简单的方法(看到这里总有一种前面被欺骗了的感觉),该函数具体的用法如下

其中,x可以是数据框、向量、矩阵;subset表示选入观测的一个逻辑表述或者说是一个条件;select表示要选取的列向量;drop = TRUE 表示将得到的结果组成列表。


还以系统自带数据框mtcars为例,仍然选择cyl等于8,wt大于4的观测,但同时选择从cyl到wt的所有列,如果运用函数subset(),则代码如下

newdata_7 <- subset(mtcars, cyl == 8 & wt > 4, select=cyl:wt)
运行代码,得到newdata_7,如下图

还可以这样玩,选择mpg大于30或者小于15的观测,保留mpg、cyl、wt三列,如果运用函数subset(),则代码如下

newdata_8 <- subset(mtcars, mpg > 30 | mpg < 15, select=c(mpg, cyl, wt))

运行代码,得到newdata_8,如下图

五、随机抽样


无论是以往的统计学实际应用,还是目前异常火爆的数据挖掘和机器学习领域,常常需要做随机抽样。书中提到,往往会选择两份随机样本,一份用于构建预测模型,另一份用于验证模型的有效性。在R语言中,运用函数sample()可以从数据集中(有放回或无放回地)抽取大小为n的一个随机样本,用法截图如下

其中,x表示备选向量;n 表示选取的数量;replace 表示是否放回抽样;prob用来设置所要抽取的每个元素被抽取的概率。

举例说明,看下面一段代码。nrow(mtcars)表示数据框mtcars的观测(行)数,因此备选向量表示1到数据框中观测的数量;抽取的数量为4;抽样不放回

newsample <- mtcars[sample(1:nrow(mtcars), 4, replace = FALSE), ]

运行代码,抽取到随机样本sample,如图所示

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3122352/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 安装docker
请登录后发表评论 登录
全部评论

注册时间:2018-05-16

  • 博文量
    4259
  • 访问量
    40140