Łatwy sposób na eksport wielu data.frame do wielu arkuszy programu Excel


85

Zaskoczyło mnie, że nie ma łatwego sposobu na wyeksportowanie wielu data.frame do wielu arkuszy w pliku Excel? Wypróbowałem pakiet xlsx , wydaje się, że można pisać tylko na jednym arkuszu (nadpisać stary arkusz); Próbowałem też paczki WriteXLS , ale cały czas daje mi błąd ...

Moja struktura kodu jest następująca: zgodnie z projektem, dla każdej iteracji wyjściowa ramka danych (tempTable) i SheetName (sn) zostały zaktualizowane i wyeksportowane do jednej karty.

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

Mogę eksportować do kilku plików cvs, ale musi być na to łatwy sposób w Excelu, prawda?


3
Mylisz się co do xlsx . Istnieje createSheetfunkcja, która pozwala tworzyć nowe arkusze, a następnie pisać do nich w pętli. Dodatkowo równoważne funkcje w XLConnect są wektoryzowane, co pozwala na zapisywanie listy ramek danych na wielu arkuszach.
joran

@joran, createSheet jest używany z addDataFrame not write.xlsx? Widziałem to wcześniej w dokumencie, ale nie mogłem rozgryźć całego procesu.
Ogre Magi

Odpowiedzi:


145

Możesz pisać na wielu arkuszach z xlsxpaczką. Wystarczy użyć innej sheetNameramki dla każdej ramki danych i dodać 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)

Inną opcją, która zapewnia większą kontrolę nad formatowaniem i miejscem umieszczenia ramki danych, jest zrobienie wszystkiego w kodzie R / xlsx, a następnie zapisanie skoroszytu na końcu. Na przykład:

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

Jeśli uznasz to za przydatne, oto kilka interesujących funkcji pomocniczych, które ułatwiają dodawanie formatowania, metadanych i innych funkcji do arkuszy kalkulacyjnych za pomocą xlsx: http://www.sthda.com/english/wiki/r2excel-read-write -i-format-łatwo-pliki-excel-używając-oprogramowania-r


xlsxnie dba o liczby w pierwszym rzędzie R umieszczając tam. openxlsxUsuń ich.
buhtz

1
Dodaj, row.names=FALSEaby usunąć nazwy wierszy.
eipi10

@EcologyTom Przestawiłem się z xlsxna openxlsxjakiś czas temu, ponieważ uważam, że jest znacznie bardziej intuicyjny, a także unika zależności od Java.
eipi10

Tak, zależność od Java zmusiła mnie do wykonania tego samego przełącznika. Chociaż kod jest trochę dłuższy, jest dość prosty. Aby openxlsxzapoznać się z metodą z wersją 4.0, zobacz moją dodatkową odpowiedź poniżej.
Ecology Tom

2
Czy to tylko ja, czy arkusz 2 po prostu zapisuje arkusz 1, gdy używa się tego kodu?
NewBee

89

Możesz również użyć biblioteki openxlsx do wyeksportowania wielu zestawów danych do wielu arkuszy w jednym skoroszycie. Przewaga openxlsx nad xlsx polega na tym, że openxlsx usuwa zależności od bibliotek java.

Napisz listę data.frames do poszczególnych arkuszy, używając nazw list jako nazw arkuszy.

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

3
Użyłem tych pakietów i myślę, że openxlsxjest najszybszy, ponieważ jego c ++. XlConnectzje twój RAM. Może zechcesz zrobić kilka testów porównawczych między xlsxaopenxlsx
Hanjo Jo'burg Odendaal

2
Kolejną zaletą tego pakietu jest dbanie o numerację R w pierwszym rzędzie.
buhtz

4
Dzięki, openxlsx::write.xlsxto droga do zrobienia ... Zapisałem 11 arkuszy, każdy w ramce danych 20000x10, gotowe to kilka sekund, podczas gdy błąd xlsx::write.xlsxpo dołączeniu drugiego arkusza zjava.lang.OutOfMemoryError: Java heap space
Djork

Musiałem dodać parametr append=TRUEdo write.xlsx, aby zapisywał kilka arkuszy naraz do jednego pliku Excela
Mondano

Śliczny! Utworzyłem swoją listę jako część pętli i po prostu musiałem ją zainicjować ( list_of_dfs <- list()), a następnie wypełnić, używając temp_key i temp_df skonstruowanych podczas pętli ( list_of_dfs[[temp_key]] = temp_df). Pisanie było również bardzo szybkie, pomimo 16 arkuszy, które musiałem stworzyć! Czy ktoś był świadkiem problemów z pamięcią podczas tworzenia?
Lionel Trebuchon

30

W mieście jest nowa biblioteka od rOpenSci: writexl

Przenośna, lekka ramka danych do eksportera xlsx oparta na libxlsxwriter. Nie jest wymagana Java ani Excel

Znalazłem to lepiej i szybciej niż powyższe sugestie (praca z wersją dev):

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

1
Dzięki! To działało tam, gdzie openxlsx nie działało (nie mogę zainstalować rtools w pracy).
Ape

Której wersji używasz do tego? Domyślne pobieranie Crane nie obsługuje wielu arkuszy (jeszcze): `` Błąd w writexl :: write_xlsx (list (...: Argument x musi być ramką danych lub listą ramek danych '')
JAD

Jak napisałem, wersja dev.
Giora Simchoni

@JarkoDubbeldam: Zainstalowałem mój z żurawia i wiele arkuszy działa dla mnie (R 3.3.0). Sprawdź, czy obiekty na liście to data.frames.
Ape

to naprawdę działa. nie można zainstalować xlsx w r.
Cina

20

Wiele dobrych odpowiedzi tutaj, ale niektóre z nich są trochę przestarzałe. Jeśli chcesz dodać kolejne arkusze do jednego pliku, to jest to podejście, które uważam za skuteczne. Dla jasności, oto przepływ pracy dla openxlsxwersji 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")

EDYTOWAĆ

Wypróbowałem teraz kilka innych odpowiedzi i naprawdę lubię @ Syed's. Nie wykorzystuje wszystkich funkcji programu, openxlsxale jeśli chcesz mieć szybką i łatwą metodę eksportu, jest to prawdopodobnie najprostsza metoda.


8

Nie znam pakietu WriteXLS; Generalnie używam 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)

Można to z pewnością wektoryzować, jak zauważył @joran powyżej, ale tylko w celu szybkiego generowania dynamicznych nazw arkuszy użyłem forpętli do zademonstrowania.

Użyłem create=TRUEargumentu w, loadWorkbookponieważ tworzyłem nowy plik .xlsx, ale jeśli twój plik już istnieje, nie musisz tego określać, ponieważ wartość domyślna to FALSE.

Oto kilka zrzutów ekranu utworzonego skoroszytu:

wprowadź opis obrazu tutaj

wprowadź opis obrazu tutaj

wprowadź opis obrazu tutaj


1
Nie korzystałem z XLConnect, bardzo szczegółowy przykład, dzięki!
Ogre Magi

Nie ma za co - uznałem, że to bardzo przydatny pakiet. W CRAN jest całkiem niezła winieta, która szczegółowo opisuje niektóre z głównych funkcji, z ładnym przykładem w sekcji 4 pokazującym, jak zapisywać wykresy R w arkuszu.
nrussell

5

Rozmiar danych Incase jest niewielki, R ma wiele pakietów i funkcji, które można wykorzystać zgodnie z wymaganiami.

write.xlsx, write.xlsx2, XLconnect również działają, ale czasami są one powolne w porównaniu do openxlsx .

Tak więc, jeśli masz do czynienia z dużymi zestawami danych i napotkałeś błędy Java. Proponuję spojrzeć na „openxlsx”, co jest naprawdę niesamowite i skrócić czas do 1/12.

Przetestowałem wszystko i ostatecznie byłem pod wielkim wrażeniem wydajności możliwości openxlsx.

Oto kroki, aby zapisać wiele zestawów danych w wielu arkuszach.

 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") musi być statyczny, ponieważ pobiera odniesienie do jakiegoś narzędzia z Rtools.

Uwaga: narzędzie Incase Rtools nie jest zainstalowane w twoim systemie, zainstaluj go najpierw, aby uzyskać płynne działanie. tutaj jest link do twojego odniesienia: (wybierz odpowiednią wersję)

https://cran.r-project.org/bin/windows/Rtools/ sprawdź opcje zgodnie z poniższym linkiem (podczas instalacji należy zaznaczyć wszystkie pola wyboru)

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

openxlsxPakiet jest naprawdę dobry do czytania i zapisywania ogromnych danych z / w plikach Excela i ma wiele opcji niestandardowego formatowania w programie Excel.

Ciekawostką jest to, że nie musimy się tutaj przejmować pamięcią stosu Java.


3

Miałem dokładnie ten problem i rozwiązałem go w ten sposób:

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

W ten sposób nie będziesz musiał ręcznie tworzyć bardzo długiej listy, jeśli masz mnóstwo ramek danych do zapisania w programie Excel.


2
Nie wiem, dlaczego to nadpisuje pierwszy arkusz
roboczy

1

Regularnie używam zapakowanego rio do eksportu wszelkiego rodzaju. Używając rio, możesz wprowadzić listę, nazwać każdą kartę i określić zestaw danych. rio kompiluje inne pakiety wejścia / wyjścia, a do eksportu do Excela używa openxlsx.

library(rio)

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

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

0

Dla mnie WriteXLSzapewnia funkcjonalność, której szukasz. Ponieważ nie określiłeś, które błędy zwraca, pokażę ci przykład:

Przykład

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

Wyjaśnienie

Jeśli xjest:

  • lista ramek danych, każda z nich jest zapisywana na pojedynczym arkuszu
  • wektor znaków (obiektów R), każdy obiekt jest zapisywany na pojedynczym arkuszu
  • coś innego, a następnie zobacz również, co stwierdza pomoc:

Więcej o użytkowaniu

?WriteXLS

przedstawia:

`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.

Rozwiązanie

Na przykład musisz zebrać wszystkie data.frames na liście podczas pętli i użyć ich WriteXLSpo zakończeniu pętli.

Informacje o sesji

  • R 3.2.4
  • Napisz XLS 4.0.0

Ten pakiet będzie działał, ale IMHO spróbuję uniknąć zależności perl (tak jak próbowałbym uniknąć zależności Javy z xlsx), ponieważ utrudnia to konfigurację
R Yoda

0

Robię to w ten sposób dla openxlsx używając następującej funkcji

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 jest tutaj kluczem do otwierania istniejących plików
makarand kulkarni

Również jeśli ktoś chce pisać formuły do ​​programu Excel, to jest inna funkcja o nazwie writeFormula, dodatkowo po napisaniu formuły plik musi zostać odświeżony lub ponownie otwarty, a następnie zapisany, a następnie zamknięty w programie Excel. demo jest podane tutaj [link ( stackoverflow.com/questions/46914303/… )
makarand kulkarni

0

Robię to cały czas, jedyne co robię to

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

i wszystkie te ramki danych pochodzą stąd

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

oczywiście rozsądna rutyna byłaby tutaj lepsza


0

dla wersji przyjaznej dla aplikacji.

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
Czy mógłbyś dodać jakiś opis do tej odpowiedzi, aby podać kontekst, w jaki sposób odpowiada ona na pytanie?
tshimkus
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.