Читайте файл 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
Msgstr "Я ніколи не бачу причини, щоб спочатку не експортувати в текстовий файл". Як щодо цього: Коли я експортую в CSV, одне з полів, яке мені потрібно, не записується. Це схоже на якийсь DRM, але оскільки я не писав електронну таблицю, я не знаю.
Nate Reed

Відповіді:


41

Так. Дивіться відповідну сторінку на R-вікі . Коротка відповідь: read.xlsз gdataпакету працює більшість часу (хоча вам потрібно встановити Perl у вашій системі - як правило, це вже стосується MacOS та Linux, але робить додатковий крок у Windows, тобто див. Http://strawberryperl.com/ ). Існують різні застереження та альтернативи, перелічені на сторінці R wiki.

Єдина причина, по якій я бачу, щоб не робити цього безпосередньо, полягає в тому, що, можливо, ви захочете вивчити електронну таблицю, щоб побачити, чи є в ній збої (дивні заголовки, кілька робочих аркушів [ви можете читати лише по одному за раз, хоча ви, очевидно, можете прокрутити всі їх] , включені ділянки тощо). Але для добре сформованої прямокутної електронної таблиці з простими числами та даними символів (тобто не відформатованих комами чисел, дат, формул з помилками, розділеними на нуль, відсутніми значеннями тощо, тощо), я взагалі не маю проблем за допомогою цього процесу.


6
Є багато потенційних проблем, з якими я стикався особисто. Поля з цифрами з комою потрібно вилучити та перетворити на числові в R. Поля з "-" потрібно перекодувати в NA. Загальна рекомендація - по-справжньому переглянути свої номери в Excel і переконатись, що вони правильно перекладені на R.
Брендон Бертельсен,

3
Не можу сперечатися з "вам дійсно потрібно дивитись на свої номери" ... у чому проблема з полями "-"? Чи na.strings="-"вирішення проблеми? Скільки цих питань є загальними і скільки з них (наприклад, числові поля з комами) можна вирішити за допомогою інших інструментів, таких як XLConnect ...?
Бен Болкер,

1
Цей коментар був спрямований на ОП, а не на тебе, Бен, моя вина за погане розміщення.
Брендон Бертельсен,

1
Відповідний анекдот: read.xlsвдалося прочитати дуже великий аркуш із файлу Excel, де XLConnectі xlsxне вдалося (я вважаю, тому що вони обидва покладаються на POI Apache )
Метт Паркер,

49

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

На мій погляд, причини використання XLConnect:

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

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


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 бачить нову відповідь на деякі (спроби) об'єктивні
еталони, що

Чи є спосіб прочитати рядки як фактори використання read_excel? Мені подобається швидкість порівняно з read.xlsx, але необхідність ручного перетворення стовпців із символів у фактори перешкоджає цілі.
копія

2
+1 за те, що він не має залежностей. Я ненавиджу встановлювати java. І я спробував, і це дуже добре для мене працює.
Бастіан,

2
readxl та openxlsx - найкращі. readxl швидший, але не дозволяє писати. У будь-якому випадку, жоден з них не працює добре при спробі вказати класи / типи стовпців.
skan

29

EDIT 2015 жовтень: Як і інші відзначили тут openxlsxі readxlпакети набагато швидше , ніж xlsxпакет , і на самому справі вдається відкрити великі файли Excel (> 1 500 рядків і стовпців> 120). @MichaelChirico демонструє, що readxlкраще, коли швидкість є кращою, і openxlsxзамінює функціональність, передбачену xlsxпакетом. Якщо ви шукаєте пакет для читання, запису та модифікації файлів Excel у 2015 році, виберіть openxlsxзамістьxlsx .

До 2015 року: я використовував xlsxпакет . Це змінило мій робочий процес із програмами 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

Ми бачимо мого власного улюбленця на xlsx60% повільніше, ніж readxl.

25 000-рядковий файл Excel

Через кількість часу я зробив лише 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 Я спочатку провів кілька тестів, 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 Довгий і навіть на вікнах це ПІТА. Немає сексуального часу для мене та 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. xlsxпакунок може обробляти однойменні розширення.


@Ben Thx за підказку, я включу це у свою відповідь. Однак я не намагався бути повним, оскільки сторінка wiki, на яку посилаються прийняті відповіді, вже досить повна. Але в ньому не згадується пакет 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)))).
Мікко

Це працює лише настільки, наскільки тип стовпця може бути адекватно визначений першим рядком. Зазвичай для цього визначають більше, ніж перший рядок. Відповідь можна покращити для вирішення коментаря 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")
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.