Прочтите файл Excel прямо из сценария R

95

Как я могу прочитать файл Excel прямо в R? Или я должен сначала экспортировать данные в текстовый или CSV-файл и импортировать этот файл в R?

вандеры
источник
@Sacha Epskamp: с xlsReadWrite вам даже не нужно устанавливать Perl.
Джорис Мейс
1
gdataверсия 2.8.2 читает xlsxфайлы с read.xlsфункцией
Бен
1
См. Мое предупреждение (как ответ ниже) относительно возможной потери точности при экспорте данных в текстовый формат из Excel.
russellpierce
1
xlsxпакет для xlsx / xlsm / xls, не знаю о xlam и т. д.
Qbik
2
«Я никогда не вижу причин не экспортировать сначала в текстовый файл». Как насчет этого: при экспорте в CSV одно из нужных мне полей не записывается. Это похоже на какую-то DRM, но так как я не писал электронную таблицу, я не знаю.
Нейт Рид,

Ответы:

41

Да. См. Соответствующую страницу в R-вики . Краткий ответ: пакет read.xlsfrom the gdatapackage работает большую часть времени (хотя в вашей системе должен быть установлен Perl - обычно это уже верно для MacOS и Linux, но требует дополнительного шага в Windows, например, см. Http://strawberryperl.com/ ). Существуют различные предостережения и альтернативы, перечисленные на вики-странице R.

Единственная причина, по которой я не вижу этого напрямую, заключается в том, что вы можете проверить электронную таблицу, чтобы увидеть, есть ли в ней сбои (странные заголовки, несколько листов [вы можете читать только по одному, хотя вы, очевидно, можете перебирать их все] , включенные участки и др.). Но для хорошо сформированной прямоугольной таблицы с простыми числами и символьными данными (т.е. числами, датами, формулами без запятых, ошибками деления на ноль, пропущенными значениями и т. Д. И т. Д.) У меня обычно нет проблем. с этим процессом.

Бен Болкер
источник
6
Есть много потенциальных проблем, с которыми я столкнулся лично. Поля с числами с запятыми необходимо удалить и преобразовать в числовые в R. Поля со знаком «-» необходимо перекодировать в NA. Общая рекомендация - внимательно посмотреть на свои числа в Excel и убедиться, что они правильно переводятся в R.
Брэндон Бертельсен
3
Не могу поспорить с «вам действительно нужно посмотреть на свои числа» ... в чем проблема с полями «-»? ли na.strings="-"решение проблемы? Сколько из этих проблем являются общими и сколько из них (например, числовые поля с запятыми) можно решить с помощью других инструментов, таких как XLConnect ...?
Бен Болкер
1
Этот комментарий был адресован OP, а не вам, Бен, я виноват в плохом размещении.
Брэндон Бертельсен
1
Соответствующий анекдот: read.xlsудалось прочитать очень большой лист из файла Excel, где оба XLConnectи xlsxне смогли (я считаю, потому что они оба полагаются на Apache POI )
Мэтт Паркер
49

Позвольте мне повторить то, что рекомендовал @Chase: используйте XLConnect .

На мой взгляд, причины использования XLConnect:

  1. Кросс-платформа. XLConnect написан на Java и, таким образом, будет работать в Win, Linux, Mac без изменения вашего кода R (кроме, возможно, строк пути)
  2. Больше нечего загружать. Просто установите XLConnect и продолжайте жить.
  3. Вы упомянули только чтение файлов Excel, но XLConnect также будет записывать файлы Excel, включая изменение форматирования ячеек. И он будет делать это из Linux или Mac, а не только из Win.

XLConnect является несколько новым по сравнению с другими решениями, поэтому он реже упоминается в сообщениях блогов и справочной документации. Для меня это было очень полезно.

JD Long
источник
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. И я попробовал, и у меня это очень хорошо работает.
Bastian
2
readxl и openxlsx - лучшие. readxl быстрее, но не позволяет писать. В любом случае, ни один из них не работает хорошо при попытке указать классы / типы столбцов.
skan
29

EDIT 2015-октябрь: Как и другие отметили здесь openxlsxи readxlпакеты гораздо быстрее , чем xlsxпакет , и на самом деле удается открыть большие файлы Excel (> 1500 строк и столбцов> 120). @MichaelChirico демонстрирует, что readxlлучше, когда предпочтительна скорость, и openxlsxзаменяет функциональность, предоставляемую xlsxпакетом. Если вы ищете пакет для чтения, записи и изменения файлов Excel в 2015 году, выберите openxlsxвместо xlsx.

До 2015 года: я использовал xlsxpackage . Это изменило мой рабочий процесс с Excel и R. Больше никаких раздражающих всплывающих окон с вопросом, уверен ли я, что хочу сохранить свой лист Excel в формате .txt. Пакет также записывает файлы 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спецификация преобразует ваши столбцы в факторы. Использование 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)))
Микко
источник
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 пакетов , упомянутых в этой теме: xlsx, openxlsx, readxl, и gdata, используя параметры по умолчанию (я также попробовал версию ли я или нет указать типы столбцов, но это не изменило ранжирование).

Я исключаю, RODBCпотому что я использую Linux; XLConnectпотому что кажется, что его основная цель - не чтение отдельных листов Excel, а импорт целых книг Excel, поэтому ставить свою лошадь в гонку только на ее способностях чтения кажется несправедливым; и xlsReadWriteпотому, что он больше не совместим с моей версией R(похоже, был прекращен).

Затем я провел тесты с NN=1000Lи NN=25000L(сбрасывая начальное число перед каждым объявлением data.frameвыше), чтобы учесть различия в размере файла Excel. gcв первую очередь для того xlsx, что, как я обнаружил, иногда может создавать засорение памяти. Без лишних слов, вот результаты, которые я нашел:

Файл Excel на 1000 строк

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на 60% медленнее readxl.

Файл Excel на 25000 строк

Из-за большого количества времени я сделал только 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) col_typesаргумент readxlтолько (как этого текста) принимает нестандартные R: "text"вместо "character"и "date"вместо "Date".

Майкл Кирико
источник
Было бы здорово, если бы вы также добавили тест для XLConnect. Также прокомментируйте, что readxl не может писать. xlsx и openxlsx не работают должным образом с опцией col_types или colClasses.
skan
@skan Сначала я провел несколько тестов, XLConnectно он очень медленный; Я считаю, readxlчто недостатки были достаточно освещены в моем последнем абзаце; и у меня нет подобного опыта в ваш с xlsxили openxlsxкак я регулярно использовать как для определения типов.
MichaelChirico
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 Long
1
@JD Long и даже на окнах это PITA. Нет времени для меня и ODBC на 64-битной W7 ...
Роман Луштрик
4
Загрузка необходимого пакета: Ошибка RODBC в odbcConnectExcel (имя_файла): odbcConnectExcel можно использовать только с 32-битной Windows
andrekos
6

Другим решением является xlsReadWriteпакет, который не требует дополнительных установок, но требует, чтобы вы загрузили дополнительный shlib перед его первым использованием:

require(xlsReadWrite)
xls.getshlib()

Если вы забудете об этом, это приведет к полному разочарованию. Был там и все такое ...

На заметку: вы можете рассмотреть возможность преобразования в текстовый формат (например, csv) и читать оттуда. Это по ряду причин:

  • независимо от вашего решения (RODBC, gdata, xlsReadWrite) могут произойти некоторые странные вещи, когда ваши данные будут преобразованы. Особенно финики могут быть довольно громоздкими. В HFWutilsпакете есть некоторые инструменты для работы с датами EXCEL (согласно комментарию @Ben Bolker).

  • если у вас большие листы, чтение текстовых файлов происходит быстрее, чем чтение из EXCEL.

  • для файлов .xls и .xlsx могут потребоваться другие решения. НАПРИМЕР, пакет xlsReadWrite в настоящее время не поддерживает .xlsx AFAIK. gdataтребует, чтобы вы установили дополнительные библиотеки Perl для поддержки .xlsx. xlsxpackage может обрабатывать одноименные расширения.

Джорис Мейс
источник
@Ben Спасибо за совет, я включу его в свой ответ. Однако я не пытался быть полным, так как страница вики, на которую ссылается принятый ответ, уже довольно полная. Но здесь не упоминается пакет HFWutils.
Джорис Мейс
1
-1; Смотрите мой ответ. TL: DR: Excel не сохраняет набор данных полной точности в CSV (или в буфер обмена). Сохраняются только видимые значения.
russellpierce
5

Как отмечалось выше во многих других ответах, есть много хороших пакетов, которые подключаются к файлу XLS / X и получают данные разумным способом. Однако вы должны быть предупреждены, что ни при каких обстоятельствах вы не должны использовать файл буфера обмена (или файл .csv) для извлечения данных из Excel. Чтобы понять, почему, войдите =1/3в ячейку в Excel. Теперь уменьшите количество видимых вам десятичных знаков до двух. Затем скопируйте и вставьте данные в R. Теперь сохраните CSV. Вы заметите, что в обоих случаях Excel помогает сохранить только те данные, которые были видны вам через интерфейс, и вы потеряли всю точность ваших фактических исходных данных.

Расселпирс
источник
1
Я хотел бы знать, кто считал, что числовая точность не важна.
russellpierce
1
Хорошее предупреждение. Однако это зависит от используемого вами пакета. некоторые не попадают в эту ловушку.
RockScience,
@RocketScience Это фундаментальный выбор дизайна при экспорте CSV в Excel. У вас есть пример пакета, который использует буфер обмена и не имеет этой проблемы? Пакеты, непосредственно анализирующие файл 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
Ваше решение возвращается numericна factorsна моем компьютере. read.xlsxиспользуется characterв readColumnsфункции для указания факторов. Я уверен , что есть более удобный способ получения факторов , как героев, но здесь представляет собой модифицированную версию вашей функции , которая работает: df.real <- read.xlsx2("filename.xlsx", 1, colClasses=gsub("factor", "character", as.vector(sapply(df.temp, class)))).
Mikko
Это работает только в той степени, в которой тип столбца может быть адекватно определен по первой строке. Обычно, чтобы сделать это определение, анализируется больше, чем первая строка. Ответ можно улучшить, обратившись к комментарию aaa90210, указав пакет, из которого берутся эти функции.
russellpierce
1

Файл Excel можно прочитать непосредственно в R следующим образом:

my_data <- read.table(file = "xxxxxx.xls", sep = "\t", header=TRUE)

Чтение файлов xls и xlxs с использованием пакета readxl

library("readxl")
my_data <- read_excel("xxxxx.xls")
my_data <- read_excel("xxxxx.xlsx")
Ашок Кумар Джаяраман
источник