《R语言实战》学习笔记及代码(第四章)
感谢Robert I.Kabacoff 著作本书,同时感谢高涛、肖楠、陈钢编译此书。
最近在学习《R语言实战》,特将学习过程记录下来,供各位朋友参考,虽说是笔记,但是90%是书中内容,另外10%是自己偶尔冒出的一点点想法的记录和一些疑问,希望互相探讨。末尾有本章的代码清单下载地址,与各位交流,还是提倡按照书中内容把代码一个个敲出来。
第四章 基本数据管理
本章内容
操纵日期和缺失值
熟悉数据类型的转换
变量的创建和重编码
数据集的排序,合并与取子集
选入和丢弃变量
4.1 一个示例
代码清单中,最后一行的最后一个参数,stringsAsFactors = FALSE,个人认为含义是:特征向量能否转换为因子,默认TRUE,可以转换。R中解释为:
stringsAsFactors
logical: should character vectors be converted to factors? The ‘factory-fresh’ default is TRUE, but this can be changed by setting options(stringsAsFactors = FALSE)
4.2 创建新变量
在R中,算数运算符除了+、-、*、/,还有
^(或 **):求幂。
x%%y:求余,5%%2的结果为1。
x%/%y:整数除法,5%/%2的结果为2。
代码清单4-2提供了三种将新变量整合到原始的数据框中的方式。相当于在列表中增加新的一列(新的观测)。作者推荐使用第三种方式,我个人也比较喜欢第三种,主要是简便并且不容易误操作。
4.3 变量的重编码
重编码涉及根据一个变量和/或其他变量的现有值创建新值得过程。
P69页的第一句话是什么意思?
语句variable[condition] <- expression将仅在condition的值为TRUE时执行赋值。
解释:
variable 变量的
condition 条件
expression 表达式
仅在变量的条件为TRUE时进行赋值。
首先要执行“将99转换为缺失值NA”,其次在书中P69页执行第一段或者第二段代码。
函数within()与函数with()类似,不同的是它允许你修改数据框。
4.4变量的重命名
- 交互式方法。
使用fix(数据框名)即可调出一个交互式的编辑器,可直接点击变量名进行修改。 - 编程的方法
下载、载入reshape包,注意使用R 3.3.1版本。然后使用其中的rename()函数即可。
编程的方式也分为几种方法:
-
直接将旧名称换为新名称。
data.frame <- rename(oldname = "newname", oldname = "newname", …)
-
指定变换的变量数字。
names(data.frame)[2] <- "newname"
-
以向量的方式批量更换某一部分变量名。
names(data.frame)[2:5] <- c("newname", "newname", …)
4.5 缺失值
is.na()将返回逻辑值TRUE(存在缺失值)和FALSE(不存在缺失值)。
注意:
缺失值被认为是不可比较的,即便是与确实值自身的比较。这一位这无法使用比较运算符来检测缺失值是否存在。例如,逻辑测试myvar == NA的结果永远不会是TRUE。作为替代,你只能使用处理缺失值的函数(如本节中所述的那些)来识别R数据对象终归的缺失值。
4.5.1 重编码某些值为缺失值
如4.3节那样可以使用赋值语句将某些值重编码为缺失值。
leadership$age[leadership$age == 99] <- NA
请确保所有的缺失数据已在分析之前被妥善地编码为缺失值,否则分析结果将失去意义。
4.5.2 在分析中排出缺失值
缺失值需要以某种方式删除,因为含有缺失值的算术表达式和函数的计算结果也是缺失值。
多数数值函数拥有一个na.rm = TRUE的选项,可以在计算之前移除缺失值并使用剩余值进行计算。
x <- c(1, 2, NA, 3)
<BR>
y <- sum(x, na.rm = TRUE)
在使用函数处理不完整的数据时,请务必查阅他们的帮助文档,检查这些函数是如何处理缺失数据的。
函数na.omit()可以移除所有含有缺失值的观测。
4.6 日期值
日期通常以字符串的方式输入到R中,然后转化为以数值形式存储的日期变量。函数as.Date()用于执行这种转化。其语法为:as.Date(x, "input_format")
在P73页中有一句话,个人觉得,翻译有误。原文为:
< 使用指定格式读取字符型变量,并将其作为一个日期变量替换到数据框中。
个人建议将第二句话改为:并将其修改成指定格式的数值型变量(指定的日期格式)。
时间戳
- Sys.Date()函数 返回当天的日期。
- date()函数 返回当前的日期和时间。
使用函数format(x, format = "output_format")来输出指定格式的日期值,并且可以提取日期值中的某些部分。
疑问
在使用如下代码时,书中显示的是英文的非缩写月份,而在RStudio中是中文的月份。
today <- Sys.Date()
format(today, format = "%B %d %Y")
书中显示的是:"December 01 2010"
而我操作时显示的是:"六月 29 2016"
format(today, "%A")
书中显示的是:"Wednesday"
而我操作时显示的是:"星期三"
difftime()函数用于计算时间间隔,并以星期、天、时、分、秒来表示。units = auto(自动)、secs(秒)、mins(分)、hours(时)、days(天)、weeks(星期)。
问:为何没有年为结果的参数选项?
4.6.1 将日期转换为字符型变量
strDate <- as.character(dates)
4.6.2 更进一步
要了解字符型数据转换为日期的更多细节,请查看help(as.Date)和help(strftime)。
要了解更多关于日期和时间格式的知识,请参考help(ISOdatetime)
lubridate包中包含了许多简化日期处理的函数,可以用于识别和解析日期-时间数据,抽取日期-时间成分(例如年份、月份、日期等),以及对日期-时间值进行算术运算。
如果你需要对日期进行复杂的计算,namefCalendar包可能会有帮助。它提供了大量的日期处理函数,可以同时处理多个时区,并且提供了历法操作功能,支持工作日、周末以及假期。
4.7 类型转换
名为is.datatype()这样的函数返回TRUE或FALSE,而as.datatype()这样的函数则将其参数转换为对应的类型。
4.8 数据排序
使用order()函数对一个数据框进行排序。默认的排序顺序是升序,在排序变量前边加一个减号,即可得到降序的排序结果。order()可以同时添加多个变量。
4.9 数据集的合并
如果数据分散在多个地方,你就需要在继续下一步之前将其合并。本节展示了向数据框中添加列(变量)和行(观测)的方法。
4.9.1 添加列
使用merge()函数可以,通过一个或多个共有变量合并数据框。
如下代码
ID <- c(1, 2, 3)
name1 <- c("a", "b", "c")
age1 <- c(11, 12, 13)
name2 <- c("d", "e", "f")
age2 <- c(14, 15, 16)
dataframe1 <- data.frame(ID, name1, age1)
dataframe1
dataframe2 <- data.frame(ID, name2, age2)
dataframe2
newdataframe <- merge(dataframe1, dataframe2, by = "ID")
newdataframe
以上是通过一个共有变量ID,合并两个数据框的。
newdataframe2 <- cbind(dataframe1, dataframe2)
newdataframe2
使用cbind()函数可以直接横向合并两个矩阵或数据框。
4.9.2 添加行
使用rbind()函数可以纵向合并两个数据框(数据集)。通常用于向数据框中添加观测。
注意
- 两个数据框必须拥有相同的变量,顺序可以不同。
- 如果数据框A中有数据框B没有的变量,请在合并之前做以下某种处理:
- 删除A中的多余变量。
- 在B中创建追加的变量并将其值设为NA(缺失)。
4.10 数据集取子集
R拥有强大的索引特性,可以用于访问对象中的元素。也可利用这些特性对变量或观测进行选入和排除。
4.10.1 选入(保留)变量
myvars3 <- names(leadership) %in% c("q3", "q4")
newdata4 <- leadership[!myvars3]
newdata4
(1) names(leadership)生成了一个包含所有变量名的字符型向量:c("manafer", "date", "country", "gender", "age", "q1", "q2", "q3", "q4", "q5")。
(2) names(leadership) %in% c("q3", "q4")返回一个逻辑型向量,names(leadership)中每个匹配q3或q4的值为TRUE,反之为FALSE:c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE)。
(3)运算符非(!)将逻辑值翻反转:c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE)。
(4) leadership[c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE)]选择了逻辑值为TRUE的列,于是q3和q4倍剔除了。
在知道q3和q4是第八个和第九个变量的情况下,可以使用语句:
newdata <- leadership[c(-8, -9)]
将他们剔除。原理是:**在某一列的下标之前加一个减号(-)就会剔除那一列了。
相同的变量删除工作亦可通过:
leadership$q3 <- leadershi$q4 <- NULL
来完成。
将q3和q4设为了未定义(NULL)。注意,NULL和NA是不同的。
4.10.3 选入观测
选入或剔除观测(行)通常是成功的数据准备和数据分析的一个关键方面。
代码清单4-6 选入观测
newdata <- leadership[1:3, ]
newdata
newdata <- leadership[which(leadership$gender == "M" & leadership$age > 30), ]
newdata
attach(leadership)
newdata <- leadership[which(gender == "M"& leadership$age > 30), ]
detach(leadership)
newdata
在以上的每个示例中,你只提供了行下标,并将列下标留空(故选入了所有列)。在第一个示例中,你选择了第一行到第三行(前三个观测)。
在第二个示例中,你选择了所有30岁以上的男性。让我们拆解这行代码以便理解它。
(1) 逻辑比较leadership$gender == "M" 生成了向量c(TRUE, FALSE, FALSE, TRUE, FALSE)。
(2) 逻辑比较leadership$age > 30 生成了向量c(TRUE, TRUE, FALSE, TRUE, TRUE)。
(3) 逻辑比较c(TRUE, FALSE, FALSE, TRUE, FALSE) & c(TRUE, TRUE, FALSE, TRUE, TRUE)生成了向量c(TRUE, FALSE, FALSE, TRUE, FALSE)。
(4) 函数which()给出了向量中值为TRUE元素的下标。因此,which(c(TRUE, FALSE, FALSE, TRUE, FALSE))生成了向量c(1, 4)。
(5) leadership[c(1, 4), ]从数据框中选择了第一个和第四个观测。这就满足了我们选取准则(30岁以上的男性)。
第三个示例使用了attach()函数,所以就不必再变量名前加上数据框名称了。
将研究范围限定子啊2009年1月1日到2009年12月31日之间收集的观测,使用以下代码:
leadership$date <- as.Date(leadership$date, "%m/%d/%y")
startdate <- as.Date("2009-01-01")
enddate <- as.Date("2009-12-31")
newdate <- leadership[wihch(leadershi$date >= startdate & leadership$date <= enddate), ]
4.10.4 subset()函数
使用subset()函数可以简便的选入观测。
冒号运算符“:”,表示从…到…,在书中表示选择保留的列。
4.10.5 随机抽样
sample()函数可以从数据集中(有放回或无放回地)抽取大小为n的一个随机样本。
sample()函数中的第一个参数是一个由要从中抽样的元素组成的向量,在这里,这个向量是1到数据框中观测的梳理,第二个参数是要抽取的元素数量,第三个参数表示无放回抽样。sample()函数会返回随机抽样得到的元素,之后可用于选择数据框中的行。
更进一步
R中拥有齐全的抽样工具,包括抽取和小郑调查样本(详见sampling包)以及分析复杂调查数据(详见survey包)的工具其他依赖于抽样的方法,包括自助法和重抽样统计方法,详见第11章。
4.11 使用SQL语句操作数据框
由于不会SQL以及没有数据库相关经验,故跳过此章。