2015-01-21 19 views
8

Ich kann ein StringIO Objekt pd.to_csv() übergeben ganz gut:Schreiben Sie mit Pandas Excelwriter an das StringIO-Objekt?

io = StringIO.StringIO() 
pd.DataFrame().to_csv(io) 

Aber wenn der Schriftsteller Excel, ich bin viel mehr Probleme haben.

io = StringIO.StringIO() 
writer = pd.ExcelWriter(io) 
pd.DataFrame().to_excel(writer,"sheet name") 
writer.save() 

Gibt ein

AttributeError: StringIO instance has no attribute 'rfind' 

Ich versuche, ein ExcelWriter Objekt zu erstellen, ohne pd.ExcelWriter() Aufruf aber einige Probleme habe. Dies ist, was ich bisher versucht:

from xlsxwriter.workbook import Workbook 
writer = Workbook(io) 
pd.DataFrame().to_excel(writer,"sheet name") 
writer.save() 

Aber jetzt bin ich immer ein AttributeError: 'Workbook' object has no attribute 'write_cells'

Wie kann ich eine Pandas Datenrahmen im Excel-Format zu einem StringIO Objekt speichern?

+1

Ich bin mir nicht sicher, ob Sie es können, zumindest nicht leicht. Das Argument für "to_excel" ist ein * Pfad * zu einer Excel-Datei, kein tatsächliches Dateiobjekt. Warum möchten Sie trotzdem eine In-Memory-Darstellung einer Excel-Datei erstellen? – BrenBarn

+0

Flask verwenden, um einen herunterladbaren Bericht zu erstellen. –

Antwort

16

Pandas erwartet einen Dateinamenpfad zu den ExcelWriter-Konstruktoren, obwohl jede der Writer-Engines StringIO unterstützt. Vielleicht sollte das als Bug/Feature-Anfrage in Pandas angesprochen werden.

In der Zwischenzeit ist hier eine Abhilfe Beispiel die Pandas xlsxwriter Engine:

import pandas as pd 
import StringIO 

io = StringIO.StringIO() 

# Use a temp filename to keep pandas happy. 
writer = pd.ExcelWriter('temp.xlsx', engine='xlsxwriter') 

# Set the filename/file handle in the xlsxwriter.workbook object. 
writer.book.filename = io 

# Write the data frame to the StringIO object. 
pd.DataFrame().to_excel(writer, sheet_name='Sheet1') 
writer.save() 
xlsx_data = io.getvalue() 

aktualisieren: Ab Pandas 0,17 es nun möglich ist, dies direkt zu tun:

# Note, Python 2 example. For Python 3 use: output = io.BytesIO(). 
output = StringIO.StringIO() 

# Use the StringIO object as the filehandle. 
writer = pd.ExcelWriter(output, engine='xlsxwriter') 

Siehe auch Saving the Dataframe output to a string in den XlsxWriter-Dokumenten.

+0

Vielen Dank - die Ein-Zeilen-Lösung hat perfekt funktioniert! –

+3

Dies wurde gerade in Pandas hinzugefügt, siehe hier: https://github.com/pydata/pandas/pull/10376. Wird in der Version 0.17.0 sein (Prob Ende Juli) – Jeff

5

Blick auf die pandas.io.excel-Quelle sieht aus wie es sollte kein allzu großes Problem sein, wenn es Ihnen nichts ausmacht mit xlwt als Ihr Schreiber. Die anderen Engines sind vielleicht auch nicht so schwierig, aber xlwt springt so einfach heraus, da seine Speichermethode einen Stream oder einen Dateipfad benötigt.

Sie müssen zunächst einen Dateinamen eingeben, nur um Pandas glücklich zu machen, wie es die Dateinamenerweiterung gegen die Engine überprüft, um sicherzustellen, dass es ein unterstütztes Format ist. Im Fall der xlwt-Engine wird der Dateiname jedoch nur in das Pfadattribut des Objekts eingefügt und dann in der Speichermethode verwendet. Wenn Sie das Pfadattribut in Ihren Stream ändern, wird es beim Speichern der Speichermethode in diesem Stream gespeichert.

Hier ist ein Beispiel:

import pandas as pd 
import StringIO 
import base64 

df = pd.DataFrame.from_csv('http://moz.com/top500/domains/csv') 
xlwt_writer = pd.io.excel.get_writer('xlwt') 
my_writer = xlwt_writer('whatever.xls') #make pandas happy 
xl_out = StringIO.StringIO() 
my_writer.path = xl_out 
df.to_excel(my_writer) 
my_writer.save() 
print base64.b64encode(xl_out.getvalue()) 

Das ist das schnell, einfach und leicht schmutzig Weg, es zu tun. BTW ... ein sauberer Weg, um es zu tun ist, ExcelWriter (oder eine seiner vorhandenen Unterklassen, zB _XlwtWriter) Unterklasse - aber ehrlich gesagt, es ist so wenig in die Aktualisierung der Pfad-Attribut beteiligt, ich habe gewählt, um Ihnen den einfachen Weg zu zeigen, anstatt zu gehen die etwas längere Route.

2

Für diejenigen, die nicht xlsxwriter als ihre engine= für to_excel hier verwendet, ist eine Lösung openpyxl im Speicher zu verwenden:

in_memory_file = StringIO.StringIO() 
xlw = pd.ExcelWriter('temp.xlsx', engine='openpyxl') 
# ... do many .to_excel() thingies 
xlw.book.save(in_memory_file) 
# if you want to read it or stream to a client, don't forget this 
in_memory_file.seek(0) 

Erklärung: die ExcelWriter Wrapper-Klasse, die Motoren einzelne Arbeitsmappe durch die .book Eigenschaft aussetzt.Für openpyxl können Sie dann wie gewohnt die Workbook.save Methode verwenden!