Czytaj plik Excela bezpośrednio ze skryptu R.

95

Jak mogę czytać plik Excela bezpośrednio do R? Czy powinienem najpierw wyeksportować dane do pliku tekstowego lub CSV i zaimportować ten plik do R?

wałki
źródło
@Sacha Epskamp: dzięki xlsReadWrite nie musisz nawet instalować Perla.
Joris Meys
1
gdatawersja 2.8.2 czyta xlsxpliki z read.xlsfunkcją
Ben
1
Zobacz moje ostrzeżenie (jako odpowiedź poniżej) dotyczące możliwej utraty precyzji, jeśli eksportujesz dane do formatu tekstowego z programu Excel.
russellpierce
1
xlsxpakiet dla xlsx / xlsm / xls, nie wiem o xlam itp.
Qbik
2
„Nigdy nie widzę powodu, aby nie eksportować najpierw do pliku tekstowego”. Co powiesz na to: kiedy eksportuję do CSV, jedno z potrzebnych pól nie jest zapisywane. Wygląda na to, że jest to jakiś DRM, ale ponieważ nie napisałem arkusza kalkulacyjnego, nie wiem.
Nate Reed

Odpowiedzi:

41

Tak. Zobacz odpowiednią stronę w R wiki . Krótka odpowiedź: read.xlsz gdatapakietu działa przez większość czasu (chociaż musisz mieć zainstalowany Perl w swoim systemie - zwykle jest to już prawda na MacOS i Linux, ale robi dodatkowy krok w Windows, tj. Patrz http://strawberryperl.com/ ). Istnieją różne zastrzeżenia i alternatywy wymienione na stronie R wiki.

Jedynym powodem, dla którego nie robię tego bezpośrednio, jest to, że możesz chcieć sprawdzić arkusz kalkulacyjny, aby sprawdzić, czy nie ma błędów (dziwne nagłówki, wiele arkuszy roboczych [możesz czytać tylko jeden naraz, chociaż oczywiście możesz je wszystkie zapętlić] , wliczone działki itp.). Ale dla dobrze uformowanego, prostokątnego arkusza kalkulacyjnego z prostymi liczbami i danymi znakowymi (tj. Liczbami nieprzecinkowymi, datami, formułami z błędami dzielenia przez zero, brakującymi wartościami itp.) Generalnie nie mam problemu z tym procesem.

Ben Bolker
źródło
6
Jest wiele potencjalnych problemów, na które napotkałem osobiście. Pola z liczbami z przecinkami należy usunąć i przekonwertować na numeryczne w R. Pola z „-” należy przekodować na NA. Ogólnie zaleca się, aby naprawdę spojrzeć na swoje liczby w Excelu i upewnić się, że są poprawnie przetłumaczone na R.
Brandon Bertelsen
3
Nie możesz się kłócić z „naprawdę musisz spojrzeć na swoje liczby”… jaki jest problem z polami „-”? ma na.strings="-"rozwiązać ten problem? Ile z tych problemów jest ogólnych, a ile z nich (np. Pola liczbowe z przecinkami) można rozwiązać za pomocą innych narzędzi, takich jak XLConnect…?
Ben Bolker
1
Ten komentarz był skierowany do OP, a nie do ciebie, Ben, moja wina za złe umieszczenie.
Brandon Bertelsen
1
Odpowiednia anegdota: read.xlsudało się odczytać bardzo duży arkusz z pliku Excela, w którym zarówno XLConnecti xlsxnie powiodło się (myślę, że oboje polegają na Apache POI )
Matt Parker
49

Powtórzę, co zaleca @Chase: użyj XLConnect .

Moim zdaniem powody korzystania z XLConnect to:

  1. Wiele platform. XLConnect jest napisany w Javie i dlatego będzie działał na Win, Linux, Mac bez zmiany kodu R (z wyjątkiem ewentualnie ciągów ścieżek)
  2. Nic więcej do załadowania. Wystarczy zainstalować XLConnect i żyć dalej.
  3. Wspomniałeś tylko o czytaniu plików Excela, ale XLConnect będzie również zapisywał pliki Excel, w tym zmieniając formatowanie komórek. I zrobi to z Linuksa lub Maca, a nie tylko z Win.

XLConnect jest nieco nowy w porównaniu z innymi rozwiązaniami, więc jest rzadziej wspominany w postach na blogach i dokumentach referencyjnych. Dla mnie to bardzo przydatne.

JD Long
źródło
48

A teraz jest readxl :

Pakiet readxl ułatwia pobieranie danych z Excela do R. W porównaniu z istniejącymi pakietami (np. Gdata, xlsx, xlsReadWrite itp.) Readxl nie ma żadnych zewnętrznych zależności, więc jest łatwy w instalacji i obsłudze we wszystkich systemach operacyjnych. Jest przeznaczony do pracy z danymi tabelarycznymi przechowywanymi w jednym arkuszu.

readxl jest zbudowany na bazie biblioteki libxls C, która eliminuje wiele zawiłości bazowego formatu binarnego.

Obsługuje zarówno starszy format .xls, jak i .xlsx

readxl jest dostępny w CRAN lub możesz go zainstalować z github za pomocą:

# install.packages("devtools")
devtools::install_github("hadley/readxl")

Stosowanie

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")

Zauważ, że chociaż opis mówi `` brak zewnętrznych zależności '', wymaga on Rcpppakietu , który z kolei wymaga Rtools (dla Windows) lub Xcode (dla OSX), które zależnościami zewnętrznymi w stosunku do R. Chociaż wiele osób ma je zainstalowane z innych powodów. .

Ben
źródło
3
Znacznie szybszy niż xlsx. Czas odczytu jest podobny do odczytu.xlsx2, ale określa typy.
Steve Rowe
1
@SteveRowe widzę nową odpowiedź na niektóre (próbowane) obiektywne testy porównawcze, które to potwierdzają
MichaelChirico.
Czy istnieje sposób na odczytanie ciągów znaków jako czynników używających read_excel? Podoba mi się prędkość w porównaniu z read.xlsx, ale konieczność ręcznej konwersji kolumn ze znaków na czynniki mija się z celem.
coip
2
+1 za to, że nie ma żadnych zależności. Nienawidzę instalować Java. Wypróbowałem to i działa to bardzo dobrze.
Bastian,
2
readxl i openxlsx są najlepsze. readxl jest szybszy, ale nie pozwala na pisanie. W każdym razie żaden z nich nie działa dobrze, gdy próbujesz określić klasy / typy kolumn.
skan
29

EDYCJA 2015-październik: Tak jak inni komentowali tutaj, pakiety openxlsxi readxlsą znacznie szybsze niż xlsxpakiet i faktycznie potrafią otwierać większe pliki Excela (> 1500 wierszy i> 120 kolumn). @MichaelChirico pokazuje, że readxljest lepsza, gdy preferowana jest prędkość, i openxlsxzastępuje funkcjonalność dostarczaną przez xlsxpakiet. Jeśli szukasz pakietu do odczytu, zapisu i modyfikowania plików Excela w 2015 roku, wybierz openxlsxzamiast xlsx.

Przed 2015 rokiem: korzystałem z xlsxpakietu . Zmieniło to mój przepływ pracy w Excelu i R. Koniec z irytującymi wyskakującymi okienkami z pytaniem, czy jestem pewien, że chcę zapisać arkusz Excela w formacie .txt. Pakiet zapisuje również pliki Excel.

Jednak uważam, że read.xlsxfunkcja działa wolno podczas otwierania dużych plików Excela. read.xlsx2funkcja jest znacznie szybsza, ale nie odrzuca klasy wektorów kolumn data.frame. Musisz użyć colClassespolecenia, aby określić żądane klasy kolumn, jeśli używasz read.xlsx2funkcji. Oto praktyczny przykład:

read.xlsx("filename.xlsx", 1)czyta plik i sprawia, że ​​klasy kolumn data.frame są prawie przydatne, ale jest bardzo powolne w przypadku dużych zestawów danych. Działa również dla .xlsplików.

read.xlsx2("filename.xlsx", 1)jest szybszy, ale będziesz musiał ręcznie zdefiniować klasy kolumn. Skrót polega na dwukrotnym uruchomieniu polecenia (patrz przykład poniżej). characterspecyfikacja konwertuje kolumny na czynniki. Zastosowanie Datei POSIXctopcje dotyczące czasu.

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)))
Mikko
źródło
25

Biorąc pod uwagę Rmnogość 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, xlsxodką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, RODBCponieważ używam Linuksa; XLConnectponieważ 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 xlsReadWriteponieważ nie jest już kompatybilny z moją wersją R(wydaje się, że został wycofany).

Następnie przeprowadziłem testy porównawcze z NN=1000Li NN=25000L(resetując ziarno przed każdą deklaracją data.framepowyższego), aby uwzględnić różnice w rozmiarze pliku Excel. gcjest 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 readxljak zwycięzca, z openxlsxkonkurencyjnym i gdatawyraź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 xlsxjest 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 readxljest wyraźnym zwycięzcą, jeśli chodzi o prędkość. gdatalepiej 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 openxlsxto 1) jego rozbudowane inne metody ( readxlma na celu zrobienie tylko jednej rzeczy, co prawdopodobnie jest częścią powodu, dla którego jest tak szybki), zwłaszcza jego write.xlsxfunkcji, i 2) (większa wada readxl) col_typesargumentu readxltylko (jako tego tekstu) akceptuje niektóre niestandardowe R: "text"zamiast "character"i "date"zamiast "Date".

MichaelChirico
źródło
Byłoby wspaniale, gdybyś dodał również benchmark dla XLConnect. Skomentuj również, że readxl nie jest w stanie pisać. xlsx i openxlsx nie działają poprawnie z opcją col_types lub colClasses.
skan
@skan Na początku przeprowadziłem kilka testów, XLConnectale jest to bardzo powolne; Uważam, że readxlw moim ostatnim akapicie wystarczająco omówiono wady; i nie mam podobnego doświadczenia do twojego z xlsxlub openxlsxponieważ regularnie używam obu do określania typów.
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)

Osobiście lubię RODBC i mogę go polecić.

Brandon Bertelsen
źródło
7
Ostrzeżenie: ODBC może być czasami trudne do uruchomienia na platformach innych niż Windows.
JD Long
1
@JD Długie i nawet na Windowsie to PITA. Nie ma seksownego czasu dla mnie i ODBC na 64-bitowym W7 ...
Roman Luštrik
4
Ładowanie wymaganego pakietu: Błąd RODBC w odbcConnectExcel (nazwa_pliku): odbcConnectExcel działa tylko z 32-bitowym systemem Windows
andrekos
6

Innym rozwiązaniem jest xlsReadWritepakiet, który nie wymaga dodatkowych instalacji, ale wymaga pobrania dodatkowego shlib przed pierwszym użyciem przez:

require(xlsReadWrite)
xls.getshlib()

Zapominanie o tym może wywołać całkowitą frustrację. Byłem tam i to wszystko ...

Na marginesie: możesz rozważyć konwersję do formatu tekstowego (np. Csv) i odczytać stamtąd. Dzieje się tak z kilku powodów:

  • bez względu na rozwiązanie (RODBC, gdata, xlsReadWrite) po konwersji danych mogą się wydarzyć dziwne rzeczy. Zwłaszcza daty mogą być dość uciążliwe. HFWutilsPakiet zawiera kilka narzędzi do radzenia sobie z datami Excel (na komentarzu @Ben Bolker'S).

  • jeśli masz duże arkusze, czytanie plików tekstowych jest szybsze niż czytanie z EXCEL.

  • w przypadku plików .xls i .xlsx mogą być konieczne inne rozwiązania. Na przykład pakiet xlsReadWrite obecnie nie obsługuje formatu .xlsx AFAIK. gdatawymaga zainstalowania dodatkowych bibliotek perl dla obsługi .xlsx. xlsxpakiet może obsługiwać rozszerzenia o tej samej nazwie.

Joris Meys
źródło
@ Ben Thx za wskazówkę, dołączę ją do mojej odpowiedzi. Nie starałem się jednak być kompletny, ponieważ strona wiki, na którą linki są akceptowane, jest już dość kompletna. Ale nie wspomina o pakiecie HFWutils.
Joris Meys
1
-1; Zobacz moją odpowiedź. TL: DR: Excel nie zapisuje zestawu danych o pełnej precyzji do csv (lub schowka). Zachowywane są tylko widoczne wartości.
russellpierce
5

Jak wspomniano powyżej w wielu innych odpowiedziach, istnieje wiele dobrych pakietów, które łączą się z plikiem XLS / X i pobierają dane w rozsądny sposób. Należy jednak ostrzec, że w żadnym wypadku nie należy używać schowka (ani pliku .csv) do pobierania danych z programu Excel. Aby zobaczyć, dlaczego, wejdź =1/3do komórki w programie Excel. Teraz zmniejsz liczbę widocznych miejsc dziesiętnych do dwóch. Następnie skopiuj i wklej dane do R. Teraz zapisz plik CSV. Zauważysz, że w obu przypadkach program Excel pomógł tylko zachować dane, które były widoczne dla Ciebie przez interfejs, i straciłeś całą dokładność w rzeczywistych danych źródłowych.

russellpierce
źródło
1
Chciałbym wiedzieć, kto uważał, że wierność liczbowa nie jest istotna / ważna.
russellpierce
1
Dobre ostrzeżenie. Jednak zależy to od używanego pakietu. niektórzy nie wpadają w tę pułapkę.
RockScience
@RocketScience To jest podstawowy wybór projektu w przypadku eksportu CSV przez Excel. Czy masz przykład pakietu korzystającego ze schowka, w którym nie występuje ten problem? Pakiety bezpośrednio analizujące plik xls xlsx nie wpadną w tę pułapkę. Stąd konkretny zakres mojego ostrzeżenia.
russellpierce
na Uniksie możesz spróbować gnumeric::read.gnumeric.sheet. W systemie Windows nie jestem w 100% pewien, ale myślę, że gdata::read.xlspowinien również działać dobrze (chociaż trzeba zainstalować perl)
RockScience
@RockScience Z szacunkiem, gdata :: read.xls nie działa na danych ze schowka (chyba że zejdziesz z drogi), a gnumeric to nie Excel. Tak więc, przy braku nadzwyczajnego dowodu, moje ostrzeżenie jest aktualne. Jest tak wiele innych dobrych opcji w odpowiedzi na to pytanie - miejmy nadzieję, że ludzie zamiast tego z nich skorzystają.
russellpierce
5

Rozwijając odpowiedź udzieloną przez @Mikko, możesz użyć sprytnego triku, aby przyspieszyć działanie bez konieczności „znajomości” klas kolumn z wyprzedzeniem. Po prostu użyj, read.xlsxaby pobrać ograniczoną liczbę rekordów, aby określić klasy, a następnie wykonaj czynnościread.xlsx2

Przykład

# 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)))
JasonAizkalns
źródło
1
Twoje rozwiązanie powraca numericdo factorsna moim komputerze. read.xlsxużywa characterw readColumnsfunkcji do określenia czynników. Jestem pewien, że jest bardziej elegancki sposób na uzyskanie czynniki jako znaki, ale tutaj jest zmodyfikowaną wersją swojej funkcji, która działa: df.real <- read.xlsx2("filename.xlsx", 1, colClasses=gsub("factor", "character", as.vector(sapply(df.temp, class)))).
Mikko
Działa to tylko w takim zakresie, w jakim typ kolumny można odpowiednio określić na podstawie pierwszego wiersza. Zwykle analizuje się więcej niż pierwszy wiersz, aby to ustalić. Odpowiedź można poprawić, aby odnieść się do komentarza aaa90210, nazywając pakiet, z którego pochodzą te funkcje.
russellpierce
1

Plik Excela można wczytać bezpośrednio do R w następujący sposób:

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

Odczytywanie plików xls i xlxs przy użyciu pakietu readxl

library("readxl")
my_data <- read_excel("xxxxx.xls")
my_data <- read_excel("xxxxx.xlsx")
Ashok Kumar Jayaraman
źródło