如何直接将Excel文件读入R?还是应该先将数据导出为文本或CSV文件,然后再将该文件导入到R中?
让我重申一下@Chase的建议:使用XLConnect。
我认为使用XLConnect的原因有:
与其他解决方案相比,XLConnect相对较新,因此在博客文章和参考文档中提及的频率较低。对我来说它非常有用。
现在有了readxl:
readxl包使得从Excel中获取数据并导入到R变得更加容易。与现有的包(例如gdata、xlsx、xlsReadWrite等)相比,readxl没有外部依赖,因此可以在所有操作系统上轻松安装和使用。它被设计用于处理存储在单个工作表中的表格数据。
readxl是基于libxls C库构建的,该库抽象了底层二进制格式的许多复杂性。
它支持传统的.xls格式和.xlsx格式。
readxl可从CRAN获取,或者你可以使用以下命令从github安装:
# install.packages("devtools")
devtools::install_github("hadley/readxl")
使用方法
library(readxl)
# read_excel reads both xls and xlsx files
read_excel("my-old-spreadsheet.xls")
read_excel("my-new-spreadsheet.xlsx")
# Specify sheet with a number or name
read_excel("my-spreadsheet.xls", sheet = "data")
read_excel("my-spreadsheet.xls", sheet = 2)
# If NAs are represented by something other than blank cells,
# set the na argument
read_excel("my-spreadsheet.xls", na = "NA")
请注意,尽管描述中说“没有外部依赖项”,但它确实需要Rcpp
包,该包又需要Rtools(适用于Windows)或Xcode(适用于OSX),这些是R之外的外部依赖项。虽然许多人出于其他原因已经安装了它们。
read_excel
将字符串读取为因子?我喜欢它相对于read.xlsx
的速度,但是需要手动将列从字符转换为因子,这样做就失去了意义。 - coip是的。请参考R百科相关页面:http://en.wikibooks.org/wiki/R_Programming/Importing_and_exporting_data#Excel_.28xls.2Cxlsx.29。简而言之,gdata
包中的read.xls
通常可行(尽管您需要在系统上安装Perl - 在MacOS和Linux上通常已经存在,但在Windows上需要额外步骤,例如参见http://strawberryperl.com/)。 R百科页面列出了各种注意事项和替代方案。
我唯一看到不直接这样做的原因是您可能希望检查电子表格以查看其是否存在问题(奇怪的标题、多个工作表[每次只能读取一个,虽然您可以循环遍历它们所有]、包含绘图等)。但对于格式良好、矩形的电子表格,其中只有普通数字和字符数据(即没有逗号格式化的数字、日期、除零错误的公式、缺失值等),我通常使用此方法没有问题。
na.strings="-"
可以解决这个问题吗?这些问题中有多少是通用的,而另外一些问题(例如带逗号的数字字段)可以通过其他工具(如XLConnect)来解决...? - Ben Bolkerread.xls
成功读取了一个非常大的 Excel 文件中的工作表,而 XLConnect
和 xlsx
都失败了(我相信这是因为它们都依赖于 Apache POI)。 - Matt Parker编辑于2015年10月:正如其他人在这里评论的,openxlsx
和readxl
包比xlsx
包快得多,并且实际上能够打开更大的 Excel 文件(>1500行和>120列) 。@MichaelChirico演示了当速度更重要时,readxl
更好,而openxlsx
替换了xlsx
包提供的功能。如果您正在寻找2015年读取、写入和修改Excel文件的软件包,请选择openxlsx
而不是xlsx
。
2015年之前:我使用了xlsx
包。它改变了我的Excel和R的工作流程。再也没有烦人的弹出窗口询问我是否确定要将Excel表格保存为.txt格式。该软件包还可以编写Excel文件。
但是,我发现当打开大型Excel文件时,read.xlsx
函数很慢。read.xlsx2
函数要快得多,但不能猜测数据框列的向量类别。如果您使用read.xlsx2
函数,则必须使用colClasses
命令来指定所需的列类别。以下是一个实用示例:
read.xlsx("filename.xlsx", 1)
读取文件并使数据框列类别几乎有用,但对于大型数据集非常慢。也适用于.xls
文件。
read.xlsx2("filename.xlsx", 1)
更快,但您必须手动定义列类别。一种快捷方式是运行该命令两次(请参见下面的示例)。character
规范将您的列转换为因子。使用Date
和POSIXct
选项进行时间处理。
coln <- function(x){y <- rbind(seq(1,ncol(x))); colnames(y) <- colnames(x)
rownames(y) <- "col.number"; return(y)} # A function to see column numbers
data <- read.xlsx2("filename.xlsx", 1) # Open the file
coln(data) # Check the column numbers you want to have as factors
x <- 3 # Say you want columns 1-3 as factors, the rest numeric
data <- read.xlsx2("filename.xlsx", 1, colClasses= c(rep("character", x),
rep("numeric", ncol(data)-x+1)))
考虑到在 R
中读取 Excel 文件的不同方式以及这里提到的大量答案,我想尝试一下阐明哪些选项在几种简单情况下表现最佳。
我自己从开始使用 R
起就一直在使用 xlsx
,主要是出于惯性,近期我注意到似乎没有任何关于哪个包更好的客观信息。
任何基准测试都充满了困难,因为某些软件包肯定会比其他软件包处理某些情况更好,还有一系列其他注意事项。
话虽如此,我使用一个(可再现的)数据集,我认为它是以相当常见的格式(8个字符串字段、3个数字、1个整数、3个日期)呈现的:
set.seed(51423)
data.frame(
str1 = sample(sprintf("%010d", 1:NN)), #ID field 1
str2 = sample(sprintf("%09d", 1:NN)), #ID field 2
#varying length string field--think names/addresses, etc.
str3 =
replicate(NN, paste0(sample(LETTERS, sample(10:30, 1L), TRUE),
collapse = "")),
#factor-like string field with 50 "levels"
str4 = sprintf("%05d", sample(sample(1e5, 50L), NN, TRUE)),
#factor-like string field with 17 levels, varying length
str5 =
sample(replicate(17L, paste0(sample(LETTERS, sample(15:25, 1L), TRUE),
collapse = "")), NN, TRUE),
#lognormally distributed numeric
num1 = round(exp(rnorm(NN, mean = 6.5, sd = 1.5)), 2L),
#3 binary strings
str6 = sample(c("Y","N"), NN, TRUE),
str7 = sample(c("M","F"), NN, TRUE),
str8 = sample(c("B","W"), NN, TRUE),
#right-skewed integer
int1 = ceiling(rexp(NN)),
#dates by month
dat1 =
sample(seq(from = as.Date("2005-12-31"),
to = as.Date("2015-12-31"), by = "month"),
NN, TRUE),
dat2 =
sample(seq(from = as.Date("2005-12-31"),
to = as.Date("2015-12-31"), by = "month"),
NN, TRUE),
num2 = round(exp(rnorm(NN, mean = 6, sd = 1.5)), 2L),
#date by day
dat3 =
sample(seq(from = as.Date("2015-06-01"),
to = as.Date("2015-07-15"), by = "day"),
NN, TRUE),
#lognormal numeric that can be positive or negative
num3 =
(-1) ^ sample(2, NN, TRUE) * round(exp(rnorm(NN, mean = 6, sd = 1.5)), 2L)
)
我将数据写入csv文件,然后在LibreOffice中打开并保存为.xlsx文件,接着对这篇帖子中提到的4个包:xlsx
, openxlsx
, readxl
和gdata
进行基准测试(使用默认选项;我还尝试了一种不指定列类型的版本,但这没有改变排名)。
由于我使用Linux系统,因此排除了RODBC
;XLConnect
似乎主要用于导入整个Excel工作簿,而不是读取单个Excel表格,因此仅考虑其读取能力似乎有失公正;xlsReadWrite
无法与我的R
版本兼容,似乎已经逐渐淘汰。
然后我使用NN=1000L
和NN=25000L
(在每次声明上述data.frame
之前重置种子)进行基准测试,以考虑Excel文件大小的影响。 gc
主要用于xlsx
包,因为我发现有时会出现内存问题。以下是我得到的结果:
benchmark1k <-
microbenchmark(times = 100L,
xlsx = {xlsx::read.xlsx2(fl, sheetIndex=1); invisible(gc())},
openxlsx = {openxlsx::read.xlsx(fl); invisible(gc())},
readxl = {readxl::read_excel(fl); invisible(gc())},
gdata = {gdata::read.xls(fl); invisible(gc())})
# Unit: milliseconds
# expr min lq mean median uq max neval
# xlsx 194.1958 199.2662 214.1512 201.9063 212.7563 354.0327 100
# openxlsx 142.2074 142.9028 151.9127 143.7239 148.0940 255.0124 100
# readxl 122.0238 122.8448 132.4021 123.6964 130.2881 214.5138 100
# gdata 2004.4745 2042.0732 2087.8724 2062.5259 2116.7795 2425.6345 100
所以readxl
是胜者,openxlsx
有竞争力而gdata
则明显失败。相对于列最小值进行每项测量:
# expr min lq mean median uq max
# 1 xlsx 1.59 1.62 1.62 1.63 1.63 1.65
# 2 openxlsx 1.17 1.16 1.15 1.16 1.14 1.19
# 3 readxl 1.00 1.00 1.00 1.00 1.00 1.00
# 4 gdata 16.43 16.62 15.77 16.67 16.25 11.31
我们看到我个人最喜欢的xlsx
比readxl
慢了60%。
由于所需时间较长,因此我只在较大的文件上进行了20次重复,否则命令相同。以下是原始数据:
# Unit: milliseconds
# expr min lq mean median uq max neval
# xlsx 4451.9553 4539.4599 4738.6366 4762.1768 4941.2331 5091.0057 20
# openxlsx 962.1579 981.0613 988.5006 986.1091 992.6017 1040.4158 20
# readxl 341.0006 344.8904 347.0779 346.4518 348.9273 360.1808 20
# gdata 43860.4013 44375.6340 44848.7797 44991.2208 45251.4441 45652.0826 20
这里是相关数据:
# expr min lq mean median uq max
# 1 xlsx 13.06 13.16 13.65 13.75 14.16 14.13
# 2 openxlsx 2.82 2.84 2.85 2.85 2.84 2.89
# 3 readxl 1.00 1.00 1.00 1.00 1.00 1.00
# 4 gdata 128.62 128.67 129.22 129.86 129.69 126.75
因此,readxl
在速度方面是明显的赢家。gdata
最好还有其他优点,因为它读取Excel文件的速度非常慢,对于较大的表格这个问题只会更加严重。
openxlsx
的两个优势是:1)它的其他方法非常丰富(readxl
仅设计了做一件事情,这也可能是它如此快的部分原因),特别是其write.xlsx
函数;2)(对于readxl
来说更像是一个缺点)readxl
中的col_types
参数目前仅接受一些非标准的R
:"text"
而不是"character"
和"date"
而不是"Date"
。
XLConnect
进行了一些测试,但它非常慢;我相信 readxl
的缺点在我的最后一段已经足够涵盖了;而且我对于 xlsx
或 openxlsx
没有类似于你的经验,因为我经常使用两者来指定类型。 - MichaelChirico我使用XLConnect
取得了不错的运气:http://cran.r-project.org/web/packages/XLConnect/index.html
library(RODBC)
file.name <- "file.xls"
sheet.name <- "Sheet Name"
## Connect to Excel File Pull and Format Data
excel.connect <- odbcConnectExcel(file.name)
dat <- sqlFetch(excel.connect, sheet.name, na.strings=c("","-"))
odbcClose(excel.connect)
个人而言,我喜欢RODBC并且可以推荐它。
openxlsx
包,它的表现非常好(而且运行速度很快)。
http://cran.r-project.org/web/packages/openxlsx/index.html
xlsReadWrite
包,它不需要额外的安装,但在第一次使用前需要下载额外的 shlib。require(xlsReadWrite)
xls.getshlib()
xlsx
软件包可以处理相同名称的扩展名。在 @Mikko 提供的答案基础上,您可以使用一个巧妙的技巧来加速操作,而不必提前“知道”列类。只需使用 read.xlsx
获取有限数量的记录以确定类别,然后再使用 read.xlsx2
进行跟进。
示例
# just the first 50 rows should do...
df.temp <- read.xlsx("filename.xlsx", 1, startRow=1, endRow=50)
df.real <- read.xlsx2("filename.xlsx", 1,
colClasses=as.vector(sapply(df.temp, mode)))
numeric
类型的 factors
。read.xlsx
函数使用 character
来指定 factors 的读取列。我相信有更优雅的方法将 factors 作为字符获取,但这里是一个修改过的函数版本:df.real <- read.xlsx2("filename.xlsx", 1, colClasses=gsub("factor", "character", as.vector(sapply(df.temp, class))))
。 - Mikko
gdata
版本 2.8.2 可以使用read.xls
函数读取xlsx
文件。 - Benxlsx
包用于处理xlsx/xlsm/xls格式的文件,但不支持xlam等其他格式。 - Qbik