Una forma sencilla de exportar varios marcos de datos a varias hojas de cálculo de Excel

85

Me sorprende descubrir que no hay una manera fácil de exportar múltiples data.frame a múltiples hojas de trabajo de un archivo de Excel. Probé xlsx paquete, parece que sólo se puede escribir en una hoja (hoja anular de edad); También probé el paquete WriteXLS , pero me da errores todo el tiempo ...

Mi estructura de código es así: por diseño, para cada iteración, el marco de datos de salida (tempTable) y el sheetName (sn) se actualizaron y exportaron a una pestaña.

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

Puedo exportar a varios archivos cvs, pero tiene que haber una manera fácil de hacerlo en Excel, ¿verdad?

Magos ogros
fuente
3
Te equivocas con xlsx . Hay una createSheetfunción que le permite crear nuevas hojas y luego escribirlas en un bucle. Además, las funciones equivalentes en XLConnect están vectorizadas, lo que permite escribir una lista de marcos de datos en varias hojas.
Joran
@joran, createSheet se usa con addDataFrame no write.xlsx? Lo vi anteriormente en el documento, pero no pude entender todo el proceso.
Ogre Magi

Respuestas:

144

Puede escribir en varias hojas con el xlsxpaquete. Solo necesita usar uno diferente sheetNamepara cada marco de datos y debe agregar 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)

Otra opción, una que le brinda más control sobre el formato y dónde se coloca el marco de datos, es hacer todo dentro del código R / xlsx y luego guardar el libro de trabajo al final. Por ejemplo:

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

En caso de que le resulte útil, aquí hay algunas funciones de ayuda interesantes que facilitan la adición de formato, metadatos y otras características a las hojas de cálculo mediante xlsx: http://www.sthda.com/english/wiki/r2excel-read-write -y-formatee-fácilmente-archivos-excel-usando-r-software

eipi10
fuente
xlsxno se ocupa de los números en la primera fila que R pone allí. openxlsxeliminarlos.
Buhtz
1
Agregar row.names=FALSEpara eliminar los nombres de las filas.
eipi10
@EcologyTom Cambié de xlsxa hace openxlsxun tiempo, ya que lo encuentro mucho más intuitivo y también evita la dependencia de Java.
eipi10
Sí, la dependencia de Java me obligó a hacer el mismo cambio. Aunque el código es un poco más largo, es bastante sencillo. Para obtener un método con la openxlsxversión 4.0, consulte mi respuesta complementaria a continuación.
EcologyTom
2
¿Soy solo yo, o la hoja 2 simplemente escribe sobre la hoja 1 cuando se usa este código?
NewBee
88

También puede utilizar la biblioteca openxlsx para exportar varios conjuntos de datos a varias hojas en un solo libro de trabajo. La ventaja de openxlsx sobre xlsx es que openxlsx elimina las dependencias de las bibliotecas java.

Escriba una lista de data.frames en hojas de trabajo individuales usando nombres de lista como nombres de hojas de trabajo.

require(openxlsx)
list_of_datasets <- list("Name of DataSheet1" = dataframe1, "Name of Datasheet2" = dataframe2)
write.xlsx(list_of_datasets, file = "writeXLSX2.xlsx")
Syed
fuente
3
He usado estos paquetes y creo que openxlsxes el más rápido ya que es c ++. XlConnectcomerá tu RAM. Es posible que desee hacer una evaluación comparativa entre xlsxyopenxlsx
Hanjo Jo'burg Odendaal
2
Otra ventaja de ese paquete es que se encarga de la numeración R en la primera fila.
Buhtz
4
Gracias, openxlsx::write.xlsxes el camino a seguir ... me ahorro 11 hojas, cada una trama de datos 20,000x10, es hecho un par de segundos, mientras que xlsx::write.xlsxcon error después añadiendo la segunda hoja conjava.lang.OutOfMemoryError: Java heap space
Djork
Necesitaba agregar el parámetro append=TRUEa write.xlsx para que escriba varias hojas a la vez en un archivo de Excel
mondano
¡Encantador! Creé mi lista como parte de un bucle y solo tuve que inicializarla ( list_of_dfs <- list()) y luego llenarla, usando temp_key y temp_df construidos durante el bucle ( list_of_dfs[[temp_key]] = temp_df). También fue muy rápido al escribir, ¡a pesar de las 16 hojas que necesitaba crear! ¿Alguien ha sido testigo de problemas de memoria durante la creación?
Lionel Trebuchon
30

Hay una nueva biblioteca en la ciudad, de rOpenSci: writexl

Marco de datos portátil y liviano para exportador xlsx basado en libxlsxwriter. No se requiere Java o Excel

Lo encontré mejor y más rápido que las sugerencias anteriores (trabajando con la versión dev):

library(writexl)
sheets <- list("sheet1Name" = sheet1, "sheet2Name" = sheet2) #assume sheet1 and sheet2 are data frames
write_xlsx(sheets, "path/to/location")
Giora Simchoni
fuente
1
¡Gracias! Esto funcionó donde openxlsx no funcionó (no puedo instalar rtools en el trabajo).
Ape
¿Qué versión usas para esto? La descarga de cran predeterminada no admite varias hojas (todavía): 'Error en writexl :: write_xlsx (list (...: El argumento x debe ser un marco de datos o una lista de marcos de datos'
JAD
Como escribí, la versión dev.
Giora Simchoni
@JarkoDubbeldam: instalé el mío desde cran y varias hojas me funcionan (R 3.3.0). Compruebe si los objetos dentro de su lista son data.frames.
Ape
este es uno que realmente funciona. no se pudo instalar xlsx en r.
Cina
20

Muchas buenas respuestas aquí, pero algunas de ellas están un poco anticuadas. Si desea agregar más hojas de trabajo a un solo archivo, este es el enfoque que encuentro que funciona para mí. Para mayor claridad, aquí está el flujo de trabajo para la openxlsxversión 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")

EDITAR

Ahora probé algunas otras respuestas y, de hecho, me gusta mucho la de @ Syed. No explota toda la funcionalidad de, openxlsxpero si desea un método de exportación rápido y fácil, probablemente sea el más sencillo.

EcologíaTom
fuente
8

No estoy familiarizado con el paquete WriteXLS; Generalmente uso 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)

Esto ciertamente se puede vectorizar, como @joran señaló anteriormente, pero solo para generar nombres de hojas dinámicas rápidamente, utilicé un forbucle para demostrar.

Usé el create=TRUEargumento en loadWorkbookya que estaba creando un nuevo archivo .xlsx, pero si su archivo ya existe, entonces no tiene que especificarlo, ya que el valor predeterminado es FALSE.

Aquí hay algunas capturas de pantalla del libro de trabajo creado:

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

nrussell
fuente
1
No he usado XLConnect, ejemplo muy detallado, ¡gracias!
Ogre Magi
De nada, me parece un paquete muy útil. Hay una viñeta bastante buena en CRAN que detalla algunas de las características principales, con un buen ejemplo en la sección 4 que demuestra cómo escribir gráficos R en una hoja de trabajo.
nrussell
5

En caso de que el tamaño de los datos sea pequeño, R tiene muchos paquetes y funciones que se pueden utilizar según sus necesidades.

write.xlsx, write.xlsx2, XLconnect también hacen el trabajo, pero a veces son lentos en comparación con openxlsx .

Entonces, si está lidiando con grandes conjuntos de datos y encontró errores de Java. Sugeriría echar un vistazo a "openxlsx", que es realmente impresionante y reducir el tiempo a 1/12 .

Lo probé todo y finalmente quedé realmente impresionado con el rendimiento de las capacidades de openxlsx.

Estos son los pasos para escribir varios conjuntos de datos en varias hojas.

 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") tiene que ser estático, ya que hace referencia a alguna utilidad de Rtools.

Nota: En caso de que Rtools no esté instalado en su sistema, instálelo primero para una experiencia fluida. aquí está el enlace para su referencia: (elija la versión apropiada)

https://cran.r-project.org/bin/windows/Rtools/ marque las opciones según el enlace a continuación (debe seleccionar todas las casillas de verificación durante la instalación)

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

El paquete openxlsx es realmente bueno para leer y escribir datos enormes desde / en archivos de Excel y tiene muchas opciones para el formato personalizado dentro de Excel.

El hecho interesante es que aquí no tenemos que preocuparnos por la memoria del montón de Java.

ayush varshney
fuente
3

Tuve este problema exacto y lo resolví de esta manera:

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

De esa manera, no tendrá que crear una lista muy larga manualmente si tiene toneladas de marcos de datos para escribir en Excel.

alexmathios
fuente
2
No sé por qué esto está sobrescribiendo la primera hoja de trabajo
Lunalo John
1

Utilizo regularmente el rio empaquetado para exportar todo tipo. Con rio, puede ingresar una lista, nombrar cada pestaña y especificar el conjunto de datos. rio compila otros paquetes de entrada / salida y, para exportar a Excel, usa openxlsx.

library(rio)

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

export(list(sn1 = tempTable1, sn2 = tempTable2, sn3 = tempTable3), filename)
24 lindsey
fuente
0

Para mí, WriteXLSproporciona la funcionalidad que busca. Como no especificaste qué errores devuelve, te muestro un ejemplo:

Ejemplo

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

Explicación

Si xes:

  • una lista de marcos de datos, cada uno está escrito en una sola hoja
  • un vector de caracteres (de objetos R), cada objeto se escribe en una sola hoja
  • algo más, luego vea también lo que dice la ayuda:

Más sobre el uso

?WriteXLS

muestra:

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

Solución

Para su ejemplo, necesitaría recopilar todos los data.frames en una lista durante el ciclo y usarlos WriteXLSdespués de que el ciclo haya terminado.

Información de la sesión

  • R 3.2.4
  • EscribirXLS 4.0.0
setempler
fuente
Este paquete funcionará, pero en mi humilde opinión, trataría de evitar la dependencia de perl (como trataría de evitar la dependencia de Java con xlsx) ya que hace que sea más difícil de configurar
R Yoda
0

Lo hago de esta manera para openxlsx usando la siguiente función

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)
}
makarand kulkarni
fuente
loadWorkbook es clave aquí para abrir archivos existentes
makarand kulkarni
Además, si uno quiere escribir fórmulas para sobresalir, existe una función diferente llamada writeFormula, además, una vez que escribe la fórmula, el archivo debe actualizarse o volverse a abrir, luego guardar y luego cerrar en Excel. la demostración se da aquí [enlace ( stackoverflow.com/questions/46914303/… )
makarand kulkarni
0

Hago esto todo el tiempo, todo lo que hago es

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

y todos esos marcos de datos vienen de aquí

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

obviamente, la rutina de aplicación sería mejor aquí

Suman C
fuente
0

para una versión fácil de usar.

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
fuente
1
¿Podría agregar alguna descripción a esta respuesta para proporcionar un contexto de cómo esto responde a la pregunta?
tshimkus