readxl :: read_xls возвращает ошибку libxls: невозможно открыть файл

У меня есть несколько файлов .xls (~ 100 МБ), из которых я хотел бы загрузить несколько листов (из каждого) в R в качестве фрейма данных. Я пробовал различные функции, такие как xlsx::xlsx2 и XLConnect::readWorksheetFromFile, обе из которых всегда работают очень долго (> 15 минут) и никогда не заканчиваются, и мне приходится принудительно закрыть RStudio, чтобы продолжить работу.

Я также пробовал gdata::read.xls, который завершается, но на один лист уходит более 3 минут, и он не может извлекать несколько листов одновременно (что было бы очень полезно для ускорения моего конвейера), как XLConnect::loadWorkbook.

Время, необходимое для выполнения этих функций (и я даже не уверен, что первые две когда-либо закончатся, если я позволю им работать дольше), слишком велико для моего конвейера, где мне нужно работать со многими файлами одновременно. Есть ли способ заставить их работать / закончить быстрее?

В нескольких местах я видел рекомендацию использовать функцию readxl::read_xls, которая, кажется, широко рекомендуется для этой задачи и должна быть быстрее на листе. Однако это дает мне ошибку:

> # Minimal reproducible example:
> setwd("/Users/USER/Desktop")
> library(readxl)
> data <- read_xls(path="test_file.xls")
Error: 
  filepath: /Users/USER/Desktop/test_file.xls
  libxls error: Unable to open file

Я также провел элементарное тестирование, чтобы убедиться, что файл существует и имеет правильный формат:

> # Testing existence & format of the file
> file.exists("test_file.xls")
[1] TRUE
> format_from_ext("test_file.xls")
[1] "xls"
> format_from_signature("test_file.xls")
[1] "xls"

Использованный выше test_file.xls доступен здесь. Мы будем признательны за любой совет относительно того, как заставить работать первые функции быстрее или вообще read_xls - спасибо!

ОБНОВИТЬ:

Похоже, что некоторые пользователи могут открыть указанный выше файл с помощью функции readxl::read_xls, в то время как другие не могут, как на Mac, так и на Windows, использовать самые последние версии R, Rstudio и readxl. Проблема была опубликована на readxl GitHub и еще не решена.


person Brunox13    schedule 06.12.2019    source источник


Ответы (7)


Я загрузил ваш набор данных и прочитал каждый лист Excel таким образом (например, для листов «Общие» и «Площадь»):

install.packages("readxl")
library(readxl)
library(data.table)

dt_overall <- as.data.table(read_excel("test_file.xls", sheet = "Overall"))
area_sheet <- as.data.table(read_excel("test_file.xls", sheet = "Area"))

Наконец, я получаю такое dt (например, только часть набора данных для листа «Площадь»):

введите описание изображения здесь

Точно так же вы можете использовать функцию read_xls вместо read_excel.

Проверил, тоже работает корректно и даже немного быстрее, так как read_excel - это оболочка над функциями read_xls и read_xlsx из пакета readxl.

Кроме того, вы можете использовать функцию excel_sheets из пакета readxl для чтения всех листов вашего файла Excel.

ОБНОВЛЕНИЕ

Тестирование выполняется с помощью пакета microbenchmark для следующих пакетов / функций: gdata::read.xls, XLConnect::readWorksheetFromFile и readxl::read_excel.

Но XLConnect это решение на основе Java, поэтому для него требуется много оперативной памяти.

введите описание изображения здесь

person red_quark    schedule 07.12.2019
comment
Спасибо за ответ! К сожалению, это никоим образом не способствует решению моей проблемы - когда я пытаюсь запустить ваш код, я все равно получаю ту же ошибку, которая описана в исходном вопросе: libxls error: Unable to open file - person Brunox13; 08.12.2019
comment
Попробуйте удалить пакет readxl, перезапустите RStudio и переустановите readxl. Также попробуйте обновить R и RStudio до последних версий (если у вас устаревшие версии). - person red_quark; 08.12.2019
comment
Как возможный вариант, вы можете открыть файл Excel, сохранить его с расширением .xlsx, а затем прочитать его таким же образом (используя функцию read_excel из пакета readxl). - person red_quark; 08.12.2019
comment
Хорошая идея, но переустановка пакета readxl не помогла. Если возможно, я хотел бы открыть файл как есть, все в R, без предварительного использования Excel. Я отправил отчет об ошибке в readxl github, поэтому мы посмотрим, есть ли у них лучшее предложение! - person Brunox13; 09.12.2019
comment
О, это очень интересно. Надеюсь, они помогут вам найти решение проблемы. Одновременно у меня есть еще две рекомендации, которые, возможно, могут вам помочь: 1. Попробуйте напрямую установить пакет Rcpp, который, в свою очередь, требует Xcode (для OSX), которые являются зависимостями, внешними по отношению к R. - person red_quark; 09.12.2019
comment
2. Попробуйте открыть файл Excel с помощью более старой версии пакета readxl (например, v.1.3.0, 1.2.0, 1.1.0. И т. Д., Все архивные версии доступны здесь: cran.r-project.org/src/contrib/Archive/readxl). Установить можно так (например): if(!require(readxl)) { install.packages("https://cran.r-project.org/src/contrib/Archive/readxl/readxl_1.2.0.tar.gz", repos = NULL, type="source"); suppressPackageStartupMessages(require(readxl))} P.S. в ссылке можно указать любую версию пакета архива - person red_quark; 09.12.2019
comment
Спасибо, это несколько находчивых идей! К сожалению, они не помогли - у меня уже есть и Rcpp, и Xcode; следуя вашему совету, я пробовал предыдущие версии пакета readxl, но все равно получаю ту же ошибку; единственная разница в том, что ошибка v1.1.0 Error in read_fun(path = path, sheet_i = sheet, limits = limits, shim = shim, : Failed to open test_file.xls, но я предполагаю, что это по сути то же самое. - person Brunox13; 09.12.2019
comment
Пожалуйста, какова скорость gdata::read.xls, XLConnect::readWorksheetFromFile и readxl::read_xls на вашем компьютере для этого файла? И вы изменили (или открыли в Excel) файл перед его успешной загрузкой с помощью пакета readxl? - person Brunox13; 10.12.2019
comment
Я провел для вас бенчмаркинг (в соответствии с указанными вами функциями раз = 1L). Как видите, readxl::read_excel намного быстрее других. Я обновил свой ответ, чтобы продемонстрировать бенчмаркинг. - person red_quark; 10.12.2019
comment
Конечно же нет. Я не изменял и не открывал файл Excel перед его загрузкой с пакетом readxl. Я запускаю код в Windows 10 Enterprise (RAM 16 ГБ, 64-разрядная версия). Но! Когда я пытаюсь прочитать ваш файл Excel с помощью RStudio Server (Ubuntu), я получаю ту же ошибку: libxls error: Unable to open file. - person red_quark; 10.12.2019
comment
Большое вам спасибо за все это !! Я перепубликую ваш комментарий на гитхабе. - person Brunox13; 10.12.2019
comment
Я просто попробовал функцию readxl::read_excel на компьютере с Windows и закончил с той же ошибкой - libxls error: Unable to open file. Какая настройка на компьютере, на котором эта функция работает с этим файлом? Версии Windows, R, RStudio, readxl и т. Д.? - person Brunox13; 11.12.2019
comment
О, очень странно (у меня > sessionInfo() R version 3.6.1 (2019-07-05) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows >= 8 x64 (build 9200) (Windows: Windows 10 Enterprise, версия 1803, сборка ОС 17134.1006. Proc: Intel Core i7-8550U, 64-битная ОС). RStudio - версия 1.1.456 (19 июля 2018 г.) - person red_quark; 13.12.2019

Я предложу другой рабочий процесс. Если у вас установлен LibreOffice, вы можете программно преобразовать файлы Excel в CSV. У меня Linux, поэтому я делаю это в bash, но уверен, что это возможно и в macOS.

Итак, откройте терминал, перейдите в папку с вашими файлами Excel и запустите в терминале:

for i in *.xls
    do soffice --headless --convert-to csv "$i" 
done

Теперь в R вы можете использовать data.table::fread для чтения файлов в цикле:

Сценарий 1: структура файлов другая

Если структура файлов отличается, вам не нужно rbind их вместе. Вы можете запустить в R:

files <- dir("path/to/files", pattern = ".csv")
all_files <- list()
for (i in 1:length(files)){
  fileName <- gsub("(^.*/)(.*)(.csv$)", "\\2", files[i])
  all_files[[fileName]] <- fread(files[i])
}

Если вы хотите извлечь именованные элементы из списка в глобальную среду, чтобы их можно было преобразовать в объекты, вы можете использовать list2env:

list2env(all_files, envir = .GlobalEnv)

Обратите внимание на две вещи: во-первых, в вызове gsub направление косой черты. Во-вторых, list2env может перезаписывать объекты в вашей глобальной среде, если они имеют то же имя, что и названные элементы в списке.

Сценарий 2: структура файлов такая же

В таком случае, вероятно, вы захотите rbind их всех вместе. Вы можете запустить в R:

files <- dir("path/to/files", pattern = ".csv")
joined <- list()
for (i in 1:length(files)){
  joined <- rbindlist(joined, fread(files[i]), fill = TRUE)
}
person PavoDive    schedule 07.12.2019
comment
Спасибо за ответ! Я бы предпочел решение, полностью выполненное на R, так как я разрабатываю этот рабочий процесс для друга, который не так хорошо разбирается в кодировании, поэтому я хотел бы передать ей один рабочий сценарий вместо того, чтобы перейти к терминалу. - person Brunox13; 08.12.2019

Я обнаружил, что не могу открыть файл с помощью read_xl сразу после его загрузки, но если я открою файл в Excel, сохраню его и снова закрою, тогда read_xl смог бы открыть его без проблем.

Я предлагаю обходной путь для обработки сотен файлов - создать небольшую утилиту командной строки C #, которая открывает, сохраняет и закрывает файл Excel. Исходный код приведен ниже, утилиту можно скомпилировать с помощью Visual Studio Community Edition.

using System.IO;
using Excel = Microsoft.Office.Interop.Excel;

namespace resaver
{
  class Program
  {
    static void Main(string[] args)
    {
      string srcFile = Path.GetFullPath(args[0]);
      Excel.Application excelApplication = new Excel.Application();
      excelApplication.Application.DisplayAlerts = false;
      Excel.Workbook srcworkBook = excelApplication.Workbooks.Open(srcFile);
      srcworkBook.Save();
      srcworkBook.Close();
      excelApplication.Quit();
    }
  }
}

После компиляции утилита может быть вызвана из R, например, system2().

person mikeck    schedule 12.03.2020

В моей системе мне пришлось использовать path.expand.

R> file = "~/blah.xls"
R> read_xls(file)

Error: 
  filepath: ~/Dropbox/signal/aud/rba/balsheet/data/a03.xls
  libxls error: Unable to open file

R> read_xls(path.expand(file)) # fixed
person ricardo    schedule 05.05.2020

Сохраните файл повторно, и вы легко решите свою проблему.

Я тоже сталкивался с этой проблемой раньше, но я получил ответ из вашего обсуждения.

Я использовал read_excel(), чтобы открыть эти файлы.

person 花落思量错    schedule 06.08.2020
comment
Вы имеете в виду пересохранение файла в Excel? Да, это уже предлагалось, но это не решает проблему при работе с сотнями файлов (вы можете себе представить, что открытие и повторное сохранение каждого файла в Microsoft Excel займет очень много времени). - person Brunox13; 06.08.2020
comment
И не имеет значения, используется ли read_xls() или read_excel() - согласно read_excel() документация, read_xls() на самом деле лучше: read_excel() вызывает excel_format(), чтобы определить, является ли путь xls или xlsx, в зависимости от расширения файла и самого файла в указанном порядке. Используйте read_xls() и read_xlsx() напрямую, если вы лучше знаете и хотите предотвратить такие предположения. - person Brunox13; 06.08.2020

Я видел аналогичную ошибку и хотел поделиться краткосрочным решением.

library(readxl)
download.file("https://mjwebster.github.io/DataJ/spreadsheets/MLBpayrolls.xls", "MLBPayrolls.xls")
MLBpayrolls <- read_excel("MLBpayrolls.xls", sheet = "MLB Payrolls", na = "n/a")

Урожайность (на некоторых системах в моем классе, но не на других):

Ошибка: путь к файлу: MLBPayrolls.xls ошибка libxls: невозможно открыть файл

Временным решением было вставить URL-адрес файла xls в Firefox и загрузить его через браузер. Как только это будет сделано, мы сможем запустить строку read_excel без ошибок.

Это происходило сегодня в Windows 10 с R 3.6.2 и R Studio 1.2.5033.

person Ryan Thornburg    schedule 31.01.2020
comment
Спасибо, @Ryan! Как я уже упоминал на GitHub, проблема, описанная в OP, была связана с файлами, уже загруженными локально, поэтому, вероятно, это другой вопрос. - person Brunox13; 31.01.2020

Если вы загрузили данные .xls из Интернета, даже если вы открываете их в Ms.Excel, сначала откроется окно с просьбой подтвердить, доверяете ли вы источнику, см. Снимок экрана ниже, я предполагаю, что это причина R (read_xls) тоже не может его открыть, так как это считается небезопасным. Сохраните его как файл .xlsx, а затем используйте read_xlsx() или read_excel(). введите описание изображения здесь

person ahmadzai    schedule 13.03.2021