2015-01-21 63 views
8

我可以傳遞一個StringIO對象以pd.to_csv()就好了:使用Pandas Excelwriter寫入到StringIO對象?

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

但使用Excel時,作家,我有很多的麻煩。

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

返回一個

AttributeError: StringIO instance has no attribute 'rfind' 

我試圖創建一個ExcelWriter對象,而不調用pd.ExcelWriter()但我有一些麻煩。這是我到目前爲止已經試過:

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

但現在我得到一個AttributeError: 'Workbook' object has no attribute 'write_cells'

我如何在Excel格式的數據幀大熊貓保存到一個StringIO對象?

+1

我不確定你可以,至少不容易。 'to_excel'的參數是Excel文件的*路徑,而不是實際的文件對象。爲什麼你要創建一個Excel文件的內存表示呢? – BrenBarn 2015-01-21 02:52:39

+0

使用Flask製作可下載的報告。 – 2015-01-21 16:44:40

回答

16

儘管每個寫入引擎支持StringIO,但熊貓期望ExcelWriter構造函數的文件名路徑。也許這應該作爲Pandas中的bug /功能請求提出。

在這裏同時是利用熊貓xlsxwriter引擎解決方法例如:

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

更新:作爲熊貓0.17的,現在可以到這個更直接做:

# 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') 

請參閱XlsxWriter文檔中的Saving the Dataframe output to a string

+0

謝謝 - 單線解決方案完美工作! – 2015-01-22 01:13:38

+3

這只是在熊貓中添加,請參閱:https://github.com/pydata/pandas/pull/10376。將在0.17.0版本發佈(概念7月底) – Jeff 2015-06-25 19:34:25

5

看着pandas.io.excel源代碼看起來應該不是太多的問題,如果你不介意使用xlwt作爲你的作家。其他引擎可能並不是那麼困難,但xlwt跳出很容易,因爲它的save方法需要一個流或一個文件路徑。

爲了讓熊貓快樂起來,你需要首先傳入文件名,因爲它會根據引擎檢查文件擴展名,以確保它是支持的格式。但是在xlwt引擎的情況下,它只是將文件名填充到對象的路徑屬性中,然後在save方法中使用它。如果將路徑屬性更改爲流,則在調用save方法時,它將很高興地保存到該流中。

下面是一個例子:

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

那是快速,簡單和輕度污染的方式來做到這一點。順便說一句,一個更簡潔的方法是將ExcelWriter(或其中一個現有的子類,如_XlwtWriter)子類化 - 但老實說,在更新路徑屬性時很少涉及,我投票給你展示簡單的方法而不是去稍長的路線。

2

對於那些不使用xlsxwriter作爲他們engine=to_excel這裏是在內存使用openpyxl一個解決方案:

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) 

解釋:ExcelWriter包裝類暴露引擎通過.book財產個人工作簿。對於openpyxl,您可以照常使用Workbook.save方法!