Учитывая распространение различных способов чтения файла 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"
.