Biorąc pod uwagę R
mnogość różnych sposobów czytania pliku Excel i mnóstwo odpowiedzi tutaj, pomyślałem, że spróbuję rzucić trochę światła na to, które z wymienionych tutaj opcji działają najlepiej (w kilku prostych sytuacjach).
Sam używam, xlsx
odkąd zacząłem używać R
, dla bezwładności, jeśli nic innego, a ostatnio zauważyłem, że nie ma żadnych obiektywnych informacji o tym, który pakiet działa lepiej.
Każde ćwiczenie benchmarkingowe jest obarczone trudnościami, ponieważ niektóre pakiety z pewnością radzą sobie w pewnych sytuacjach lepiej niż inne, a także szereg innych zastrzeżeń.
To powiedziawszy, używam (odtwarzalnego) zestawu danych, który moim zdaniem ma dość powszechny format (8 pól ciągów, 3 numeryczne, 1 liczba całkowita, 3 daty):
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)
)
Potem napisał do csv i otwarty w LibreOffice i zapisać go jako plik .xlsx, a następnie na podstawie porównania 4 pakietów wymienionych w tym wątku: xlsx
, openxlsx
, readxl
, i gdata
, przy użyciu domyślnych opcji (Próbowałem też wersję, czy nie ja określić typy kolumn, ale nie zmieniło to rankingów).
Wykluczam, RODBC
ponieważ używam Linuksa; XLConnect
ponieważ wydaje się, że jego głównym celem nie jest czytanie pojedynczych arkuszy Excela, ale importowanie całych skoroszytów Excela, więc wystawienie konia do wyścigu tylko na jego możliwości czytania wydaje się niesprawiedliwe; i xlsReadWrite
ponieważ nie jest już kompatybilny z moją wersją R
(wydaje się, że został wycofany).
Następnie przeprowadziłem testy porównawcze z NN=1000L
i NN=25000L
(resetując ziarno przed każdą deklaracją data.frame
powyższego), aby uwzględnić różnice w rozmiarze pliku Excel. gc
jest przeznaczony przede wszystkim dla xlsx
, co do których odkryłem, że czasami może powodować zatory pamięci. Bez dalszych ceregieli, oto wyniki, które znalazłem:
1000-wierszowy plik 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
Tak readxl
jak zwycięzca, z openxlsx
konkurencyjnym i gdata
wyraźnym przegranym. Biorąc każdy pomiar w stosunku do minimum kolumny:
# 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
Widzimy, że mój ulubiony xlsx
jest o 60% wolniejszy niż readxl
.
Plik Excel z 25 000 wierszami
Ze względu na ilość czasu, który zajmuje, wykonałem tylko 20 powtórzeń na większym pliku, w przeciwnym razie polecenia były identyczne. Oto surowe dane:
# 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
Oto dane względne:
# 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
Więc readxl
jest wyraźnym zwycięzcą, jeśli chodzi o prędkość. gdata
lepiej mieć coś innego do roboty, ponieważ czytanie plików Excela jest boleśnie powolne, a ten problem jest tylko zaostrzony w przypadku większych tabel.
Dwie zalety openxlsx
to 1) jego rozbudowane inne metody ( readxl
ma na celu zrobienie tylko jednej rzeczy, co prawdopodobnie jest częścią powodu, dla którego jest tak szybki), zwłaszcza jego write.xlsx
funkcji, i 2) (większa wada readxl
) col_types
argumentu readxl
tylko (jako tego tekstu) akceptuje niektóre niestandardowe R
: "text"
zamiast "character"
i "date"
zamiast "Date"
.