直接从R脚本读取Excel文件

waa*_*ers 93 excel r r-faq

如何将Excel文件直接读入R?或者我应该首先将数据导出到文本或CSV文件并将该文件导入R?

JD *_*ong 48

让我重申@Chase推荐的内容:使用XLConnect.

在我看来,使用XLConnect的原因是:

  1. 跨平台.XLConnect是用Java编写的,因此可以在Win,Linux,Mac上运行而不需要更改R代码(可能的路径字符串除外)
  2. 没有其他东西可以加载.只需安装XLConnect并继续生活.
  3. 您只提到了阅读Excel文件,但XLConnect也会编写Excel文件,包括更改单元格格式.它将通过Linux或Mac实现,而不仅仅是Win.

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


Ben*_*Ben 44

现在有readxl:

readxl包使得从Excel和R中获取数据变得容易.与现有的包(例如gdata,xlsx,xlsReadWrite等)相比,readxl没有外部依赖性,因此很容易在所有操作系统上安装和使用.它旨在处理存储在单个工作表中的表格数据.

readxl构建在libxls C库之上,它反映了底层二进制格式的许多复杂性.

它支持传统的.xls格式和.xlsx

readxl可以从CRAN获得,或者你可以从github安装它:

# install.packages("devtools")
devtools::install_github("hadley/readxl")
Run Code Online (Sandbox Code Playgroud)

用法

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")
Run Code Online (Sandbox Code Playgroud)

请注意,尽管描述中描述了"没有外部依赖关系",但它确实需要Rcpp,而后者又需要Rtools(对于Windows)或Xcode(对于OSX),这些 R 之外的依赖关系.虽然许多人出于其他原因安装了它们.

  • 比xlsx快得多.读取时间与read.xlsx2类似,但它推断类型. (3认同)
  • +1表示它没有依赖关系.我讨厌必须安装java.我已经尝试过了,它对我来说效果很好. (2认同)
  • readxl 和 openxlsx 是最好的。readxl 速度更快,但不允许写入。无论如何,在尝试指定列类/类型时,它们都不能很好地工作。 (2认同)

Ben*_*ker 40

是.请参阅R维基上的相关页面.简短的回答:大部分时间read.xlsgdata包中运行(尽管你需要在你的系统上安装Perl - 在MacOS和Linux上通常都是正确的,但在Windows上需要额外的一步,即参见http://strawberryperl.com/).R维基页面上列出了各种警告和替代方案.

我看到不直接这样做的唯一原因是你可能想要检查电子表格以查看它是否有毛刺(奇怪的标题,多个工作表[你一次只能读一个,尽管你显然可以循环遍历它们] ,包括地块等).但对于格式良好的矩形电子表格,其中包含普通数字和字符数据(即,不是逗号格式的数字,日期,具有被零除错误的公式,缺失值等等.)我一般都没有问题用这个过程.

  • 我个人遇到了很多潜在的问题需要考虑.带有逗号数字的字段需要被剥离并在R中转换为数字.带" - "的字段需要重新编码为NA.总体建议是在Excel中真正查看您的数字,并确保将它们正确地转换为R. (5认同)
  • 无法争辩"你真的需要看看你的数字"......" - "字段的问题是什么?`na.strings =" - "`解决问题?这些问题中有多少是通用的,有多少问题(例如带逗号的数字字段)可以用其他工具解决,例如XLConnect ......? (2认同)

Mik*_*kko 28

编辑2015年10月:正如其他人在这里评论的那样openxlsx,readxl软件包的速度远远快于xlsx软件包,实际上可以打开更大的Excel文件(> 1500行&> 120列).@MichaelChirico演示了readxl在首选速度时更好,并openxlsx取代了xlsx软件包提供的功能.如果您正在寻找一个包,以便在2015年阅读,编写和修改Excel文件,请选择openxlsx而不是xlsx.

2015年之前:我用过xlsx包装.它用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)))
Run Code Online (Sandbox Code Playgroud)


Mic*_*ico 23

鉴于阅读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)
)
Run Code Online (Sandbox Code Playgroud)

然后我写了这为CSV和LibreOffice中打开并保存它作为一个.xlsx文件,然后基准在这个线程中提到的包的4: ,xlsx,openxlsx,readxlgdata,使用默认选项(我也试过一个版本是否不是我指定列类型,但这并没有改变排名).

我排除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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

我们看到自己最喜欢的,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
Run Code Online (Sandbox Code Playgroud)

这是相关数据:

#       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
Run Code Online (Sandbox Code Playgroud)

readxl在速度方面,明显的赢家也是如此.gdata更好地拥有其他东西,因为它在读取Excel文件时非常缓慢,而且这个问题只会在更大的表格中加剧.

两个方面openxlsx是1)其广泛的其他方法(readxl设计只做一件事,这可能是为什么它如此快速的一部分),特别是它的write.xlsx功能,2)(更多的一个缺点readxl)col_types参数readxl只是(如写这篇文章)的接受一些不规范R:"text"代替"character""date"代替的"Date".


Cha*_*ase 19

我很幸运XLConnect:http://cran.r-project.org/web/packages/XLConnect/index.html

  • 在其他SE网络中,这个答案将因仅链接而被关闭. (3认同)

Bra*_*sen 12

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)
Run Code Online (Sandbox Code Playgroud)

就个人而言,我喜欢RODBC并且可以推荐它.

  • 警告:在Windows以外的平台上运行ODBC有时会很棘手. (7认同)
  • 加载所需的包:odbcConnectExcel(file.name)中的RODBC错误:odbcConnectExcel仅适用于32位Windows (3认同)

Chr*_*ris 7

openxlsx今天就试试这个包.它工作得很好(而且很快).

http://cran.r-project.org/web/packages/openxlsx/index.html


Jor*_*eys 5

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

require(xlsReadWrite)
xls.getshlib()
Run Code Online (Sandbox Code Playgroud)

忘记这一点可能会让人感到非常沮丧.去过那里......

旁注:您可能需要考虑转换为基于文本的格式(例如csv)并从那里读入.这有以下几个原因:

  • 无论您的解决方案是什么(RODBC,gdata,xlsReadWrite),当您的数据转换时,可能会发生一些奇怪的事情.特别是日期可能相当繁琐.该HFWutils软件包有一些处理EXCEL日期的工具(根据@Ben Bolker的评论).

  • 如果您有大张纸,则读取文本文件比从EXCEL读取更快.

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


rus*_*rce 5

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


Jas*_*lns 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)))
Run Code Online (Sandbox Code Playgroud)