4.10 数据集取子集
R拥有强大的索引特性,可以用于访问对象中的元素。也可利用这些特性对变量或观测进行选入和排除。以下几节演示了对变量和观测进行保留或删除的若干方法。
4.10.1 选入(保留)变量
从一个大数据集中选择有限数量的变量来创建一个新的数据集是常有的事。在第2章中,数据框中的元素是通过dataframe[row indices, column indices]
这样的记号来访问的。你可以沿用这种方法来选择变量。例如:
newdata <- leadership[, c(6:10)]
从leadership
数据框中选择了变量q1
、q2
、q3
、q4
和q5
,并将它们保存到了数据框newdata
中。将行下标留空(,
)表示默认选择所有行。
语句:
myvars <- c("q1", "q2", "q3", "q4", "q5")
newdata <-leadership[myvars]
实现了等价的变量选择。这里,(引号中的)变量名充当了列的下标,因此选择的列是相同的。
最后,其实你可以写:
myvars <- paste("q", 1:5, sep="")
newdata <- leadership[myvars]
本例使用paste()
函数创建了与上例中相同的字符型向量。paste()
函数将在第5章中讲解。
4.10.2 剔除(丢弃)变量
剔除变量的原因有很多。举例来说,如果某个变量中有若干缺失值,你可能就想在进一步分析之前将其丢弃。下面是一些剔除变量的方法。
你可以使用语句:
myvars <- names(leadership) %in% c("q3", "q4")
newdata <- leadership[!myvars]
剔除变量q3
和q4
。为了理解以上语句的原理,你需要把它拆解如下。
names(leadership)
生成了一个包含所有变量名的字符型向量:c("managerID","testDate","country","gender","age","q1", "q2","q3","q4","q5")
。names(leadership) %in% c("q3", "q4")
返回了一个逻辑型向量,names(leadership)
中每个 匹配q3
或q4
的元素的值为TRUE
,反之为FALSE
:c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE)
。运算符非(
!
)将逻辑值反转:c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE)
。leadership[c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE)]
选择了逻辑值为TRUE
的列,于是q3
和q4
被剔除了。
在知道q3
和q4
是第8个和第9个变量的情况下,可以使用语句:
newdata <- leadership[c(-8,-9)]
将它们剔除。这种方式的工作原理是,在某一列的下标之前加一个减号(?)就会剔除那一列。
末了,相同的变量删除工作亦可通过:
leadership$q3 <- leadership$q4 <- NULL
来完成。这回你将q3
和q4
两列设为了未定义(NULL
)。注意,NULL
与NA
(表示缺失)是不同的。
丢弃变量是保留变量的逆向操作。选择哪一种方式进行变量筛选依赖于两种方式的编码难易程度。如果有许多变量需要丢弃,那么直接保留需要留下的变量可能更简单,反之亦然。
4.10.3 选入观测
选入或剔除观测(行)通常是成功的数据准备和数据分析的一个关键方面。代码清单4-6给出了一些例子。
代码清单4-6 选入观测
newdata <- leadership[1:3,]
newdata <- leadership[which(leadership$gender=="M" &
leadership$age > 30),]
attach(leadership)
newdata <- leadership[which(gender=='M' & age > 30),]
detach(leadership)
在以上每个示例中,你只提供了行下标,并将列下标留空(故选入了所有列)。在第一个示例中,你选择了第1行到第3行(前三个观测)。
在第二个示例中,你选择了所有30岁以上的男性。让我们拆解这行代码以便理解它。
逻辑比较
leadership$gender=="M"
生成了向量c(TRUE, FALSE, FALSE, TRUE, FALSE)
。逻辑比较
leadership$age > 30
生成了向量c(TRUE, TRUE, FALSE, TRUE, TRUE)
。逻辑比较
c(TRUE, FALSE, FALSE, TRUE, TRUE) & c(TRUE, TRUE, FALSE, TRUE, TRUE)
生成了向量c(TRUE, FALSE, FALSE, TRUE, FALSE)
。函数
which()
给出了向量中值为TRUE
元素的下标。因此,which(c(TRUE, FALSE, FALSE, TRUE, FALSE))
生成了向量c(1, 4)
。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-10-31")
newdata <- leadership[which(leadership$date >= startdate &
leadership$date <= enddate),]
首先,使用格式mm/dd/yy将开始作为字符值读入的日期转换为日期值。然后,创建开始日期和结束日期。由于as.Date()
函数的默认格式就是yyyy-mm-dd,所以你无须在这里提供这个参数。最后,像上例一样选取那些满足你期望中准则的个案即可。
4.10.4 subset()
函数
前两节中的示例很重要,因为它们辅助描述了逻辑型向量和比较运算符在R中的解释方式。理解这些例子的工作原理在总体上将有助于你对R代码的解读。既然你已经用笨办法完成了任务,现在不妨来看一种简便方法。
使用subset
函数大概是选择变量和观测最简单的方法了。两个示例如下:
newdata <- subset(leadership, age >= 35 | age < 24,
select=c(q1, q2, q3, q4))
newdata <- subset(leadership, gender=="M" & age > 25,
select=gender:q4)
在第一个示例中,你选择了所有age
值大于等于35 或age
值小于24的行,保留了变量q1
到q4
。在第二个示例中,你选择了所有25岁以上的男性,并保留了变量gender
到q4
(gender
、q4
和其间所有列)。你在第2章中已经看到了冒号运算符from:to
。在这里,它表示了数据框中变量from
到变量to
包含的所有变量。
4.10.5 随机抽样
在数据挖掘和机器学习领域,从更大的数据集中抽样是很常见的做法。举例来说,你可能希望选择两份随机样本,使用其中一份样本构建预测模型,使用另一份样本验证模型的有效性。sample()
函数能够让你从数据集中(有放回或无放回地)抽取大小为n的一个随机样本。
你可以使用以下语句从leadership
数据集中随机抽取一个大小为3的样本:
mysample <- leadership[sample(1:nrow(leadership), 3, replace=FALSE),]
sample()
函数中的第一个参数是一个由要从中抽样的元素组成的向量。在这里,这个向量是1到数据框中观测的数量,第二个参数是要抽取的元素数量,第三个参数表示无放回抽样。sample()
函数会返回随机抽样得到的元素,之后即可用于选择数据框中的行。
更进一步
R中拥有齐全的抽样工具,包括抽取和校正调查样本(参见sampling
包)以及分析复杂调查数据(参见survey
包)的工具。其他依赖于抽样的方法,包括自助法和重抽样统计方法,详见第11章。