Un modo semplice per esportare più data.frame su più fogli di lavoro Excel


88

Sono sorpreso di scoprire che non esiste un modo semplice per esportare più data.frame su più fogli di lavoro di un file Excel? Ho provato il pacchetto xlsx , sembra che possa scrivere solo su un foglio (sovrascrivere il vecchio foglio); Ho anche provato il pacchetto WriteXLS , ma mi dà sempre errori ...

La struttura del mio codice è così: in base alla progettazione, per ogni iterazione, il dataframe di output (tempTable) e il sheetName (sn) sono stati aggiornati ed esportati in una scheda.

for (i in 2 : ncol(code)){ 
        ...
        tempTable <- ...
        sn <- ...
        WriteXLS("tempTable", ExcelFileName = "C:/R_code/../file.xlsx",
              SheetNames = sn);
}

Posso esportare in diversi file cvs, ma deve esserci un modo semplice per farlo in Excel, giusto?


3
Ti sbagli su xlsx . C'è una createSheetfunzione che ti permette di creare nuovi fogli e poi di scrivere su di essi, in un ciclo. Inoltre, le funzioni equivalenti in XLConnect sono vettorializzate, consentendo di scrivere un elenco di frame di dati su più fogli.
joran

@joran, createSheet viene utilizzato con addDataFrame non write.xlsx? L'ho visto prima nel documento ma non sono riuscito a capire l'intero processo.
Ogre Magi

Risposte:


149

Puoi scrivere su più fogli con il xlsxpacchetto. Devi solo usare un diverso sheetNameper ogni data frame e devi aggiungere append=TRUE:

library(xlsx)
write.xlsx(dataframe1, file="filename.xlsx", sheetName="sheet1", row.names=FALSE)
write.xlsx(dataframe2, file="filename.xlsx", sheetName="sheet2", append=TRUE, row.names=FALSE)

Un'altra opzione, che ti dà un maggiore controllo sulla formattazione e sulla posizione del data frame, è fare tutto all'interno del codice R / xlsx e quindi salvare la cartella di lavoro alla fine. Per esempio:

wb = createWorkbook()

sheet = createSheet(wb, "Sheet 1")

addDataFrame(dataframe1, sheet=sheet, startColumn=1, row.names=FALSE)
addDataFrame(dataframe2, sheet=sheet, startColumn=10, row.names=FALSE)

sheet = createSheet(wb, "Sheet 2")

addDataFrame(dataframe3, sheet=sheet, startColumn=1, row.names=FALSE)

saveWorkbook(wb, "My_File.xlsx")

Nel caso in cui potresti trovarlo utile, ecco alcune interessanti funzioni di supporto che rendono più facile aggiungere formattazione, metadati e altre funzionalità ai fogli di calcolo utilizzando xlsx: http://www.sthda.com/english/wiki/r2excel-read-write -e-formattare-facilmente-file-excel-utilizzando-r-software


xlsxnon si occupa dei numeri della prima riga che R ci mette. openxlsxrimuovili.
buhtz

1
Aggiungi row.names=FALSEper rimuovere i nomi delle righe.
eipi10

@EcologyTom Sono passato da xlsxa openxlsxqualche tempo fa, poiché lo trovo molto più intuitivo ed evita anche la dipendenza da java.
eipi10

Sì, la dipendenza da java mi ha costretto a fare lo stesso passaggio. Sebbene il codice sia un po 'più lungo, è piuttosto semplice. Per un metodo con la openxlsxversione 4.0 vedere la mia risposta supplementare di seguito.
EcologyTom

6
Sono solo io, o il foglio 2 scrive semplicemente sul foglio 1 quando si usa questo codice?
NewBee

94

È inoltre possibile utilizzare la libreria openxlsx per esportare più set di dati su più fogli in una singola cartella di lavoro.Il vantaggio di openxlsx rispetto a xlsx è che openxlsx rimuove le dipendenze dalle librerie java.

Scrivi un elenco di data.frames su singoli fogli di lavoro utilizzando i nomi degli elenchi come nomi di fogli di lavoro.

require(openxlsx)
list_of_datasets <- list("Name of DataSheet1" = dataframe1, "Name of Datasheet2" = dataframe2)
write.xlsx(list_of_datasets, file = "writeXLSX2.xlsx")

3
Ho usato questi pacchetti e penso che openxlsxsia il più veloce in quanto il suo c ++. XlConnectmangerà la tua RAM. Potresti voler fare alcuni benchmark tra xlsxeopenxlsx
Hanjo Jo'burg Odendaal

2
Un altro vantaggio di quel pacchetto è che si occupa della numerazione R nella prima riga.
buhtz

4
Grazie, openxlsx::write.xlsxè la strada da percorrere ... stavo salvando 11 fogli, ciascuno un dataframe 20.000x10, fatto un paio di secondi mentre si è verificato un errore xlsx::write.xlsxdopo aver aggiunto il secondo foglio conjava.lang.OutOfMemoryError: Java heap space
Djork

Avevo bisogno di aggiungere il parametro append=TRUEa write.xlsx per fargli scrivere più fogli contemporaneamente su un file Excel
mondano

Bello! Ho creato la mia lista come parte di un ciclo, e dovevo solo inizializzarla ( list_of_dfs <- list()) e poi riempirla, usando temp_key e temp_df costruiti durante il ciclo ( list_of_dfs[[temp_key]] = temp_df). È stato anche molto veloce nella scrittura, nonostante i 16 fogli che dovevo creare! Qualcuno ha assistito a problemi con la memoria durante la creazione?
Lionel Trebuchon

32

C'è una nuova biblioteca in città, da rOpenSci: writexl

Data frame portatile e leggero per esportatore xlsx basato su libxlsxwriter. Nessun Java o Excel richiesto

L'ho trovato migliore e più veloce dei suggerimenti sopra (lavorando con la versione dev):

library(writexl)
sheets <- list("sheet1Name" = sheet1, "sheet2Name" = sheet2) #assume sheet1 and sheet2 are data frames
write_xlsx(sheets, "path/to/location")

1
Grazie! Ha funzionato dove openxlsx non ha funzionato (non posso installare rtools al lavoro).
Ape

Quale versione usi per questo? Il download predefinito di cran non supporta più fogli (ancora): "Errore in writexl :: write_xlsx (list (...: L'argomento x deve essere un frame di dati o un elenco di frame di dati"
JAD

Come ho scritto, la versione dev.
Giora Simchoni

@ JarkoDubbeldam: ho installato il mio da cran e più fogli funzionano per me (R 3.3.0). Controlla se gli oggetti nella tua lista sono data.frames.
Ape

questo funziona davvero. Impossibile installare xlsx in r.
Cina

22

Molte buone risposte qui, ma alcune sono un po 'datate. Se desideri aggiungere ulteriori fogli di lavoro a un singolo file, questo è l'approccio che trovo funzioni per me. Per chiarezza, ecco il flusso di lavoro per la openxlsxversione 4.0

# Create a blank workbook
OUT <- createWorkbook()

# Add some sheets to the workbook
addWorksheet(OUT, "Sheet 1 Name")
addWorksheet(OUT, "Sheet 2 Name")

# Write the data to the sheets
writeData(OUT, sheet = "Sheet 1 Name", x = dataframe1)
writeData(OUT, sheet = "Sheet 2 Name", x = dataframe2)

# Export the file
saveWorkbook(OUT, "My output file.xlsx")

MODIFICARE

Ora ho provato alcune altre risposte e in realtà mi piace molto quella di @ Syed. Non sfrutta tutte le funzionalità di, openxlsxma se desideri un metodo di esportazione facile e veloce, questo è probabilmente il più semplice.


8

Non ho familiarità con il pacchetto WriteXLS; Generalmente utilizzo XLConnect:

library(XLConnect)
##
newWB <- loadWorkbook(
  filename="F:/TempDir/tempwb.xlsx",
  create=TRUE)
##
for(i in 1:10){
  wsName <- paste0("newsheet",i)
  createSheet(
    newWB,
    name=wsName)
  ##
  writeWorksheet(
    newWB,
    data=data.frame(
      X=1:10,
      Dataframe=paste0("DF ",i)),
    sheet=wsName,
    header=TRUE,
    rownames=NULL)
}
saveWorkbook(newWB)

Questo può certamente essere vettorializzato, come @joran ha notato sopra, ma solo per generare rapidamente nomi di fogli dinamici, ho usato un forciclo per dimostrare.

Ho usato l' create=TRUEargomento da loadWorkbookquando stavo creando un nuovo file .xlsx, ma se il tuo file esiste già, non devi specificarlo, poiché il valore predefinito è FALSE.

Ecco alcuni screenshot della cartella di lavoro creata:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


1
Non ho usato XLConnect, esempio molto dettagliato, grazie!
Ogre Magi

Prego, l'ho trovato un pacchetto molto utile. C'è una bella vignetta su CRAN che descrive in dettaglio alcune delle caratteristiche principali, con un bell'esempio nella sezione 4 che mostra come scrivere grafici R in un foglio di lavoro.
nrussell

5

Nel caso in cui la dimensione dei dati sia piccola, R ha molti pacchetti e funzioni che possono essere utilizzati secondo le tue esigenze.

Anche write.xlsx, write.xlsx2, XLconnect fanno il lavoro, ma a volte sono lenti rispetto a openxlsx .

Quindi, se hai a che fare con set di dati di grandi dimensioni e ti sei imbattuto in errori java. Suggerirei di dare un'occhiata a "openxlsx" che è davvero fantastico e ridurre il tempo a 1/12.

Ho provato tutto e alla fine sono rimasto davvero impressionato dalle prestazioni delle funzionalità di openxlsx.

Ecco i passaggi per scrivere più set di dati in più fogli.

 install.packages("openxlsx")
 library("openxlsx")

    start.time <- Sys.time()

    # Creating large data frame
    x <- as.data.frame(matrix(1:4000000,200000,20))
    y <- as.data.frame(matrix(1:4000000,200000,20))
    z <- as.data.frame(matrix(1:4000000,200000,20))

    # Creating a workbook
    wb <- createWorkbook("Example.xlsx")
    Sys.setenv("R_ZIPCMD" = "C:/Rtools/bin/zip.exe") ## path to zip.exe

Sys.setenv ("R_ZIPCMD" = "C: /Rtools/bin/zip.exe") deve essere statico in quanto prende riferimento ad alcune utility di Rtools.

Nota: Incase Rtools non è installato sul tuo sistema, installalo prima per un'esperienza fluida. ecco il link per il tuo riferimento: (scegli la versione appropriata)

https://cran.r-project.org/bin/windows/Rtools/ controlla le opzioni come da link sottostante (è necessario selezionare tutte le caselle di controllo durante l'installazione)

https://cloud.githubusercontent.com/assets/7400673/12230758/99fb2202-b8a6-11e5-82e6-836159440831.png

    # Adding a worksheets : parameters for addWorksheet are 1. Workbook Name 2. Sheet Name

    addWorksheet(wb, "Sheet 1")
    addWorksheet(wb, "Sheet 2")
    addWorksheet(wb, "Sheet 3")

    # Writing data in to respetive sheets: parameters for writeData are 1. Workbook Name 2. Sheet index/ sheet name 3. dataframe name

    writeData(wb, 1, x)

    # incase you would like to write sheet with filter available for ease of access you can pass the parameter withFilter = TRUE in writeData function.
    writeData(wb, 2, x = y, withFilter = TRUE)

    ## Similarly writeDataTable is another way for representing your data with table formatting:

    writeDataTable(wb, 3, z)

    saveWorkbook(wb, file = "Example.xlsx", overwrite = TRUE)

    end.time <- Sys.time()
    time.taken <- end.time - start.time
    time.taken

Il pacchetto openxlsx è davvero ottimo per leggere e scrivere dati enormi da / in file excel e ha molte opzioni per la formattazione personalizzata all'interno di Excel.

Il fatto interessante è che qui non dobbiamo preoccuparci della memoria java heap.


3

Ho avuto questo problema esatto e l'ho risolto in questo modo:

library(openxlsx) # loads library and doesn't require Java installed

your_df_list <- c("df1", "df2", ..., "dfn")

for(name in your_df_list){
  write.xlsx(x = get(name), 
             file = "your_spreadsheet_name.xlsx", 
             sheetName = name)
}

In questo modo non dovrai creare manualmente un elenco molto lungo se hai tonnellate di dataframe da scrivere in Excel.


3
Non so perché questo sovrascrive il primo foglio di lavoro
Lunalo John

Questo sovrascrive il foglio, io e altri abbiamo affrontato anche il problema. Guarda qui - stackoverflow.com/questions/57278418/…
Skurup

2

Uso regolarmente il rio confezionato per esportare tutti i tipi. Utilizzando rio, è possibile inserire un elenco, denominare ciascuna scheda e specificare il set di dati. rio compila altri pacchetti in / out e, per l'esportazione in Excel, utilizza openxlsx.

library(rio)

filename <- "C:/R_code/../file.xlsx"

export(list(sn1 = tempTable1, sn2 = tempTable2, sn3 = tempTable3), filename)

0

Per me, WriteXLSfornisce le funzionalità che stai cercando. Dato che non hai specificato quali errori restituisce, ti mostro un esempio:

Esempio

library(WriteXLS)
x <- list(sheet_a = data.frame(a=letters), sheet_b = data.frame(b = LETTERS))
WriteXLS(x, "test.xlsx", names(x))

Spiegazione

Se xè:

  • un elenco di frame di dati, ciascuno scritto su un singolo foglio
  • un vettore di caratteri (di oggetti R), ogni oggetto viene scritto su un singolo foglio
  • qualcos'altro, quindi guarda anche cosa dice la guida:

Maggiori informazioni sull'utilizzo

?WriteXLS

Spettacoli:

`x`: A character vector or factor containing the names of one or
     more R data frames; A character vector or factor containing
     the name of a single list which contains one or more R data
     frames; a single list object of one or more data frames; a
     single data frame object.

Soluzione

Per il tuo esempio, dovresti raccogliere tutti i data.frames in un elenco durante il ciclo e utilizzarli al WriteXLStermine del ciclo.

Informazioni sulla sessione

  • R 3.2.4
  • WriteXLS 4.0.0

Questo pacchetto funzionerà ma IMHO proverei a evitare la dipendenza di perl (poiché proverei a evitare la dipendenza di Java con xlsx) poiché rende più difficile la configurazione
R Yoda

0

Lo faccio in questo modo per openxlsx usando la seguente funzione

mywritexlsx<-function(fname="temp.xlsx",sheetname="Sheet1",data,
                  startCol = 1, startRow = 1, colNames = TRUE, rowNames = FALSE)
{
  if(! file.exists(fname))
    wb = createWorkbook()
  else
   wb <- loadWorkbook(file =fname)
  sheet = addWorksheet(wb, sheetname)

  writeData(wb,sheet,data,startCol = startCol, startRow = startRow, 
          colNames = colNames, rowNames = rowNames)
  saveWorkbook(wb, fname,overwrite = TRUE)
}

loadWorkbook è la chiave qui per aprire i file esistenti
makarand kulkarni

Inoltre, se si desidera scrivere formule per eccellere, esiste una funzione diversa denominata writeFormula, inoltre una volta scritta la formula il file deve essere aggiornato o riaperto, quindi salvato e quindi chiuso in Excel. demo è data qui [link ( stackoverflow.com/questions/46914303/... )
makarand Kulkarni

0

Lo faccio sempre, tutto quello che faccio è

WriteXLS::WriteXLS(
    all.dataframes,
    ExcelFileName = xl.filename,
    AdjWidth = T,
    AutoFilter = T,
    FreezeRow = 1,
    FreezeCol = 2,
    BoldHeaderRow = T,
    verbose = F,
    na = '0'
  )

e tutti quei frame di dati provengono da qui

all.dataframes <- vector()
for (obj.iter in all.objects) {
  obj.name <- obj.iter
  obj.iter <- get(obj.iter)
  if (class(obj.iter) == 'data.frame') {
      all.dataframes <- c(all.dataframes, obj.name)
}

ovviamente la routine sdolcinata sarebbe migliore qui


0

per una versione lapply-friendly ..

library(data.table)
library(xlsx)

path2txtlist <- your.list.of.txt.files
wb <- createWorkbook()
lapply(seq_along(path2txtlist), function (j) {
sheet <- createSheet(wb, paste("sheetname", j))
addDataFrame(fread(path2txtlist[j]), sheet=sheet, startColumn=1, row.names=FALSE)
})

saveWorkbook(wb, "My_File.xlsx")

1
Potresti aggiungere qualche descrizione a questa risposta per fornire un contesto su come risponde alla domanda?
tshimkus
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.