直接从R脚本读取Excel文件


95

如何将Excel文件直接读入R?还是应该首先将数据导出到文本或CSV文件,然后将该文件导入R?


@Sacha Epskamp:使用xlsReadWrite,您甚至不需要安装Perl。
Joris Meys 2011年

1
gdata版本2.8.2读取xlsx具有以下read.xls功能的文件
2012年

1
如果您将数据从Excel导出为文本格式,请参阅我的警告(以下为答案),以防止精度下降。
russellpierce 2014年

1
xlsx打包XLSX / XLSM / XLS,不知道xlam等
Qbik

2
“我从未见过不首先导出到文本文件的原因”。怎么样:当我导出为CSV时,不需要的字段之一没有写好。看起来像某种DRM,但由于我没有编写电子表格,所以我不知道。
Nate Reed

Answers:


41

是。请参阅R Wiki上的相关页面。简短的答案:大多数情况下read.xls,该gdata软件包都有效(尽管您需要在系统上安装Perl-通常已在MacOS和Linux上安装了Perl,但在Windows上则需要采取额外的措施,例如,请参见http://strawberryperl.com/)。R Wiki页面上列出了各种警告和替代方法。

我不直接执行此操作的唯一原因是,您可能需要检查电子表格以查看其是否存在故障(怪异的标题,多个工作表[您一次只能读取一个,尽管您显然可以遍历全部) ,包括地块等)。但是对于格式完整的矩形电子表格,其中包含纯数字和字符数据(即,非逗号格式的数字,日期,具有零除错误的公式,缺少值等)..我通常没有问题这个过程。


6
我个人碰到过很多潜在的问题。带有逗号的数字字段必须在R中剥离并转换为数字。带有“-”的字段需要重新编码为NA。总体建议是真正看在Excel中你的号码,并确保它们被正确地翻译成河
布兰登贝特尔森

3
不能与“您确实需要查看您的数字”争论……“-”字段有什么问题?不na.strings="-"解决这个问题?这些问题中有多少是通用的,可以使用其他工具(例如XLConnect ...)解决其中的哪些问题(例如带逗号的数字字段)?
本·博克

1
该评论是针对OP,而不是针对您Ben,我的错是我的错。
布兰登·贝特尔森

1
相关轶事:read.xls成功地从Excel文件中读取了一个很大的表格,但XLConnect同时xlsx失败了(我相信是因为它们都依赖于Apache POI
Matt Parker

49

让我重申@Chase的建议:使用XLConnect

我认为使用XLConnect的原因是:

  1. 跨平台。XLConnect用Java编写,因此可以在Win,Linux和Mac上运行,而无需更改R代码(可能的路径字符串除外)
  2. 没有什么可加载的了。只需安装XLConnect,即可继续生活。
  3. 您仅提到读取Excel文件,但是XLConnect还将写入Excel文件,包括更改单元格格式。而且它将从Linux或Mac(不仅仅是Win)做到这一点。

与其他解决方案相比,XLConnect有点新,因此在博客文章和参考文档中很少提及。对我来说,这非常有用。


48

现在有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的外部依赖项。 。


3
比xlsx快得多。读取时间类似于read.xlsx2,但是可以推断类型。
史蒂夫·罗

1
@SteveRowe看到了一些(尝试过的)客观基准的新答案,证实了这一点
MichaelChirico

有没有一种方法可以读取字符串作为因素read_excel?与相比read.xlsx,我比较喜欢速度,但是必须手动将列从字符转换为因子会达到目的。
coip

2
+1,因为它没有依赖性。我讨厌必须安装Java。我已经尝试过了,对我来说效果很好。
巴斯蒂安2015年

2
readxl和openxlsx是最好的。readxl速度更快,但不允许写入。无论如何,当尝试指定列类/类型时,它们都不能很好地工作。
skan,2015年

29

EDIT 2015年10月:正如其他人在这里评论的,openxlsxreadxl软件包比xlsx软件包要快得多,实际上可以打开更大的Excel文件(> 1500行和> 120列)。@MichaelChirico演示了readxl首选速度时更好的方法,并openxlsx替换了xlsx软件包提供的功能。如果您正在寻找2015年用于读取,写入和修改Excel文件的软件包,请选择openxlsx而不是xlsx

2015年之前:我已使用xlsxpackage。它使用Excel和R改变了我的工作流程。不再烦人的弹出式窗口询问我是否确定要以.txt格式保存Excel工作表。该软件包还写入Excel文件。

但是,read.xlsx打开大型Excel文件时,我发现功能很慢。read.xlsx2函数的速度要快得多,但不会查询data.frame列的向量类。colClasses如果使用read.xlsx2函数,则必须使用命令指定所需的列类。这是一个实际的例子:

read.xlsx("filename.xlsx", 1)读取文件并使data.frame列类几乎有用,但是对于大型数据集来说非常慢。也适用于.xls文件。

read.xlsx2("filename.xlsx", 1)速度更快,但是您必须手动定义列类。一种快捷方式是两次运行该命令(请参见下面的示例)。character规范会将您的列转换为因子。时间的使用DatePOSIXct选项。

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)))

25

鉴于读取Excel文件的不同方式的泛滥以及R此处的答案过多,我想我将尝试阐明此处提到的哪些选项在某些情况下效果最佳。

xlsx自从我开始使用以来,我自己一直在使用R惯性(如果没有其他问题的话),而且我最近注意到似乎没有客观的信息来说明哪个程序包效果更好。

任何基准测试活动都充满困难,因为某些程序包肯定会在某些情况下比其他程序更好地处理,还有其他警告。

就是说,我使用的是(可复制的)数据集,我认为它是一种非常常见的格式(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: ,xlsxopenxlsxreadxlgdata,使用默认选项(我也试过一个版本是否不是我指定列类型,但这不会改变排名)。

我被排除在外RODBC是因为我在Linux上。XLConnect因为它的主要目的不是在单个Excel工作表中阅读而是在导入整个Excel工作簿,所以仅凭其阅读能力来竞争就显得不公平;并且xlsReadWrite因为它不再与我的版本兼容R(似乎已被淘汰)。

然后,我使用NN=1000L和运行基准测试NN=25000L(在data.frame上述每次声明之前重置种子),以允许在Excel文件大小方面有所差异。gc主要用于xlsx,我有时发现它会创建内存阻塞。事不宜迟,这是我发现的结果:

1,000行Excel文件

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的赢家也是如此。采取相对于列最小值的每个度量:openxlsxgdata

#       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比慢60%readxl

25,000行Excel文件

由于花费的时间,我只对较大的文件重复了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.xlsx2个功能,和)(更多的缺点readxl)的col_types在参数readxl只(如(撰写本文时)接受一些非标准的R"text"代替"character""date"代替"Date"


如果您还添加了XLConnect基准,那就太好了。还评论说readxl它不能写。xlsx和openxlsx与col_types或colClasses选项无法正常工作。
skan 2015年

@skan我最初使用进行了一些测试,XLConnect但速度非常慢;我认为readxl我的最后一段已充分涵盖了缺点。并且我没有使用xlsxopenxlsx经常使用两者来指定类型的经验。
MichaelChirico 2015年


13
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并且可以推荐它。


7
警告:ODBC有时可能难以在Windows以外的平台上运行。
JD

1
@JD Long,甚至在Windows上也是PITA。对于我和在64位W7上的ODBC来说,我没有任何性感的时光
RomanLuštrik2011年

4
加载所需的软件包:odbcConnectExcel(file.name)中的RODBC错误:odbcConnectExcel仅适用于32位Windows
andrekos


6

另一个解决方案是xlsReadWrite软件包,该软件包不需要额外的安装,但是需要您在首次使用它之前下载其他shlib,方法是:

require(xlsReadWrite)
xls.getshlib()

忘记这一点可能会导致完全沮丧。去过那里...

旁注:您可能要考虑转换为基于文本的格式(例如csv)并从那里读入。这有很多原因:

  • 无论您采用哪种解决方案(RODBC,gdata,xlsReadWrite),在转换数据时都可能会发生一些奇怪的事情。特别是日期可能非常麻烦。该HFWutils软件包提供了一些处理EXCEL日期的工具(根据@Ben Bolker的评论)。

  • 如果您的工作表很大,则读取文本文件要比从EXCEL读取数据快。

  • 对于.xls和.xlsx文件,可能需要不同的解决方案。EG xlsReadWrite软件包当前不支持.xlsx AFAIK。gdata要求您安装其他Perl库以支持.xlsx。xlsx软件包可以处理相同名称的扩展名。


@Ben Thx作为提示,我将其包含在答案中。但是,我并未尝试完成,因为接受答案的链接的Wiki页面已经相当完整。但是它没有提到HFWutils软件包。
Joris Meys 2011年

1
-1; 看我的答案。TL:DR:Excel不会将全精度数据集保存到csv(或剪贴板)。仅保留可见值。
russellpierce 2014年

5

如上所述,在许多其他答案中,有很多不错的程序包可以连接到XLS / X文件并以合理的方式获取数据。但是,应警告您,在任何情况下都不应使用剪贴板(或.csv)文件从Excel中检索数据。要了解原因,请=1/3在excel中输入单元格。现在,将您可以看到的小数点数量减少到两个。然后将数据复制并粘贴到R中。现在保存CSV。您会注意到,在两种情况下,Excel都仅保留了通过界面对您可见的数据的帮助,并且您已经失去了实际源数据中的所有精度。


1
我很想知道谁认为数字保真度不重要/不重要。
russellpierce 2015年

1
好警告。但是,这取决于您使用的软件包。有些没有落入这个陷阱。
RockScience

@RocketScience这是Excel导出CSV时的基本设计选择。您是否有一个使用剪贴板的软件包示例,但没有出现此问题?直接解析xls xlsx文件的软件包很容易不属于该陷阱。因此,我的警告的具体范围。
russellpierce

在Unix上您可以尝试gnumeric::read.gnumeric.sheet。在Windows上,我不确定100%,但我认为gdata::read.xls也应该能很好地工作(尽管需要安装perl)
RockScience

@RockScience恭喜,gdata :: read.xls不能对剪贴板数据进行操作(除非您不加理会),并且gnumeric不是Excel。因此,没有特别的证据,我的警告仍然有效。对于这个问题,还有很多其他好的选择-希望人们改用这些选择。
russellpierce

5

通过扩展@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)))

1
您的解决方案返回numericfactors我的电脑上。read.xlsx使用characterreadColumns函数指定的因素。我敢肯定,有一种更优雅的方式来获取因子作为字符,但这是您的函数的修改版本,可以正常使用:df.real <- read.xlsx2("filename.xlsx", 1, colClasses=gsub("factor", "character", as.vector(sapply(df.temp, class))))
米科2015年

这仅在第一行可以充分确定列类型的范围内起作用。通常,解析要比第一行多进行确定。通过命名这些函数来自的软件包,可以改善答案以解决aaa90210的评论。
russellpierce

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.