首页 > 代码库 > 数据的输入
数据的输入
2.3 数据的输入
现在你已经掌握了各种数据结构,可以放一些数据进去了。作为一名数据分析人员,你通常
会面对来自多种数据源和数据格式的数据,你的任务是将这些数据导入你的工具,分析数据,并
汇报分析结果。R提供了适用范围广泛的数据导入工具。向R中导入数据的权威指南参见可在
http://cran.r-project.org/doc/manuals/R-data.pdf下载的R Data Import/Export手册②。
如图2-2所示,R可从键盘、文本文件、Microsoft Excel和Access、流行的统计软件、特殊格
式的文件,以及多种关系型数据库中导入数据。由于我们无从得知你的数据将来自何处,故会在
下文论及各种数据源。读者按需参阅即可。
2.3.1 使用键盘输入数据
也许输入数据最简单的方式就是使用键盘了。R中的函数edit()会自动调用一个允许手动输
入数据的文本编辑器。具体步骤如下:
(1) 创建一个空数据框(或矩阵),其中变量名和变量的模式需与理想中的最终数据集一致;
(2) 针对这个数据对象调用文本编辑器,输入你的数据,并将结果保存回此数据对象中。
在下例中,你将创建一个名为mydata的数据框,它含有三个变量:age(数值型)、gender
(字符型)和weight(数值型)。然后你将调用文本编辑器,键入数据,最后保存结果。
> mydata <- data.frame(age=numeric(0), gender=character(0), weight=numeric(0))
> madata <- edit(mydata)
类似于age=numeric(0)的赋值语句将创建一个指定模式但不含实际数据的变量。注意,编
辑的结果需要赋值回对象本身。函数edit()事实上是在对象的一个副本上进行操作的。如果你
不将其赋值到一个目标,你的所有修改将会全部丢失!
在Windows上调用函数edit()的结果如图2-3所示。
如图2-3所示,我已经自主添加了一些数据。单击列的标题,你就可以用编辑器修改变量名
和变量类型(数值型、字符型)。你还可以通过单击未使用列的标题来添加新的变量。编辑器关
闭后, 结果会保存到之前赋值的对象中( 本例中为mydata )。再次调用mydata <-
edit(mydata),就能够编辑已经输入的数据并添加新的数据。语句mydata <- edit(mydata)
的一种简捷的等价写法是fix(mydata)。
这种输入数据的方式对于小数据集很有效。对于较大的数据集,你所期望的也许是我们接下
来要介绍的方式:从现有的文本文件、Excel电子表格、统计软件或数据库中导入数据。
2.3.2 从带分隔符的文本文件导入数据
你可以使用read.table()从带分隔符的文本文件中导入数据。此函数可读入一个表格格式
的文件并将其保存为一个数据框。其语法如下:
mydataframe <- read.table(file, header=logical_value, sep="delimiter", row.names="name")
其中,file是一个带分隔符的ASCII文本文件,header是一个表明首行是否包含了变量名的逻
辑值(TRUE或FALSE),sep用来指定分隔数据的分隔符,row.names是一个可选参数,用以指
定一个或多个表示行标识符的变量。
举个例子,语句:
grades <- read.table("studentgrades.csv", header="TRUE", sep=",", row.names="STUDENTID")
从当前工作目录中读入了一个名为studentgrades.csv的逗号分隔文件,从文件的第一行取得
了各变量名称,将变量STUDENTID指定为行标识符,最后将结果保存到了名为grades的数据
框中。
请注意,参数sep允许你导入那些使用逗号以外的符号来分隔行内数据的文件。你可以使用
sep="\t"读取以制表符分隔的文件。此参数的默认值为sep="",即表示分隔符可为一个或多个
空格、制表符、换行符或回车符。
默认情况下,字符型变量将转换为因子。我们并不总是希望程序这样做(例如处理一个含有
被调查者评论的变量时)。有许多方法可以禁止这种转换行为。其中包括设置选项
stringsAsFactors=FALSE,这将停止对所有字符型变量的此种转换。另一种方法是使用选项
colClasses为每一列指定一个类,例如logical(逻辑型)、numeric(数值型)、character
(字符型)、factor(因子)。
函数read.table()还拥有许多微调数据导入方式的追加选项。更多详情,请参阅
help(read.table)。
注意 本章中的许多示例都是从用户计算机上已经存在的文件中导入数据。R也提供了若干种
通过连接(connection)来访问数据的机制。例如,函数file()、gzfile()、bzfile()、
xzfile()、unz()和url()可作为文件名参数使用。函数file()允许用户访问文件、剪
贴板和C级别的标准输入。函数gzfile()、bzfile()、xzfile()和unz()允许用户读
取压缩文件。函数url()能够让你通过一个含有http://、ftp://或file://的完整URL
访问网络上的文件,还可以为HTTP和FTP连接指定代理。为了方便,(用""围住的)完
整的URL也经常直接用来代替文件名使用。更多详情,参见help(file)。
2.3.3 导入Excel数据
读取一个Excel文件的最好方式,就是在Excel中将其导出为一个逗号分隔文件(csv),并使
用前文描述的方式将其导入R中。在Windows系统中,你也可以使用RODBC包来访问Excel文件。
电子表格的第一行应当包含变量/列的名称。
首先,下载并安装RODBC包。
install.packages("RODBC")
你可以使用以下代码导入数据:
library(RODBC)
channel <- odbcConnectExcel("myfile.xls")
mydataframe <- sqlFetch(channel, "mysheet")
odbcClose(channel)
这里的myfile.xls是一个Excel文件,mysheet是要从这个工作簿中读取工作表的名称,
channel是一个由odbcConnectExcel()返回的RODBC连接对象,mydataframe是返回的数据
框。RODBC也可用于从Microsoft Access导入数据。更多详情,参见help(RODBC)。
Excel 2007使用了一种名为XLSX的文件格式,实质上是多个XML文件组成的压缩包。xlsx
包可以用来读取这种格式的电子表格。在第一次使用此包之前请务必先下载并安装好。包中的函
数read.xlsx()可将XLSX文件中的工作表导入为一个数据框。其最简单的调用格式是
read.xlsx(file, n),其中file是Excel 2007工作簿的所在路径,n则为要导入的工作表序号。
举例说明,在Windows上,以下代码:
library(xlsx)
workbook <- "c:/myworkbook.xlsx"
mydataframe <- read.xlsx(workbook, 1)
从位于C盘根目录的工作簿myworkbook.xlsx中导入了第一个工作表,并将其保存为一个数据
框mydataframe。xlsx包不仅仅可以导入数据表,它还能够创建和操作XLSX文件。那些需要为
R和Excel开发接口的程序员应当研究一下这个较新的包。
2.3.4 导入XML数据
以XML格式编码的数据正在逐渐增多。R中有若干用于处理XML文件的包。例如,由Duncan
Temple Lang编写的XML包允许用户读取、写入和操作XML文件。XML格式本身已经超出了本书
的范围。对使用R存取XML文档感兴趣的读者可以参阅www.omegahat.org/RSXML,从中可以找
到若干份优秀的软件包文档。
2.3.5 从网页抓取数据
在Web数据抓取(Webscraping)的过程中,用户从互联网上提取嵌入在网页中的信息,并将
其保存为R中的数据结构以做进一步的分析。完成这个任务的一种途径是使用函数readLines()
下载网页,然后使用如grep()和gsub()一类的函数处理它。对于结构复杂的网页,可以使用
RCurl包和XML包来提取其中想要的信息。更多信息和示例,请参考可在网站Programming with R
(www.programmingr.com)上找到的“Webscraping using readLines and RCurl”一文。
2.3.6 导入SPSS数据
SPSS数据集可以通过foreign包中的函数read.spss()导入到R中,也可以使用Hmisc包中
的spss.get()函数。函数spss.get()是对read. spss()的一个封装,它可以为你自动设置
后者的许多参数,让整个转换过程更加简单一致,最后得到数据分析人员所期望的结果。
首先,下载并安装Hmisc包(foreign包已被默认安装):
install.packages("Hmisc")
然后使用以下代码导入数据:
library(Hmisc)
mydataframe <- spss.get("mydata.sav", use.value.labels=TRUE)
这段代码中,mydata.sav是要导入的SPSS数据文件,use.value.labels=TRUE表示让函数将
带有值标签的变量导入为R中水平对应相同的因子,mydataframe是导入后的R数据框。
2.3.7 导入SAS数据
R中设计了若干用来导入SAS数据集的函数,包括foreign包中的read.ssd()和Hmisc包中
的sas.get()。遗憾的是,如果使用的是SAS的较新版本(SAS 9.1或更高版本),你很可能会发
现这些函数并不能正常工作,因为R尚未跟进SAS对文件结构的改动。个人推荐两种解决方案。
你可以在SAS中使用PROC EXPORT将SAS数据集保存为一个逗号分隔的文本文件,并使用
2.3.2节中叙述的方法将导出的文件读取到R中。下面是一个示例:
SAS 程序:
proc export data=http://www.mamicode.com/mydata
outfile="mydata.csv"
dbms=csv;
run;
R程序:
mydata <- read.table("mydata.csv", header=TRUE, sep=",")
另外,一款名为Stat/Transfer的商业软件(在2.3.12节介绍)可以完好地将SAS数据集(包括
任何已知的变量格式)保存为R数据框。
2.3.8 导入Stata数据
要将Stata数据导入R中非常简单直接。所需代码类似于:
library(foreign)
mydataframe <- read.dta("mydata.dta")
这里,mydata.dta是Stata数据集,mydataframe是返回的R数据框。
2.3.9 导入netCDF数据
Unidata项目主导的开源软件库netCDF(network Common Data Form,网络通用数据格式)定
义了一种机器无关的数据格式,可用于创建和分发面向数组的科学数据。netCDF格式通常用来存
储地球物理数据。ncdf包和ncdf4包为netCDF文件提供了高层的R接口。
ncdf包为通过Unidata的netCDF库(版本3或更早)创建的数据文件提供了支持,而且在
Windows、Mac OS X和Linux上均可使用。ncdf4包支持netCDF 4或更早的版本,但在Windows
上尚不可用。
考虑如下代码:
library(ncdf)
nc <- nc_open("mynetCDFfile")
myarray <- get.var.ncdf(nc, myvar)
在本例中,对于包含在netCDF文件mynetCDFfile中的变量myvar,其所有数据都被读取并保
存到了一个名为myarray的R数组中。
值得注意的是,ncdf包和ncdf4包最近进行了重大升级,使用方式可能与旧版本不同。另外,
这两个包中的函数名称也不同。请阅读在线文档以了解详情。
2.3.10 导入HDF5 数据
HDF5(Hierarchical Data Format,分层数据格式)是一套用于管理超大型和结构极端复杂数
据集的软件技术方案。hdf5包能够以那些理解HDF5格式的软件可以读取的格式,将R对象写入
到一个文件中。这些文件可以在之后被读回R中。这个包是实验性质的,并假设用户已经安装了
HDF5库(1.2版或更高)。目前,R对于HDF5格式的支持非常有限。
2.3.11 访问数据库管理系统
R中有多种面向关系型数据库管理系统(DBMS)的接口,包括Microsoft SQL Server、Microsoft
Access、MySQL、Oracle、PostgreSQL、DB2、Sybase、Teradata以及SQLite。其中一些包通过原
生的数据库驱动来提供访问功能,另一些则是通过ODBC或JDBC来实现访问的。使用R来访问存
储在外部数据库中的数据是一种分析大数据集的有效手段(参见附录G),并且能够发挥SQL和R
各自的优势。
1. ODBC接口
在R中通过RODBC包访问一个数据库也许是最流行的方式,这种方式允许R连接到任意一种
拥有ODBC驱动的数据库,其实几乎就是市面上的所有数据库。
第一步是针对你的系统和数据库类型安装和配置合适的ODBC驱动——它们并不是R的一部
分。如果你的机器尚未安装必要的驱动,上网搜索一下应该就可以找到。
针对选择的数据库安装并配置好驱动后, 请安装RODBC 包。你可以使用命令
install.packages("RODBC")来安装它。
RODBC包中的主要函数列于表2-2中。
表2-2 RODBC中的函数
函 数 描 述
odbcConnect(dsn,uid="",pwd="") 建立一个到ODBC数据库的连接
sqlFetch(channel,sqltable) 读取ODBC数据库中的某个表到一个数据框中
sqlQuery(channel,query) 向ODBC数据库提交一个查询并返回结果
sqlSave(channel,mydf,tablename=sqtable,append=FALSE) 将数据框写入或更新(append=TRUE)到ODBC数据库的某个表中
sqlDrop(channel,sqtable) 删除ODBC数据库中的某个表
close(channel) 关闭连接
RODBC包允许R和一个通过ODBC连接的SQL数据库之间进行双向通信。这就意味着你不仅可
以读取数据库中的数据到R中,同时也可以使用R修改数据库中的内容。假设你想将某个数据库
中的两个表(Crime和Punishment)分别导入为R中的两个名为crimedat和pundat的数据框,
可以通过如下代码完成这个任务:
library(RODBC)
myconn <- odbcConnect("mydsn", uid="Rob", pwd="aardvark")
crimedat <- sqlFetch (myconn, Crime)
pundat <- sqlQuery(myconn, "select * from Punishment")
close(myconn)
这里首先载入了RODBC包,并通过一个已注册的数据源名称(mydsn)和用户名(rob)以
及密码(aardvark)打开了一个ODBC数据库连接。连接字符串被传递给sqlFetch,它将Crime
表复制到R数据框crimedat中。然后我们对Punishment表执行了SQL语句select并将结果保
存到数据框pundat中。最后,我们关闭了连接。
函数sqlQuery()非常强大,因为其中可以插入任意的有效SQL语句。这种灵活性赋予了你
选择指定变量、对数据取子集、创建新变量,以及重编码和重命名现有变量的能力。
2. DBI相关包
DBI包为访问数据库提供了一个通用且一致的客户端接口。构建于这个框架之上的RJDBC包
提供了通过JDBC驱动访问数据库的方案。使用时请确保安装了针对你的系统和数据库的必要
JDBC驱动。其他有用的、基于DBI的包有RMySQL、ROracle、RPostgreSQL和RSQLite。这些
包都为对应的数据库提供了原生的数据库驱动,但可能不是在所有系统上都可用。详情请参阅
CRAN(http://cran.r-project.org)上的相应文档。
2.3.12 通过Stat/Transfer导入数据
在我们结束数据导入的讨论之前,值得提到一款能让上述任务的难度显著降低的商业软件。
Stat/Transfer(www.stattransfer.com)是一款可在34种数据格式之间作转换的独立应用程序,其中
包括R中的数据格式(见图2-4)。
2.4 数据集的标注
为了使结果更易解读,数据分析人员通常会对数据集进行标注。通常这种标注包括为变量名
添加描述性的标签,以及为类别型变量中的编码添加值标签。例如,对于变量age,你可能想附
加一个描述更详细的标签“Age at hospitalization (in years)”(入院年龄)。对于编码为1或2的性别
变量gender,你可能想将其关联到标签“male”和“female”上。
2.4.1 变量标签
遗憾的是,R处理变量标签的能力有限。一种解决方法是将变量标签作为变量名,然后通过
位置下标来访问这个变量。考虑之前病例数据框的例子。名为age的第二列包含着个体首次入院
时的年龄。代码:
names(patientdata)[2] <- "Age at hospitalization (in years)"
将age重命名为"Age at hospitalization (in years)"。很明显,新的变量名太长,不适
合重复输入。作为替代,你可以使用patientdata[2]来引用这个变量,而在本应输出age的地
方输出字符串"Age at hospitalization (in years)"。很显然,这个方法并不理想,如果
你能尝试想出更好的命名(例如,admissionAge)可能会更好一点。
2.4.2 值标签
函数factor()可为类别型变量创建值标签。继续上例,假设你有一个名为gender的变量,
其中1表示男性,2表示女性。你可以使用代码:
patientdata$gender <- factor(patientdata$gender,
levels=c(1,2),
labels=c("male", "female")
)
来创建值标签。这里levels代表变量的实际值,而labels表示包含了理想值标签的字符型向量。
2.5 处理数据对象的实用函数
在本章末尾,我们来简要总结一下实用的数据对象处理函数(参见表2-3)。
表2-3 处理数据对象的实用函数
函 数 用 途
length(object) 显示对象中元素/成分的数量
dim(object) 显示某个对象的维度
str(object) 显示某个对象的结构
class(object) 显示某个对象的类或类型
mode(object) 显示某个对象的模式
names(object) 显示某对象中各成分的名称
c(object, object,…) 将对象合并入一个向量
cbind(object, object, …) 按列合并对象
rbind(object, object, …) 按行合并对象
Object 输出某个对象
head(object) 列出某个对象的开始部分
tail(object) 列出某个对象的最后部分
ls() 显示当前的对象列表
rm(object, object, …) 删除一个或更多个对象。语句rm(list = ls())
将删除当前工作环境中的几乎所有对象*
newobject <- edit(object) 编辑对象并另存为newobject
fix(object) 直接编辑对象
*以句点.开头的隐藏对象将不受影响。——译者注
我们已经讨论过其中的大部分函数。函数head()和tail()对于快速浏览大数据集的结构非
常有用。例如,head(patientdata)将列出数据框的前六行,而tail(patientdata)将列出
最后六行。我们将在下一章中介绍length()、cbind()和rbind()等函数。我们将其汇总于此,
仅作参考。
2.6 小结
数据的准备可能是数据分析中最具挑战性的任务之一。我们在本章中概述了R中用于存储数
据的多种数据结构,以及从键盘和外部来源导入数据的许多可能方式,这是一个不错的起点。特
别是,我们将在后续各章中反复地使用向量、矩阵、数据框和列表的概念。掌握通过括号表达式
选取元素的能力,对数据的选择、取子集和变换将是非常重要的。
如你所见,R提供了丰富的函数用以访问外部数据,包括普通文本文件、网页、统计软件、
电子表格和数据库的数据。虽然本章的焦点是将数据导入到R中,你同样也可以将数据从R导出
为这些外部格式。数据的导出在附录C中论及,处理大数据集(GB级到TB级)的方法留待附录G
中讨论。
将数据集读入R之后,你很有可能需要将其转化为一种更有助于分析的格式(事实上,我发
现处理数据的紧迫感有助于促进学习)。在第4章,我们将会探索创建新变量、变换和重编码已有
变量、合并数据集和选择观测的方法。
但在转而探讨数据管理之前,让我们先花些时间在R的绘图上。因为许多读者都是因为对R
绘图怀有强烈的兴趣而开始学习R的,为了不让你们再久等,在下一章我们将直接讨论图形的创
建。我们关注的重点是管理和定制图形的通用方法,它们在本书余下章节都会用到。
数据的输入