Bir Excel dosyasını doğrudan bir R komut dosyasından okuyun


95

Bir Excel dosyasını doğrudan R'ye nasıl okuyabilirim? Veya önce verileri bir metin veya CSV dosyasına aktarmalı ve bu dosyayı R'ye mi aktarmalıyım?


@Sacha Epskamp: xlsReadWrite ile Perl'i kurmanıza bile gerek yok.
Joris Meys

1
gdatasürüm 2.8.2 xlsx, read.xlsfonksiyona sahip dosyaları okur
Ben

1
Verileri Excel'den bir metin biçiminde dışa aktarırsanız olası hassasiyet kaybıyla ilgili uyarıma (aşağıda bir yanıt olarak) bakın.
russellpierce

1
xlsxxlsx / xlsm / xls için paket, xlam vb. hakkında bilmiyorum.
Qbik

2
"Önce bir metin dosyasına aktarmamak için bir neden görmüyorum". Şuna ne dersin: CSV'ye aktardığımda ihtiyacım olan alanlardan biri yazılmıyor. Bir çeşit DRM gibi görünüyor ama elektronik tabloyu yazmadığım için bilmiyorum.
Nate Reed

Yanıtlar:


41

Evet. R wiki'deki ilgili sayfaya bakın . Kısa cevap: read.xlsgelen gdatapaket Perl sisteminizde yüklü olması gerekmektedir rağmen (çoğu zaman işleri - MacOS ve Linux üzerinde genellikle Zaten gerçek değil, Windows üzerinde fazladan bir adım attı, yani bakın http://strawberryperl.com/ ). R wiki sayfasında listelenen çeşitli uyarılar ve alternatifler vardır.

Bunu doğrudan yapmamamın tek nedeni, e-tabloyu inceleyerek hatalar olup olmadığını görmek isteyebilmenizdir (tuhaf başlıklar, birden çok çalışma sayfası [her seferinde yalnızca birini okuyabilirsiniz, ancak bunların hepsinin üzerinden geçebilirsiniz] , dahil araziler vb.). Ancak, düz sayılar ve karakter verileri içeren iyi biçimlendirilmiş, dikdörtgen bir elektronik tablo için (yani virgülle biçimlendirilmemiş sayılar, tarihler, sıfıra bölme hataları içeren formüller, eksik değerler vb.) bu süreç ile.


6
Şahsen karşılaştığımı düşünmem gereken birçok potansiyel sorun var. Virgül içeren sayılara sahip alanlar çıkarılmalı ve R'de sayısal hale dönüştürülmelidir. "-" olan alanların NA olarak yeniden kodlanması gerekir. Genel öneri, sayılarınıza gerçekten Excel'de bakmanız ve bunların doğru şekilde R'ye çevrildiğinden emin
olmanızdır

3
"Rakamlarınıza gerçekten bakmanız gerekiyor" ile tartışamıyorum ... "-" alanlarıyla ilgili sorun nedir? yok na.strings="-"sorunu ele? Bu sorunlardan kaç tanesi geneldir ve bunlardan kaç tanesi (örneğin virgül içeren sayısal alanlar) XLConnect ... gibi diğer araçlarla ele alınabilir?
Ben Bolker

1
Bu yorum OP'ye yöneltildi, sana değil Ben, kötü yerleştirme için benim hatam.
Brandon Bertelsen

1
İlgili anekdot: read.xlsnereye hem bir Excel dosyasından çok büyük bir levha okuma başarılı XLConnectve xlsxbaşarısız (her ikisi de güvenmek çünkü inanıyorum Apache POI )
Matt Parker

49

@Chase'in önerdiği şeyi tekrarlayayım: XLConnect kullanın .

Bence XLConnect kullanmanın nedenleri:

  1. Çapraz platform. XLConnect, Java ile yazılmıştır ve bu nedenle, R kodunuzda değişiklik olmaksızın (muhtemelen yol dizeleri hariç) Win, Linux, Mac üzerinde çalışacaktır
  2. Yüklenecek başka bir şey yok. Sadece XLConnect'i kurun ve hayata devam edin.
  3. Yalnızca Excel dosyalarını okumaktan bahsettiniz, ancak XLConnect, hücre biçimlendirmesini değiştirmek de dahil olmak üzere Excel dosyaları da yazacak. Ve bunu sadece Win'den değil, Linux veya Mac'ten yapacak.

XLConnect, diğer çözümlere kıyasla biraz yenidir, bu nedenle blog yazılarında ve referans belgelerinde daha az sıklıkla bahsedilir. Benim için çok faydalı oldu.


48

Ve şimdi readxl var :

Readxl paketi, Excel'den R'ye veri almayı kolaylaştırır. Mevcut paketlerle karşılaştırıldığında (örn. Gdata, xlsx, xlsReadWrite vb.) Readxl'in harici bağımlılıkları yoktur, bu nedenle tüm işletim sistemlerinde kurulumu ve kullanımı kolaydır. Tek bir sayfada depolanan tablo verileriyle çalışmak üzere tasarlanmıştır.

readxl, temelde yatan ikili biçimin karmaşıklıklarının çoğunu soyutlayan libxls C kitaplığının üzerine inşa edilmiştir.

Hem eski .xls biçimini hem de .xlsx'i destekler

readxl, CRAN'da mevcuttur veya github'dan şu şekilde yükleyebilirsiniz:

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

Kullanım

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

Açıklamada 'harici bağımlılık yok' derken, Rcpppaketi gerektirdiğini ve bunun da Rtools (Windows için) veya Xcode (OSX için) gerektirdiğini unutmayın; bunlar R'ye harici bağımlılıklardır , ancak birçok kişi başka nedenlerle bunları yüklemiştir .


3
Xlsx'ten çok daha hızlı. Okuma süresi read.xlsx2 gibidir, ancak türleri çıkarır.
Steve Rowe

1
@SteveRowe, bunu doğrulayan bazı (denenen) objektif kriterler için yeni cevabı görüyor
MichaelChirico

Dizeleri kullanan faktörler olarak okumanın bir yolu var mı read_excel? İle karşılaştırıldığında hızı seviyorum read.xlsx, ancak daha sonra sütunları karakterlerden faktörlere manuel olarak dönüştürmek, amacı bozuyor.
coip

2
Bağımlılığı olmadığı için +1. Java yüklemek zorunda kalmaktan nefret ediyorum. Ve denedim ve benim için çok iyi çalışıyor.
Bastian

2
readxl ve openxlsx en iyisidir. readxl daha hızlıdır ancak yazmaya izin vermez. Her neyse, sütun sınıflarını / türlerini belirtmeye çalışırken hiçbiri iyi çalışmıyor.
Skan

29

DÜZENLEME 2015-Ekim: Diğerlerinin burada yorumladığı gibi openxlsxve readxlpaketleri paketten çok daha hızlıdır xlsxve aslında daha büyük Excel dosyalarını (> 1500 satır ve> 120 sütun) açmayı başarır. @MichaelChirico readxl, hız tercih edildiğinde bunun daha iyi olduğunu openxlsxve xlsxpaket tarafından sağlanan işlevselliğin yerini aldığını gösteriyor . 2015'te Excel dosyalarını okumak, yazmak ve değiştirmek için bir paket arıyorsanız, openxlsxbunun yerine xlsx.

2015 Öncesi: xlsxPaket kullandım . Excel ve R ile iş akışımı değiştirdi. Excel sayfamı .txt formatında kaydetmek isteyip istemediğimi soran can sıkıcı pop-up'lara son. Paket ayrıca Excel dosyalarını da yazar.

Ancak, read.xlsxbüyük Excel dosyalarını açarken işlevi yavaş buluyorum . read.xlsx2işlevi önemli ölçüde daha hızlıdır, ancak data.frame sütunlarının vektör sınıfını sorgulamaz. Fonksiyonu colClasseskullanıyorsanız, istenen sütun sınıflarını belirtmek için command kullanmanız read.xlsx2gerekir. İşte pratik bir örnek:

read.xlsx("filename.xlsx", 1)dosyanızı okur ve data.frame sütun sınıflarını neredeyse kullanışlı hale getirir, ancak büyük veri kümeleri için çok yavaştır. .xlsDosyalar için de çalışır .

read.xlsx2("filename.xlsx", 1)daha hızlıdır, ancak sütun sınıflarını manuel olarak tanımlamanız gerekecektir. Bir kısayol, komutu iki kez çalıştırmaktır (aşağıdaki örneğe bakın). characterbelirtim, sütunlarınızı faktörlere dönüştürür. Zaman için kullanım Dateve POSIXctseçenekler.

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

Bir Excel dosyasını okumanın farklı yollarının çoğalması Rve buradaki yanıtların bolluğu göz önüne alındığında, burada bahsedilen seçeneklerden hangisinin en iyi performansı gösterdiğine ışık tutmaya çalışacağımı düşündüm (birkaç basit durumda).

Kullanmaya xlsxbaşladığımdan beri R, başka hiçbir şey olmasa bile atalet için kullanıyorum ve son zamanlarda hangi paketin daha iyi çalıştığına dair herhangi bir objektif bilgi olmadığını fark ettim.

Bazı paketler belirli durumları diğerlerinden daha iyi ele aldığından ve diğer uyarılardan oluşan bir şelale olduğundan, herhangi bir kıyaslama alıştırması zorluklarla doludur.

Bununla birlikte, oldukça yaygın bir biçimde olduğunu düşündüğüm (yeniden üretilebilir) bir veri kümesi kullanıyorum (8 dize alanı, 3 sayısal, 1 tam sayı, 3 tarih):

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

Sonra sonra bu parçacığı belirtilen paketlerin 4 benchmarked, csv bu yazmış ve LibreOffice açıldı ve bir .xlsx dosyası olarak kaydedilir: xlsx, openxlsx, readxl, ve gdata, varsayılan seçenekleri kullanarak (Ben de bir sürümünü denedik olsun veya olmasın ben sütun türlerini belirtin, ancak bu sıralamaları değiştirmedi).

Dışlıyorum RODBCçünkü Linux'tayım; XLConnectçünkü birincil amacı tek Excel sayfalarında okumak değil, tüm Excel çalışma kitaplarını içe aktarmak gibi görünüyor, bu nedenle yarışa sadece okuma yeteneklerini koymak haksız görünüyor; ve xlsReadWriteartık benim sürümümle uyumlu olmadığı için R(aşamalı olarak kullanımdan kaldırılmış gibi görünüyor).

Daha sonra Excel dosya boyutuna göre farklılıklara izin vermek için NN=1000Lve NN=25000L( data.frameyukarıdaki her bildirimden önce tohumu sıfırlayarak) ile karşılaştırmalar yaptım . gcÖncelikle xlsxbulduğum için, zaman zaman bellek tıkanıklıkları oluşturabilir. Daha fazla uzatmadan bulduğum sonuçlar şunlardır:

1.000 Satır Excel Dosyası

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

Rekabetçi ve açık bir kaybedenle readxlkazanan da öyle . Her ölçüyü minimum sütuna göre almak:openxlsxgdata

#       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

Kendi favorimin xlsx% 60 daha yavaş olduğunu görüyoruz readxl.

25.000 Satır Excel Dosyası

Aldığı süre nedeniyle büyük dosyada yalnızca 20 tekrar yaptım, aksi takdirde komutlar aynıydı. İşte ham veriler:

# 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

İşte göreceli veriler:

#       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

Yani readxlbu hıza gelince eşi yoktur. gdataExcel dosyalarını okumada acı verici bir şekilde yavaş olduğundan ve bu sorun yalnızca daha büyük tablolarda daha da arttığından, bunun için başka bir şey yapsanız iyi olur.

İki çekiliş openxlsxşunlardır: 1) kapsamlı diğer yöntemleri ( muhtemelen neden bu kadar hızlı olduğunun bir parçası olan tek bir şeyi readxlyapmak için tasarlanmıştır ), özellikle de write.xlsxişlevi ve 2) (daha çok dezavantajı readxl) col_typesargümanın readxlyalnızca ( Bu yazı) bazı standart olmayanları kabul eder R: "text"yerine "character"ve "date"yerine "Date".


XLConnect için kriter de eklerseniz harika olur. Ayrıca readxl'in yazamayacağı yorumunu yapın. xlsx ve openxlsx, col_types veya colClasses seçeneğiyle düzgün çalışmaz.
skan

@skan ile başlangıçta bazı testler yaptım XLConnectama çok yavaş; readxlSon paragrafımda dezavantajlarının yeterince ele alındığına inanıyorum ; ve birlikte sizinkine benzer hiçbir deneyime sahip xlsxveya openxlsxdüzenli türlerini belirtmek için hem kullandıkça.
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)

Şahsen, RODBC'yi seviyorum ve tavsiye edebilirim.


7
Uyarı: ODBC'nin Windows dışındaki platformlarda çalışması bazen zor olabilir.
JD Long

1
@JD Long ve hatta pencerelerde bir PITA. 64 bit
W7'de

4
Gerekli paket yükleniyor: odbcConnectExcel'de RODBC Hatası (dosya.adı): odbcConnectExcel yalnızca 32 bit Windows ile kullanılabilir
andrekos


6

Başka bir çözüm, xlsReadWriteek kurulum gerektirmeyen ancak ilk kez kullanmadan önce ek shlib'i indirmenizi gerektiren pakettir:

require(xlsReadWrite)
xls.getshlib()

Bunu unutmak tamamen hayal kırıklığına neden olabilir. Orada bulundum ve tüm bunlar ...

Bir notta: Metin tabanlı bir biçime (örn. Csv) dönüştürmeyi ve oradan okumayı düşünebilirsiniz. Bu, birkaç nedenden dolayı:

  • çözümünüz ne olursa olsun (RODBC, gdata, xlsReadWrite) verileriniz dönüştürüldüğünde bazı garip şeyler olabilir. Özellikle tarihler oldukça külfetli olabilir. HFWutilsPaketi (@Ben Bolker yorumuna göre) EXCEL tarihleri ile başa çıkmak için bazı araçlara sahiptir.

  • büyük sayfalarınız varsa, metin dosyalarında okumak EXCEL'den okumaktan daha hızlıdır.

  • .xls ve .xlsx dosyaları için farklı çözümler gerekli olabilir. Örneğin, xlsReadWrite paketi şu anda .xlsx AFAIK'i desteklemiyor. gdata.xlsx desteği için ek perl kitaplıkları kurmanızı gerektirir. xlsxpaket aynı isimdeki uzantıları işleyebilir.


@Ben Thx ipucu için cevabıma ekleyeceğim. Yine de tamamlamaya çalışmadım, çünkü kabul edilen cevap bağlantılarının bulunduğu wiki sayfası zaten tamamlanmış durumda. Ancak HFWutils paketinden bahsetmiyor.
Joris Meys

1
-1; Cevabımı gör. TL: DR: Excel, tam bir hassas veri kümesini csv'ye (veya panoya) kaydetmez. Yalnızca görünen değerler korunur.
russellpierce

5

Yukarıda diğer yanıtların çoğunda belirtildiği gibi, XLS / X dosyasına bağlanan ve verileri makul bir şekilde alan birçok iyi paket vardır. Ancak, Excel'den veri almak için hiçbir koşulda pano (veya bir .csv) dosyasını kullanmamanız gerektiği konusunda uyarılmanız gerekir. Nedenini görmek için excel'de =1/3bir hücreye girin . Şimdi, görebileceğiniz ondalık nokta sayısını ikiye indirin. Ardından verileri kopyalayıp R'ye yapıştırın. Şimdi CSV'yi kaydedin. Her iki durumda da Excel'in yalnızca arabirim aracılığıyla görebileceğiniz verileri tuttuğunu ve gerçek kaynak verilerinizdeki tüm hassasiyeti kaybettiğinizi fark edeceksiniz.


1
Sayısal sadakatin kimin alakalı / önemli olmadığını düşündüğünü bilmek isterim.
russellpierce

1
İyi uyarı. Ancak kullandığınız pakete bağlıdır. bazıları bu tuzağa düşmüyor.
RockScience

@RocketScience Bu, Excel ile CSV dışa aktarmada temel bir tasarım seçimidir. Panoyu kullanan ve bu sorunu olmayan bir paket örneğiniz var mı? Doğrudan xls xlsx dosyasını ayrıştıran paketler bu tuzağa düşmemeye meyilli olacaktır. Böylece, uyarımın özel kapsamı.
russellpierce

Unix'te deneyebilirsiniz gnumeric::read.gnumeric.sheet. Windows'ta% 100 emin değilim, ancak gdata::read.xlsiyi çalışması gerektiğini düşünüyorum (yine de perl yüklemem gerekiyor)
RockScience

@RockScience Saygılarımla, gdata :: read.xls pano verileri üzerinde çalışmaz (yolunuzdan çekilmediğiniz sürece) ve gnumeric Excel değildir. Yani, olağanüstü kanıt yok, uyarım geçerli. Bu soruya yanıt olarak başka pek çok iyi seçenek var - umalım ki insanlar bunun yerine bunları kullansın.
russellpierce

5

@Mikko tarafından sağlanan yanıtı genişleterek, sütun sınıflarınızı önceden "bilmek" zorunda kalmadan işleri hızlandırmak için düzgün bir numara kullanabilirsiniz. Basitçe kullanmak read.xlsxsınıfları belirlemek için kayıtlar sınırlı sayıda kapmak için ve daha sonra bunu takipread.xlsx2

Misal

# 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
Çözümün döndürür numericiçin factorsbilgisayarımda. read.xlsxkullanımları characteriçinde readColumnsişleve faktörlerini belirlemek için. Emin orada karakterler gibi faktörleri almanın daha zarif bir yoldur, ama burada fonksiyonunun değiştirilmiş versiyonu olduğumu çalışır: df.real <- read.xlsx2("filename.xlsx", 1, colClasses=gsub("factor", "character", as.vector(sapply(df.temp, class)))).
Mikko

Bu, yalnızca sütun türünün ilk satır tarafından yeterince belirlenebildiği ölçüde çalışır. Bu belirlemeyi yapmak için genellikle ilk satırdan daha fazlasını ayrıştırır. Cevap, aaa90210'un açıklamasını ele almak için, bu işlevlerin geldiği paketi adlandırarak geliştirilebilir.
russellpierce

1

Bir Excel dosyası aşağıdaki gibi doğrudan R'ye okunabilir:

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

Readxl paketini kullanarak xls ve xlxs dosyalarını okuma

library("readxl")
my_data <- read_excel("xxxxx.xls")
my_data <- read_excel("xxxxx.xlsx")
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.