Простой способ экспортировать несколько data.frame на несколько листов Excel

88

Я удивлен, обнаружив, что нет простого способа экспортировать несколько data.frame на несколько листов файла Excel? Я пробовал пакет xlsx , кажется, он может писать только на один лист (переопределить старый лист); Я также пробовал пакет WriteXLS , но он все время выдает ошибку ...

Моя структура кода такова: по замыслу, для каждой итерации выходной фрейм данных (tempTable) и имя листа (sn) обновлялись и экспортировались в одну вкладку.

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

Я могу экспортировать в несколько файлов cvs, но должен быть простой способ сделать это в Excel, верно?

Ogre Magi
источник
3
Вы ошибаетесь насчет xlsx . Есть createSheetфункция, которая позволяет вам создавать новые листы, а затем записывать на них в цикле. Кроме того, эквивалентные функции в XLConnect векторизованы, что позволяет записывать список фреймов данных на несколько листов.
Joran
@joran, createSheet используется с addDataFrame, а не с write.xlsx? Я видел это ранее в документе, но не мог понять весь процесс.
Ogre Magi

Ответы:

149

Вы можете писать на нескольких листах с xlsxпакетом. Вам просто нужно использовать разные sheetNameдля каждого фрейма данных, и вам нужно добавить 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)

Другой вариант, который дает вам больше контроля над форматированием и местом размещения фрейма данных, - это делать все в рамках кода R / xlsx, а затем сохранять книгу в конце. Например:

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

Если вы сочтете это полезным, вот несколько интересных вспомогательных функций, которые упрощают добавление форматирования, метаданных и других функций в электронные таблицы, используя xlsx: http://www.sthda.com/english/wiki/r2excel-read-write -and-format-easy-excel-files-using-r-software

eipi10
источник
xlsxне заботится о числах в первой строке R. openxlsxудалить их.
buhtz
1
Добавить, row.names=FALSEчтобы удалить имена строк.
eipi10
@EcologyTom Я перешел xlsxна openxlsxнекоторое время назад, так как считаю его гораздо более интуитивным, а также позволяет избежать зависимости от java.
eipi10
Да, зависимость от java заставила меня сделать такой же переход. Хотя код немного длиннее, он довольно прост. Для метода с openxlsxверсией 4.0 см. Мой дополнительный ответ ниже.
EcologyTom
6
Это только у меня, или лист 2 просто пишет поверх листа 1, когда используется этот код?
NewBee
94

Вы также можете использовать библиотеку openxlsx для экспорта нескольких наборов данных на несколько листов в одной книге. Преимущество openxlsx над xlsx заключается в том, что openxlsx удаляет зависимости от библиотек java.

Напишите список data.frames на отдельные рабочие листы, используя имена списков в качестве имен рабочих листов.

require(openxlsx)
list_of_datasets <- list("Name of DataSheet1" = dataframe1, "Name of Datasheet2" = dataframe2)
write.xlsx(list_of_datasets, file = "writeXLSX2.xlsx")
Сайед
источник
3
Я использовал эти пакеты и считаю, что openxlsxэто самый быстрый, как его C ++. XlConnectсъест вашу оперативную память. Возможно, вы захотите провести сравнительный анализ между xlsxиopenxlsx
Хандзё Йобург Одендал
2
Еще одно преимущество этого пакета состоит в том, что он заботится о нумерации R в первой строке.
buhtz
4
Спасибо, openxlsx::write.xlsxэто способ пойти ... Я сохранял 11 листов, каждый из которых представлял собой фрейм данных 20,000x10, готово за пару секунд, пока был xlsx::write.xlsxошибкой после добавления второго листа сjava.lang.OutOfMemoryError: Java heap space
Djork
Мне нужно было добавить параметр append=TRUEв write.xlsx, чтобы он записывал сразу несколько листов в один файл Excel
mondano
Прекрасно! Я создал свой список как часть цикла, и мне просто нужно было инициализировать его ( list_of_dfs <- list()), а затем заполнить его, используя temp_key и temp_df, созданные во время цикла ( list_of_dfs[[temp_key]] = temp_df). Это было также очень быстро в написании, несмотря на то, что мне нужно было создать 16 листов! Кто-нибудь был свидетелем проблем с памятью при создании?
Lionel Trebuchon
32

В городе появилась новая библиотека от rOpenSci: writexl

Портативный, легкий фрейм данных для экспортера xlsx на основе libxlsxwriter. Не требуется Java или Excel

Я нашел это лучше и быстрее, чем приведенные выше предложения (работа с версией для разработчиков):

library(writexl)
sheets <- list("sheet1Name" = sheet1, "sheet2Name" = sheet2) #assume sheet1 and sheet2 are data frames
write_xlsx(sheets, "path/to/location")
Джора Симчони
источник
1
Благодаря! Это сработало там, где не работал openxlsx (я не могу установить rtools на работе).
Ape
Какую версию вы для этого используете? Загрузка Cran по умолчанию не поддерживает несколько листов (пока): 'Ошибка в writexl :: write_xlsx (list (...: аргумент x должен быть фреймом данных или списком фреймов данных' '
JAD
Как я уже писал, версия для разработчиков.
Giora Simchoni
@JarkoDubbeldam: Я установил свой из крана, и у меня работают несколько листов (R 3.3.0). Проверьте, являются ли объекты в вашем списке data.frames.
Ape
это действительно работает. не удалось установить xlsx в r.
Cina
22

Здесь много хороших ответов, но некоторые из них немного устарели. Если вы хотите добавить дополнительные рабочие листы в один файл, то этот подход, который я считаю, работает для меня. Для наглядности вот рабочий процесс для openxlsxверсии 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")

РЕДАКТИРОВАТЬ

Теперь я попробовал несколько других ответов, и мне действительно нравится @Syed. Он не использует все функциональные возможности, openxlsxно если вам нужен быстрый и простой метод экспорта, то это, вероятно, самый простой способ.

Экология
источник
8

Я не знаком с пакетом WriteXLS; Обычно я использую 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)

Это, безусловно, можно векторизовать, как отметил @joran выше, но просто для быстрого создания динамических имен листов я использовал forцикл для демонстрации.

Я использовал create=TRUEаргумент в, loadWorkbookпоскольку я создавал новый файл .xlsx, но если ваш файл уже существует, вам не нужно указывать его, поскольку это значение по умолчанию FALSE.

Вот несколько скриншотов созданной книги:

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

Nrussell
источник
1
Я не использовал XLConnect, очень подробный пример, спасибо!
Ogre Magi
Пожалуйста - я нашел это очень полезным пакетом. На CRAN есть довольно хорошая виньетка, в которой подробно описаны некоторые из основных функций, с хорошим примером в разделе 4, демонстрирующим, как записывать графики R в рабочий лист.
nrussell
5

Если размер данных невелик, в R есть много пакетов и функций, которые можно использовать в соответствии с вашими требованиями.

write.xlsx, write.xlsx2, XLconnect также выполняют свою работу, но иногда они медленнее по сравнению с openxlsx .

Итак, если вы имеете дело с большими наборами данных и сталкивались с ошибками java. Я бы посоветовал взглянуть на "openxlsx", который действительно потрясающий, и сократить время до 1/12 .

Я протестировал все и, наконец, был действительно впечатлен производительностью возможностей openxlsx.

Вот шаги для записи нескольких наборов данных на несколько листов.

 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") должен быть статическим, так как он принимает ссылку на некоторую утилиту из Rtools.

Примечание. Если в вашей системе не установлен Rtools, сначала установите его для бесперебойной работы. вот ссылка для справки: (выберите подходящую версию)

https://cran.r-project.org/bin/windows/Rtools/ проверьте параметры по ссылке ниже (необходимо установить все флажки во время установки)

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

Пакет openxlsx действительно хорош для чтения и записи огромных данных из / в файлы Excel и имеет множество опций для пользовательского форматирования в Excel.

Интересным фактом является то, что нам не нужно беспокоиться о памяти кучи java здесь.

Аюш Варшней
источник
3

У меня была именно такая проблема, и я решил ее так:

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

Таким образом, вам не придется вручную создавать очень длинный список, если у вас есть масса фреймов данных для записи в Excel.

Алексматиос
источник
3
Я не знаю, почему это перезаписывает первый рабочий лист
Лунало Джон
Это действительно перезаписывает лист, я и другие тоже столкнулись с этой проблемой. Посмотрите здесь - stackoverflow.com/questions/57278418/…
Skurup
2

Я регулярно использую упакованный рио для экспорта всех видов. Используя rio, вы можете ввести список, назвав каждую вкладку и указав набор данных. rio компилирует другие пакеты ввода / вывода и для экспорта в Excel использует openxlsx.

library(rio)

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

export(list(sn1 = tempTable1, sn2 = tempTable2, sn3 = tempTable3), filename)
24lindsey
источник
0

На мой WriteXLSвзгляд , предоставляет функциональность, которую вы ищете. Поскольку вы не указали, какие ошибки он возвращает, я покажу вам пример:

пример

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

Объяснение

Если xэто:

  • список фреймов данных, каждый записывается на отдельный лист
  • вектор символов (из R объектов), каждый объект записывается на отдельный лист
  • что-то еще, затем посмотрите также, что указано в справке:

Подробнее об использовании

?WriteXLS

показывает:

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

Решение

В вашем примере вам нужно будет собрать все data.frames в списке во время цикла и использовать WriteXLSпосле завершения цикла.

Информация о сеансе

  • R 3.2.4
  • WriteXLS 4.0.0
Setempler
источник
Этот пакет будет работать, но ИМХО, я бы попытался избежать зависимости от perl (поскольку я бы попытался избежать зависимости от Java xlsx), поскольку это затрудняет настройку
Р Йода
0

Я делаю это для openxlsx, используя следующую функцию

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 является ключом к открытию существующих файлов
Макаранд Кулькарни
Также, если кто-то хочет написать формулы для Excel, существует другая функция с именем writeFormula, кроме того, после того, как вы напишете формулу, файл необходимо обновить или повторно открыть, затем сохранить, а затем закрыть в Excel. демо приведено здесь [ссылка ( stackoverflow.com/questions/46914303/… )
makarand kulkarni
0

Я делаю это все время, все, что я делаю, это

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

и все эти фреймы данных берутся отсюда

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

очевидно, что здесь лучше бы слаженная рутина

Суман C
источник
0

для дружественной по-ласки версии ..

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")
MinimaMoralia
источник
1
Не могли бы вы добавить описание к этому ответу, чтобы пояснить, как он отвечает на вопрос?
tshimkus